翻译:
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自动做透视划分:
g l _ p o s i t i o n = v e c 4 ( x , y , z , w ) ; o u t = ( x / w y / w z / w ) gl\_position =vec4(x,y,z,w); \\ out = \begin{pmatrix} x /w \\ y / w \\ z / w \end{pmatrix} gl_position=vec4(x,y,z,w);out=x/wy/wz/w
那么 z n = z / w z_n=z/w zn=z/w 就是点在vertex Shader最终输出的gl_position 做透视划分后的向量的z值.
所以 z n z_n zn的计算公式为:

z_n = -(Az_e + B) / z_e; // z_n in [-1, 1]
z_b = 0.5
z_n + 0.5; // z_b in [0, 1]

z_b 是把透视划分后的点从[-1,1]映射到[0,1](深度缓存值范围).

以上是片段着色器每个点的深度值计算原理。在片段着色器clip一下透明值,就可以解决绘制一个物体时被遮挡的问题。例如我只要视野内球体内部.其截面法线垂直于我的视线:
这里写图片描述

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