gpt4 book ai didi

c++ - 不同电脑的渲染问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 08:26:56 25 4
gpt4 key购买 nike

所以我正在制作塔防游戏。我与他们共享了一个构建,这样我就可以检查在另一台主机上是否一切正常。

实际发生的是,虽然一切都在我这边完美呈现(在我的 mac/xcode + windows/visual studio 2012 上),但在我 friend 这边,几何图形似乎搞砸了。我屏幕上的每个对象都由一个 VBO 表示,我每次都使用它来渲染到不同的位置。但似乎我的 VBO 具有从所有模型导入的所有几何图形。 (因此塔旁边有树。)

结果如下:

enter image description here (我的电脑)enter image description here (我 friend 的电脑)

到目前为止,我已经设法将此问题调试到一定程度。我可以说这不是我导入模型的方式,因为在将它们作为 VBO 发送到 gpu 之前,我正在创建一个包含所有 vector 的 debug.txt 文件,并且在两台计算机上它们输出相同的值。所以他们的 vector 不会被内存问题或类似的问题弄乱。所以我在想,也许这就是我设置或渲染 VBO 的方式

但最让我印象深刻的是,为什么某些东西在我的电脑上可以正常工作,而在我 friend 的电脑上却不行。我确定的一个区别是我的计算机是一个开发者站(无论这意味着什么),而我 friend 的计算机不是。

这是我的 VBO 加载函数和我的 VBO 绘图函数:我使用 glfw 创建我的窗口和上下文,并包含 glew header 以启用一些较新的 opengl 功能。

void               G4::Renderer::LoadObject(
G4::TILE_TYPES aType,
std::vector<float> &v_data,
std::vector<float> &n_data,
std::vector<float> &t_data,
float scale,
bool has_texture,
unsigned int texture_id
)
{

unsigned int vertices_id, vertices_size, normals_id, texturecoordinates_id;

vertices_size = static_cast<unsigned int>(v_data.size());

glGenBuffers(1, &vertices_id);
glGenBuffers(1, &normals_id);

//::->Vertex array buffer upload.
glBindBuffer(GL_ARRAY_BUFFER, vertices_id);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*v_data.size(), &v_data.front(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

//::->Normal Array buffer upload.
glBindBuffer(GL_ARRAY_BUFFER, normals_id);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*n_data.size(), &n_data.front(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);



if (has_texture)
{
glGenBuffers(1, &texturecoordinates_id);

glBindBuffer(GL_ARRAY_BUFFER, texturecoordinates_id);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*t_data.size(), &(t_data[0]), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}


this->vbos[aType].Update(vertices_id, vertices_size, normals_id, texture_id, texturecoordinates_id, scale, has_texture);



}

绘制代码:

void G4::Renderer::DrawUnit(G4::VBO aVBO, bool drawWithColor, float r, float g, float b, float a)
{
bool model_has_texture = aVBO.HasTexture();

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

if (model_has_texture && !drawWithColor) {
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
}

if (drawWithColor)
{
glColor4f(r, g, b, a);
}

glScalef(aVBO.GetScaleValue(), aVBO.GetScaleValue(), aVBO.GetScaleValue());

glBindBuffer(GL_ARRAY_BUFFER, aVBO.GetVerticesID());
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindBuffer(GL_ARRAY_BUFFER, aVBO.GetNormalsID());
glNormalPointer(GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);


if (model_has_texture && !drawWithColor)
{
glBindTexture(GL_TEXTURE_2D, aVBO.GetTextureID());
glBindBuffer(GL_ARRAY_BUFFER, aVBO.GetTextureCoordsID());
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}

glDrawArrays(GL_TRIANGLES, 0, aVBO.GetVerticesSize());

if (model_has_texture && !drawWithColor) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);

}

glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

}

我没有想法,希望有人能指导我如何进一步调试它。

最佳答案

OpenGL 规范。没有指定当您发出具有比缓冲区存储更多顶点的绘图调用时应该发生的确切行为。这可能在一台机器上正常工作而不在另一台机器上正常工作的原因归结为实现。如果出现这种情况,每个供应商都可以为所欲为,因此渲染伪像可能会出现在 AMD 硬件上,但根本不会出现在 nVIDIA 或 Intel 上。更糟糕的是,当要求绘制太多顶点时,调用 glDrawArrays (...) 实际上不会产生任何错误状态。您肯定需要在来自多个供应商的硬件上测试您的软件以捕获此类错误;谁制造了您计算机中的 GPU 以及驱动程序版本,与操作系统和编译器一样重要。

尽管如此,还是有一些方法可以捕捉到这些愚蠢的错误。 gDEBugger 就是其中之一,还有一个新的 OpenGL 扩展,我将在下面讨论。我更喜欢使用新的扩展,因为根据我的经验,除了已弃用的 API 调用和错误(可以配置 gDEBugger 来监控)之外,该扩展还可以警告您使用低效对齐的数据结构和各种其他可移植性和性能问题。

