OpenGL基本错误总结

论坛 期权论坛 脚本     
匿名网站用户   2020-12-20 04:16   31   0
  1. constchar*getGLErrorInfo(interrorId)
  2. {
  3. switch(errorId)
  4. {
  5. caseGL_INVALID_ENUM:
  6. return("GLInvalidEnum\n");
  7. caseGL_INVALID_VALUE:
  8. return("GLInvalidValue\n");
  9. caseGL_INVALID_OPERATION:
  10. return("GLInvalidOperation\n");
  11. caseGL_OUT_OF_MEMORY:
  12. return("GLOutOfMemory\n");
  13. //caseGL_INVALID_FRAMEBUFFER_OPERATION:
  14. //return("GLInvalidFrameBufferOperation\n");
  15. caseGL_STACK_OVERFLOW:
  16. return("GLStackOverflow\n");
  17. caseGL_STACK_UNDERFLOW:
  18. return("GLStackUnderflow\n");
  19. //caseGL_TABLE_TOO_LARGE:
  20. //return("GLTableTooLarge\n");
  21. };
  22. return"GLUndefinedError";
  23. }

错误示例1:

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

错误示例2:

画线条(即使只画一根线条)时候应该传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:

  1. voidDisplay()
  2. {
  3. //Clearframebuffer
  4. glClearColor(0,0,0,1);
  5. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  6. glEnable(GL_DEPTH_TEST);
  7. //Setlight
  8. glEnable(GL_LIGHTING);
  9. glEnable(GL_LIGHT0);
  10. //Rotateanddrawshape
  11. glPushMatrix();
  12. glTranslatef(0.5f,-0.3f,0.0f);
  13. //根据四元数计算旋转矩阵
  14. ConvertQuaternionToMatrix(g_Rotation,mat);
  15. glMultMatrixf(mat);
  16. //缩放操作
  17. glScalef(g_Zoom,g_Zoom,g_Zoom);
  18. //调用显示列表绘制物体
  19. glCallList(g_CurrentShape);
  20. glPopMatrix();
  21. //绘制UI
  22. TwDraw();
  23. //Presentframebuffer
  24. glutSwapBuffers();
  25. //RecallDisplayatnextframe
  26. glutPostRedisplay();
  27. }
  28. voidTwDraw()
  29. {
  30. //BeginDraw
  31. glMatrixMode(GL_TEXTURE);glPushMatrix();glLoadIdentity();
  32. glMatrixMode(GL_PROJECTION);glPushMatrix();glLoadIdentity();
  33. glMatrixMode(GL_MODELVIEW);glPushMatrix();glLoadIdentity();
  34. //DrawUI
  35. //EndDraw
  36. glMatrixMode(GL_MODELVIEW);glPopMatrix();
  37. glMatrixMode(GL_PROJECTION);glPopMatrix();
  38. glMatrixMode(GL_TEXTURE);glPopMatrix();//将矩阵堆栈状态设为GL_TEXTURE
  39. }


上面代码段代码,在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/

状态紊乱导致的错误示例5:

批量绘制地图上的道路,数据量很大,当批处理阈值小于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状态并没有被禁掉。

遇到过最隐晦的错误

重叠区域像素抖动特别厉害:

左图红色矩形框,右图更加严重楼块跟地图根本区分不开,视觉效果十分差!
正常的效果应该是:

出问题时透视参数:gluPerspective(45, aspect, 0.001, 10000.0);
楼块,地图本身绘制是没有问题的。问题出在gluPerspective函数设置视棱锥过长,超过了OpenGL深度缓冲区的精度,导致每次片源的深度测试结果不一致(不在支持重入性)。一般深度缓冲区是16byte buffer。精度是0-65536。
错误示例5:
网友的疑问,模型缩小时会有黑块闪烁问题,

放大后则没有问题
他的视棱锥设置:

0.1到30000,范围为300000,一般深度缓冲区16位精度也就32768。。。

Alpha混合错误:

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


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

dst{ RGBA } = src{ RGBA } * srcA + dst{ RGBA } * (1 - srcA) 气泡主体部分也混合了底图背景(灰色调),所以整体结果是灰色调。

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

dst{ RGBA } = src{ RGBA } * 1 + dst{ RGBA } * (1 - srcA) 既有抠图效果,又保持气泡色调不变。

同样的BUG再次出现:

左下角为原始纹理,黑色部分RGBA全部为0,;左上角混合模式为(srcA, 1-srcA),结果描边处看上去有种脏的感觉;右上角混合模式为(1, 1-srcA) 结果十分干净、明朗!

其他错误:

模型顶点和照相机相对位置不对,导致看不到效果。

开了光照,但是模型顶点没有设置法线 导致绘制失败。

后续继续更新中。。。

修改记录:

2012/7/29 - 增加错误示例3、4。

2013/7/9 -增加深度缓冲区错误。

2013/9/6 - 增加alpha混合错误

2013/11/23 -增加状态紊乱错误示例5

http://blog.csdn.net/ryfdizuo/article/details/7593637/

OpenGL编程低级错误 + 常见问题简答http://blog.csdn.net/augusdi/article/details/23763451

OpenGL Common Mistakehttps://www.opengl.org/wiki/Common_Mistakes

Avoiding 16 Common OpenGL Pitfallshttps://www.opengl.org/archives/resources/features/KilgardTechniques/oglpitfall/

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP