天天看點

【學習OpenGL】(五)——隐藏表面消除(深度測試)

深度測試是一種有效的用于隐藏表面消除的技巧,OpenGL提供了一些函數,允許在幕後完成這個任務。

它的概念非常簡單:當一個像素被繪制時,它将被設定一個值(稱為Z值),以表示它和觀察者之間的距離。以後,當這個螢幕需要繪制另一個像素時,新像素的值就會與原先已經存在的那個像素進行比較。如果新像素的Z值更高,它就更靠近觀察者,是以位于以前那個像素的前面。如果新像素的Z值更低,則它必須位于原先那個像素的後面,而不能遮住前面的那個像素。

為了啟用深度測試,隻要簡單的調用

glEnable(GL_DEPTH_TEST);
           

我們通過以下函數繪制一大一小兩個球

void DrawBigRedSphere()
{
    GLfloat mat_specular[] = { 1.0, 0.0, 0.0, 1.0 };
    GLfloat mat_shininess[] = { 50.0 };
    GLfloat mat_ambient[] = { 1.0, 0.0, 0.0, 1.0 };
    GLfloat mat_diffuse[] = { 1.0, 0.0, 0.0, 1.0 };

    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

    glutSolidSphere(, , ); 
}

void DrawSmallBlueSphere()
{
    GLfloat mat_specular[] = { 0.0, 0.0, 1.0, 1.0 };
    GLfloat mat_shininess[] = { 50.0 };
    GLfloat mat_ambient[] = { 0.0, 0.0, 1.0, 1.0 };
    GLfloat mat_diffuse[] = { 0.0, 0.0, 1.0, 1.0 };

    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

    glutSolidSphere(, , );
}
           

DrawBigRedSphere繪制的是大的紅球,DrawSmallBlueSphere繪制的是小的藍球,繪制的時候都采用預設坐标,即繪制在螢幕的中央,并且Z軸也不動,那麼,從理論上來講,大球會包含小球,小球就被大球遮掩了,我們顯示要的應該也是這種效果。

看一下未開啟深度測試情況下的情況我們先繪制大球,再繪制小球的和用相反順序再繪制的情形:

代碼如下:

void SceneShow(GLvoid)        
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
);    

    glPushMatrix();
    glTranslatef(-, , );
    DrawBigRedSphere();
    DrawSmallBlueSphere();
    glPopMatrix();

    glPushMatrix();
    glTranslatef(, , );
    DrawSmallBlueSphere();
    DrawBigRedSphere();
    glPopMatrix();

    glFlush();
}  
           
【學習OpenGL】(五)——隐藏表面消除(深度測試)

我們會觀察到很明顯的繪制順序導緻的問題,左邊的圖因為先繪制大球再繪制小球,小的籃球竟然覆寫掉了應該在其外部的紅球。實際使用中,我們可以都自己判斷,然後用右邊的正确繪制方式,随着圖形的增多,會增加一定的計算量,OpenGL提供的深度測試就是為我們提供了更簡便高效的方式,事實上,由于OpenGL使用的方式因為可以在測試後,直接繪制出最終圖形而忽略繪制被覆寫掉的圖形,效率上比覆寫繪制會更高一些(需要硬體支援)。

上述代碼,僅僅需要添加一行,

glEnable(GL_DEPTH_TEST);
           

以啟用深度測試,效果大不一樣:

【學習OpenGL】(五)——隐藏表面消除(深度測試)

繼續閱讀