我想添加一些我用来在我的软件中使用 OpenGL 调试输出的代码,因为这是一个错误行为的示例,它实际上不会生成您可以使用 glGetError (...) 捕获的错误。有时,您可以使用 Debug Output 捕获这些错误(不过,我只是对其进行了测试,这不是其中一种情况)。您将需要一个 OpenGL 调试上下文才能正常工作(设置它的过程高度依赖于平台),但它是一个上下文标志,就像向前/向后兼容和核心一样(glfw 应该让这对您来说很容易)。

x86 平台的自动断点宏


// Breakpoints that should ALWAYS trigger (EVEN IN RELEASE BUILDS) [x86]!
#ifdef _MSC_VER
# define eTB_CriticalBreakPoint() if (IsDebuggerPresent ()) __debugbreak ();
#else
# define eTB_CriticalBreakPoint() asm (" int $3");
#endif


启用 OpenGL 调试输出(需要调试上下文和相对较新的驱动程序,OpenGL 4.x 时代)


// SUPER VERBOSE DEBUGGING!
if (glDebugMessageControlARB != NULL) {
glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
glDebugMessageControlARB (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
glDebugMessageCallbackARB ((GLDEBUGPROCARB)ETB_GL_ERROR_CALLBACK, NULL);
}


一些重要的实用函数,用更有意义的文本替换枚举值


const char*
ETB_GL_DEBUG_SOURCE_STR (GLenum source)
{
static const char* sources [] = {
"API", "Window System", "Shader Compiler", "Third Party", "Application",
"Other", "Unknown"
};

int str_idx =
min ( source - GL_DEBUG_SOURCE_API,
sizeof (sources) / sizeof (const char *) );

return sources [str_idx];
}

const char*
ETB_GL_DEBUG_TYPE_STR (GLenum type)
{
static const char* types [] = {
"Error", "Deprecated Behavior", "Undefined Behavior", "Portability",
"Performance", "Other", "Unknown"
};

int str_idx =
min ( type - GL_DEBUG_TYPE_ERROR,
sizeof (types) / sizeof (const char *) );

return types [str_idx];
}

const char*
ETB_GL_DEBUG_SEVERITY_STR (GLenum severity)
{
static const char* severities [] = {
"High", "Medium", "Low", "Unknown"
};

int str_idx =
min ( severity - GL_DEBUG_SEVERITY_HIGH,
sizeof (severities) / sizeof (const char *) );

return severities [str_idx];
}

DWORD
ETB_GL_DEBUG_SEVERITY_COLOR (GLenum severity)
{
static DWORD severities [] = {
0xff0000ff, // High (Red)
0xff00ffff, // Med (Yellow)
0xff00ff00, // Low (Green)
0xffffffff // ??? (White)
};

int col_idx =
min ( severity - GL_DEBUG_SEVERITY_HIGH,
sizeof (severities) / sizeof (DWORD) );

return severities [col_idx];
}


我的调试输出回调(有点乱,因为它在我的软件中以不同颜色打印每个字段)


void
ETB_GL_ERROR_CALLBACK (GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
GLvoid* userParam)
{
eTB_ColorPrintf (0xff00ffff, "OpenGL Error:\n");
eTB_ColorPrintf (0xff808080, "=============\n");

eTB_ColorPrintf (0xff6060ff, " Object ID: ");
eTB_ColorPrintf (0xff0080ff, "%d\n", id);

eTB_ColorPrintf (0xff60ff60, " Severity: ");
eTB_ColorPrintf ( ETB_GL_DEBUG_SEVERITY_COLOR (severity),
"%s\n",
ETB_GL_DEBUG_SEVERITY_STR (severity) );

eTB_ColorPrintf (0xffddff80, " Type: ");
eTB_ColorPrintf (0xffccaa80, "%s\n", ETB_GL_DEBUG_TYPE_STR (type));

eTB_ColorPrintf (0xffddff80, " Source: ");
eTB_ColorPrintf (0xffccaa80, "%s\n", ETB_GL_DEBUG_SOURCE_STR (source));

eTB_ColorPrintf (0xffff6060, " Message: ");
eTB_ColorPrintf (0xff0000ff, "%s\n\n", message);

// Force the console to flush its contents before executing a breakpoint
eTB_FlushConsole ();

// Trigger a breakpoint in gDEBugger...
glFinish ();

// Trigger a breakpoint in traditional debuggers...
eTB_CriticalBreakPoint ();
}



由于我实际上无法让您的情况触发调试输出事件,我想我至少会展示一个我能够触发的事件示例。这不是您可以使用 glGetError (...) 捕获的错误,也不是与此相关的错误。但这肯定是一个 draw call 问题,如果不使用此扩展,您可能会在项目期间完全忘记 :)

OpenGL Error:============= Object ID: 102 Severity:  Medium Type:      Performance Source:    API Message:   glDrawElements uses element index type 'GL_UNSIGNED_BYTE' that is not optimal for the current hardware configuration; consider using 'GL_UNSIGNED_SHORT' instead.

关于c++ - 不同电脑的渲染问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18064988/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com