歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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";
}

錯誤示例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:

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/

狀態紊亂導致的錯誤示例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

Copyright © Linux教程網 All Rights Reserved