裁剪空间不是NDC
投影变换后得到裁剪空间坐标。在顶点和片段着色器中间OpenGL最自动执行透视除法和视口变换得到屏幕空间。
(Vertex Shader) => Clip Space
=> (透视除法) => NDC
=> (视口变换) => Screen Space
=> (Fragment Shader)
而NDC是一个长宽高取值范围为[-1,1]的立方体:
屏幕空间深度
depth是非线性的,和1/z成正比。深度值在片段着色器中[0,1]之间。
线性深度
将屏幕空间中非线性的深度值变换至线性深度值的完整片段着色器如下:
out vec4 FragColor;
float near = 0.1;
float far = 100.0;
float LinearizeDepth(float depth)
{
float z = depth * 2.0 - 1.0; // back to NDC
return (2.0 * near * far) / (far + near - z * (far - near));
}
void main()
{
float depth = LinearizeDepth(gl_FragCoord.z) / far; // 为了演示除以 far
FragColor = vec4(vec3(depth), 1.0);
}```