翻譯:
Real depth in OpenGL / GLSL - Before I Forget…
有一個需求:用openGL做球形貼圖。需要前後移動相機觀測球體,當相機位置超出球體時看到的內容從球體內表面變成球體外表面。
方案一:超出時,計算哪些片段屬於前半球,不要渲染這些片段;
方案二:在片段着色器用深度值判斷;
首先看一下這個公式.
A = -(zFar + zNear) / (zFar - zNear);
B = -2*zFar*zNear / (zFar - zNear);
A 和B分別是視錐體透視投影(perspective)的投影矩陣的3行3列(3,3)和4列(3,4)。
通常線性照相機模型最後Project矩陣左乘頂點向量後gl_position值變成:
[...,..., Az+B, -z]
然後頂點shader跑完,openGL自動做透視劃分:
那麼 就是點在vertex Shader最終輸出的gl_position 做透視劃分後的向量的z值.
所以的計算公式爲:
z_n = -(Az_e + B) / z_e; // z_n in [-1, 1]
z_b = 0.5z_n + 0.5; // z_b in [0, 1]
z_b 是把透視劃分後的點從[-1,1]映射到[0,1](深度緩存值範圍).
以上是片段着色器每個點的深度值計算原理。在片段着色器clip一下透明值,就可以解決繪製一個物體時被遮擋的問題。例如我只要視野內球體內部.其截面法線垂直於我的視線: