解決渲染過程中產生的問題--隱藏面消除解決方案

一. 渲染過程中產生的問題
  • 隱藏面消除:3D場景的繪製會出現立體圖形的可見部分和不可見部分,對觀察者不可見的部分需要隱藏不渲染。
二. 隱藏面消除的解決方案
  1. 油畫算法
    場景中物體距離觀察者有遠有近,先繪製遠的再繪製近的,重合的部分距離近的會覆蓋遠的,就解決了不可見部分需要隱藏的問題。

  2. 正背面剔除(Face Culling)

  • 油畫算法使用的場景是物體有遠有近不交叉,但是當場景中多個物體有疊加交叉的時候油畫算法就無法處理了。

  • 試想,我們在觀察一個立方體的時候是最多能看到3個面的,其他看不見的面可以不繪製,這樣OpenGL的渲染性能也會提高。

  • 讓OpenGL繪製朝向觀察者的正面,丟棄背面,以提高片元着色器的性能,我們只需告訴OpenGL需要繪製的圖形的正面和背面,通過分析頂點數據的順序來確定圖形的正面和背面。默認情況下,在觀察者角度頂點順序爲順時針方向時是背面,頂點順序爲逆時針方向時是正面。



    如圖:灰色三角形頂點順序爲1-2-3,注意左右兩個三角形頂點順序不一樣,觀察者在立體圖形的右側,右邊的三角形頂點方向爲逆時針是正面,左邊的三角形頂點方向爲順時針是背面。
    當觀察者觀察的角度和方向發生變化時,正面和背面也會跟着變化,所以正面和背面是由三角形的頂點順序和觀察者的方向共同決定的。

  • OpenGL中正背面的設置
    OpenGL中默認是背面剔除,下面方法可以開啓正面剔除和指定正背面

// 開啓正面剔除,默認是背面剔除
void glEnable(GL_CULL_FACE);

// 關閉正面剔除,默認是背面剔除
void glDisable(GL_CULL_FACE);

// 設置需要剔除的正面/背面
void glCullFace(GLenum mode); // mode參數爲: GL_FRONT,GL_BACK,GL_FRONT_AND_BACK ,默認GL_BACK

// 設置頂點順序確定正面,一般情況不進行修改,使用默認順時針爲背面逆時針爲正面
void glFrontFace(GLenum mode); // mode參數爲: GL_CW,GL_CCW,默認值:GL_CCW

// 剔除正面實現
glCullFace(GL_BACK); 
glFrontFace(GL_CW);

// 或者一個方法實現
glCullFace(GL_FRONT);
  1. Z-buffer方法(深度緩衝區DepthBuffer)
    通過計算圖形像素點的深度值與緩衝區中的深度值的比較來確定是否繪製的方法來解決隱藏面消除的問題。
  • 深度緩衝區(DepthBuffer)存儲像素的深度信息,顏色緩衝區(ColorBuffer)存儲像素的顏色信息。

  • 深度測試:

在決定是否繪製一個物體表面時,首先要將表面對應的像素的深度值與當前深度緩衝區存儲的值進行比較,如果大於深度緩衝區中的值則丟棄,否則利用這個像素對應的深度值和顏色值分別更新深度緩衝區和顏色緩衝區,這個過程稱爲深度測試。

  • 深度值計算:

深度值一般由16位、24位或者32位值表示,通常是24位。位數越⾼的話,深度的精確度越好。深度值的範圍在[0,1]之間,值越⼩表示越靠近觀察者,值越⼤表示遠離觀察者。

深度緩衝區存儲場景中所有對象的z值,將觀察者看到的內容的z值與深度緩衝區中存儲的z值進行比較,來確定需要繪製的部分。
視圖空間中的z值是投影到平面上的距離,這個值不在[0,1]範圍內,需要通過下面的方程來轉換,從而進行與深度緩衝區中的值比較。
下面的 (線性) 方程把 z 值轉換爲 0.0 和 1.0 之間的值:



(far和near是提供到投影矩陣設置可見視圖的遠近值)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章