设为首页 加入收藏

TOP

OpenGL错误总结(一)
2014-11-24 00:58:12 来源: 作者: 【 】 浏览:9
Tags:OpenGL 错误 总结

const char* getGLErrorInfo(int errorId)
{
switch (errorId)
{
case GL_INVALID_ENUM:
return ("GL Invalid Enum\n");
case GL_INVALID_VALUE:
return ("GL Invalid Value\n");
case GL_INVALID_OPERATION:
return ("GL Invalid Operation\n");
case GL_OUT_OF_MEMORY:
return ("GL Out Of Memory\n");
//case GL_INVALID_FRAMEBUFFER_OPERATION:
// return ("GL Invalid FrameBuffer Operation\n");
case GL_STACK_OVERFLOW:
return ("GL Stack Overflow\n");
case GL_STACK_UNDERFLOW:
return ("GL Stack Underflow\n");
//case GL_TABLE_TOO_LARGE:
// return ("GL Table Too Large\n");
};


return "GL Undefined Error";
}


double viewMatrix[16];


glGetDoublev(GL_MODELVIEW, viewMatrix); 编译不会报错,但是获取的viewMatrix失败。通过glGetError 获得错误码是GL_INVALID_ENUM 0x0500。


正确写法glGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix);


GL_PROJECTION_MATRIX / GL_PROJECTION


获取视口信息直接GL_VIEWPORT


画线条(即使只画一根线条)时候应该传GL_LINES, 不小心传了GL_LINE,编译也不会报错,但就是没效果。


画点GL_POINTS,四边形GL_QUADS。不小心写了GL_QUAD 编译报错 使用了未定义的枚举变量。


GL_LINE,GL_POINT,opengl中用来定义多边形的绘制模式,还有GL_FILL模式。


错误示例3:


在BeginDraw函数中call函数glPushAttrib,保存属性,在EndDraw函数中忘记glPopAttrib,检查opengl状态时,输出错误码为0x01,差了opengl手册居然没有这个错误码的说明。。。


错误示例4:


void Display()
{
// Clear frame buffer
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glEnable(GL_DEPTH_TEST);


// Set light
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);


// Rotate and draw shape
glPushMatrix();


glTranslatef(0.5f, -0.3f, 0.0f);


// 根据四元数计算旋转矩阵
ConvertQuaternionToMatrix(g_Rotation, mat);
glMultMatrixf(mat);


// 缩放操作
glScalef(g_Zoom, g_Zoom, g_Zoom);


// 调用显示列表绘制物体
glCallList(g_CurrentShape);
glPopMatrix();


// 绘制UI
TwDraw();


// Present frame buffer
glutSwapBuffers();


// Recall Display at next frame
glutPostRedisplay();
}


void TwDraw()
{
// BeginDraw
glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity();
glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity();
glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity();


// Draw UI


// EndDraw
glMatrixMode(GL_MODELVIEW); glPopMatrix();
glMatrixMode(GL_PROJECTION); glPopMatrix();
glMatrixMode(GL_TEXTURE); glPopMatrix(); // 将矩阵堆栈状态设为GL_TEXTURE
}


上面代码段代码,在BeginDraw操作保存当前的各种矩阵堆栈,EndDraw操作还原之前的矩阵堆栈,都没问题。关键是TwDraw函数放到Display函数中以后,二者结合起来运行一次以后就会有问题。而且问题十分奇怪,无论Display函数中如何glMultMatrix,如何glScale,如何glTranslate ,物体最终的位置都没有变化。


因为什么呢?
答案的根因是因为opengl是一个状态机。。。TwDraw的EndDraw操作将当前操作的矩阵堆栈设为 纹理堆栈,因此Display函数第一次执行,可能继承了来自ReShape函数中的状态,当前矩阵堆栈是模型视图,但是一旦TwDraw函数执行,就会十分“隐晦”地将当前的堆栈状态设为GL_TEXTURE,所以第二次Display函数中的glPushMatrix,glMultMatrix,glScale,glTranslate,glPop都是操作纹理堆栈,对物体的位置一点作用也没有。


参见opengl官网,Avoiding 16 Common OpenGL Pitfalls
的第三点:http://www.opengl.org/archives/resources/features/KilgardTechniques/oglpitfall/


批量绘制地图上的道路,数据量很大,当批处理阈值小于2500时所有道路可以正常绘制,当批处理阈值大于2500时就会中断。。而且是crash是必现的。不知错在哪里Zz。卡了很几天,google了好久,http://www.gamedev.net/topic/456605-opengl-crashes-in-gldrawelements/ 15楼zedz方法给了灵感:glDrawElements之前,禁掉纹理、顶点、颜色数组,绘制完再开启,此时道路没绘制出来也没有crash。说明问题出在顶点数组状态上,经过排查没有关闭GL_TEXTURE_COORD_ARRAY。道路采用颜色数组绘制,glVertexPointer只传了颜色和位置信息,而绘制完地图瓦片后GL_TEXTURE_COORD_ARRAY状态并没有被禁掉。


图1是原始纹理图片,图2是错误的显示结果(设计师不满意要求修改),图3是修改后的效果与原始气泡样式保持一致。



图2采用的混合模式时:glBlend( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 混合公式为


dst{ RGBA } = src{ RGBA } * srcA + dst{ RGBA

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇OpenGL错误和性能Tips 下一篇OpenGL中的FBO如何使用模板缓冲区

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: