C++ 不同计算机的渲染问题
所以我要做一个简短的塔防游戏。我与他们共享了一个构建,因此我可以检查在另一台主机上是否一切正常 而实际上发生的事情是,虽然我这边(在我的mac/xcode+windows/visual studio 2012上)的所有渲染都非常完美,但在我的朋友这边,几何图形似乎是一团糟。屏幕上的每个对象都由VBO表示,我每次都使用VBO渲染到不同的位置。但我的VBO似乎拥有从所有模型导入的所有几何体。(因此塔的侧面有一棵树。) 结果如下: (我的电脑)(我朋友的电脑) 到目前为止,我已经成功地调试了这个问题,直到某一点。我可以看出这不是我导入模型的方式,因为我正在创建一个包含所有向量的debug.txt文件,然后将它们作为VBO发送到gpu,并且在两台计算机上输出相同的值。所以我相信他们的向量不会被内存问题或类似的事情搞砸。所以我想也许这就是我设置或渲染VBO的方式 然而,最让我印象深刻的是,为什么我的电脑上的东西可以工作,而我朋友的电脑上却没有。我可以肯定的是,我的电脑是一个开发者工作站(不管这意味着什么),而我朋友的电脑不是 这是我的VBO加载功能和VBO绘图功能: 我使用glfw来创建我的窗口和上下文,并包含glew头来启用一些较新的opengl函数C++ 不同计算机的渲染问题,c++,opengl,C++,Opengl,所以我要做一个简短的塔防游戏。我与他们共享了一个构建,因此我可以检查在另一台主机上是否一切正常 而实际上发生的事情是,虽然我这边(在我的mac/xcode+windows/visual studio 2012上)的所有渲染都非常完美,但在我的朋友这边,几何图形似乎是一团糟。屏幕上的每个对象都由VBO表示,我每次都使用VBO渲染到不同的位置。但我的VBO似乎拥有从所有模型导入的所有几何体。(因此塔的侧面有一棵树。) 结果如下: (我的电脑)(我朋友的电脑) 到目前为止,我已经成功地调试了这个问题,
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);
}
我没有主意了,我希望有人能指导我如何进一步调试它。在与我的朋友进行了进一步调试和多次试用后,我设法找到了问题。这花了我整整两天的时间才弄明白,其实这只是一个愚蠢的错误
glDrawArrays(GL_TRIANGLES, 0, aVBO.GetVerticesSize());
上面的代码不获取顶点大小(作为点),而是作为存储在那里的浮点总数。所以一切都乘以3。添加a/3解决了这个问题
所以我假设,由于总点数乘以3倍,vbo从gpu上存储的其他vbo“窃取”了数据。(因此,树模型堆叠到我的塔)
但我还不明白的是,为什么在我的电脑上一切都很好,而在其他电脑上却没有。正如我在最初的问题中所说的,我的计算机实际上是一个开发站,而我的朋友不是。
如果有人能很好地解释为什么这种影响不会在我身上重现,我会很乐意接受他的回答,作为我问题的解决方案
谢谢你在与朋友们进行了进一步的调试和多次试用后,我终于找到了问题所在。这花了我整整两天的时间才弄明白,其实这只是一个愚蠢的错误
glDrawArrays(GL_TRIANGLES, 0, aVBO.GetVerticesSize());
上面的代码不获取顶点大小(作为点),而是作为存储在那里的浮点总数。所以一切都乘以3。添加a/3解决了这个问题
所以我假设,由于总点数乘以3倍,vbo从gpu上存储的其他vbo“窃取”了数据。(因此,树模型堆叠到我的塔)
但我还不明白的是,为什么在我的电脑上一切都很好,而在其他电脑上却没有。正如我在最初的问题中所说的,我的计算机实际上是一个开发站,而我的朋友不是。
如果有人能很好地解释为什么这种影响不会在我身上重现,我会很乐意接受他的回答,作为我问题的解决方案
谢谢OpenGL规范没有指定当您使用比缓冲区存储更多的顶点发出绘制调用时应该发生的确切行为。这可以在一台机器上正常工作而不能在另一台机器上正常工作的原因归结于实现。如果出现这种情况,每个供应商都可以自由地做任何他们想做的事情,因此渲染工件可能会出现在AMD硬件上,但在nVIDIA或Intel上根本不会出现。更糟糕的是,当要求绘制太多顶点时,调用
glDrawArrays(…)
实际上不会生成错误状态。您肯定需要在来自多个供应商的硬件上测试您的软件,以捕获此类错误;谁在您的计算机中制造GPU以及驱动程序版本,与操作系统和编译器一样重要
尽管如此,还是有办法抓住这些愚蠢的错误。gDEBugger就是其中之一,下面我将讨论一个新的OpenGL扩展。我更喜欢使用新的扩展,因为根据我的经验,除了不推荐的API调用和错误(gDEBugger可以配置为监视这些错误)之外,该扩展还可以警告您使用效率低下的数据结构以及其他各种可移植性和性能问题
我想添加一些我用来在我的软件中使用OpenGL调试输出的代码,因为这是一个错误行为的示例,它实际上不会生成一个可以通过glGetError(…)
捕获的错误。有时,您可以通过调试输出捕捉到这些错误(尽管我刚刚测试了它,但这不是那种情况)。您需要一个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 era)
用更有意义的文本替换枚举值的一些重要实用程序函数
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];
}
我的调试输出回调(有些混乱,因为它在我的软件中以不同的颜色打印每个字段)
因为我无法让您的情况触发调试输出事件,所以我想我至少应该展示一个我能够触发的事件的示例。这不是一个可以用
glGetError(…)
捕获的错误,也不是一个错误
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 ();
}
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.