2011-06-12 83 views
1

在我的OpenGL代碼中存在一個奇怪的行爲。我想在地上畫一塊地毯。同一平面內的另一個多邊形內的多邊形

在下面的代碼中,如果GROUND_SIZE大於2071且CARPET_HEIGHT小於0.0003,則不會繪製較小的多邊形。繪圖順序不會更改生成的圖像。

#include <GL/glut.h> 

const int GROUND_SIZE = 3000; 
const bool GROUND_FIRST = true; 
const float CARPET_HEIGHT = 0.0003; 

void carpet(){ 
    glColor3f(1.0,0.0,0.0); 
    glBegin(GL_QUADS); 
     glNormal3f(0,1,0); 
     glVertex3f(-1.0, -1.0, CARPET_HEIGHT); 
     glVertex3f(1.0, -1.0, CARPET_HEIGHT); 
     glVertex3f(1.0, 1.0, CARPET_HEIGHT); 
     glVertex3f(-1.0, 1.0, CARPET_HEIGHT); 
    glEnd(); 
} 
void ground(){ 
    glColor3f(0.0,0.7,0.0); 
    glBegin(GL_QUADS); 
     glNormal3f(0,1,0); 
     glVertex3f(-GROUND_SIZE, -GROUND_SIZE, 0); 
     glVertex3f(GROUND_SIZE, -GROUND_SIZE, 0); 
     glVertex3f(GROUND_SIZE, GROUND_SIZE, 0); 
     glVertex3f(-GROUND_SIZE, GROUND_SIZE, 0); 
    glEnd(); 
} 

void draw(){ 
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    if (GROUND_FIRST) { 
     ground(); 
     carpet(); 
    } 
    else { 
     carpet(); 
     ground(); 
    } 

    glutSwapBuffers(); 
} 

int main(){ 

    int argc = 1; char* argv[] = { (char*)"" }; 
    glutInit(&argc, argv); 

    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); 
    glutInitWindowPosition(100, 50); 
    glutInitWindowSize(640, 640); 
    glutCreateWindow("Window"); 

    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    glEnable(GL_DEPTH_TEST); 

    glClearColor(0.0f, 1.0f, 1.0f, 1.0f); 

    glutDisplayFunc(draw); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(45, 1, 0.1, 1000.0); 
    gluLookAt(0.0, -5.0, 1.0, 0.0f, 0.0f, 1.0f, 0,0,1); 

    glutMainLoop(); 
    return 0; 
} 

我想了解OpenGL用來決定是否會在同一平面內的另一個多邊形內繪製多邊形的規則。

謝謝

回答

4

首先,幾個代碼錯誤。

切勿將gluLookAt矩陣放在GL_PROJECTION矩陣中。這可以用你的照明來玩havok。 gluLookAt的矩陣應該是您在GL_MODELVIEW中放置的第一個矩陣。

將GL_MODELVIEW矩陣作爲默認矩陣也是一個好主意。也就是說,任何切換到GL_PROJECTION(或其中一個紋理矩陣)的代碼都會在完成其他矩陣後立即切換回GL_MODELVIEW。

最後,調用glClearDepth和glDepthFunc總是很好的形式。默認值(1.0和GL_LESS)正是你想要的,但對這些事情明確表示總是很好的。這樣,您不必通過搜索規範來確保默認值是您的想法。

現在,就主要問題。

這個規則只是深度緩衝區的規則。這是簡單和複雜的同時。

首先,有兩個飛機的斜率。雖然它們在世界空間中確實具有相同的斜率,但它們在投影后空間中不一定具有相同的斜率。這是由於從世界空間轉換到後投影空間的各種計算中的浮點錯誤。其次,如果它們之間的Z-差異太小,那麼可能發生的是它們會得到相同的Z值。或者由於浮點錯誤,地毯甚至可能具有較小的Z值。

我想如果你爲視角設置動畫,你會看到地毯飛機進出視野。

你可以做的一件簡單的事情是總是在地平面後面畫地毯,並使用GL_LEQUAL作爲glDepthFunc。這可能無法100%的時間,再次由於浮點錯誤。

下一步是使用多邊形偏移。這樣做會使某個基元的Z值偏離某個固定值。它是如何工作的細節是討論過的技術(檢查OpenGL規範,如果你很好奇),但其基本思想是,你carpet函數應該是這個樣子:

glEnable(GL_POLYGON_OFFSET_FILL); //Activates polygon offsets for filled triangles. 
glPolygonOffset(0, 2); //The 2 is just for safety's sake; 1 ought to be enough. 
//Draw the carpet 
glDisable(GL_POLYGON_OFFSET_FILL); //Turn off polygon offsetting. 
+0

我通常建議設置在任何矩陣操作之前的適當矩陣模式,而不是依賴於事物被正確地切換回來。 – datenwolf 2011-06-14 09:43:37

相關問題