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 - 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