我有一对GLSL着色器,可以为我提供场景中对象的深度贴图。我现在得到的是每个像素到相机的距离。我需要的是获得从像素到相机平面的距离。让我用一点画来说明
* |--*
/ |
/ |
C-----* C-----*
\ |
\ |
* |--*
3个星号是像素,C是相机。星号的线条是“深度”。在第一种情况下,我得到像素到相机的距离。在第二个中,我希望得到每个像素到平面的距离。
必须有办法通过使用一些投影矩阵来做到这一点,但我很难过。
以下是我正在使用的着色器。请注意,eyePosition是camera_position_object_space。
顶点着色器:
void main() {
position = gl_Vertex.xyz;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
Pixel Shader:
uniform vec3 eyePosition;
varying vec3 position;
void main(void) {
vec3 temp = vec3(1.0,1.0,1.0);
float depth = (length(eyePosition - position*temp) - 1.0) / 49.0;
gl_FragColor = vec4(depth, depth, depth, 1.0);
}
答案 0 :(得分:11)
你真的想以艰难的方式做到这一点。只需将物品转换为相机空间,然后从那里开始工作。
varying float distToCamera;
void main()
{
vec4 cs_position = glModelViewMatrix * gl_Vertex;
distToCamera = -cs_position.z;
gl_Position = gl_ProjectionMatrix * cs_position;
}
在相机空间(一切都相对于相机的位置/方向的空间)中,到顶点的平面距离只是Z坐标的负值(较高的负Z更远)。
所以你的片段着色器甚至不需要eyePosition
; “深度”直接来自顶点着色器。
答案 1 :(得分:2)
投影后的W分量包含进入场景的正交深度。您不需要为此使用单独的模型视图和投影矩阵:
varying float distToCamera;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
distToCamera = gl_Position.w;
}
答案 2 :(得分:1)
你所暗示的是正投影。您目前正在使用透视投影。实际上,你没有从像素到相机的真实距离,而是像素在视锥体中的z位置。在渲染纹理上,渲染[-1,1]范围内的最终z深度,描述其在NDC空间中的z分量。
根据您的理解,使用透视投影将所有点投射到(相当于近平面)相机上。你想要的是将它们正交地投射到近平面上。 This link详细描述了两个投影矩阵,矩阵的最终结果位于底部。您的着色器应该能够很好地处理新的投影矩阵。只需确保按照上面的建议计算您的MVP矩阵。
注意,正交投影可能并不代表渲染场景的深度。如果使用透视投影将场景渲染到屏幕上,并且想要每个像素的深度,则应相应地使用相同的透视投影。因此,如果场景使用相同的投影,或者如果某些算法需要与屏幕上看到的场景无关的深度信息,则使用正交投影渲染深度将非常有用。
此外,我建议您查看核心OpenGL配置文件(3.x),因为您似乎正在使用已弃用的功能(gl_Vertex,gl_ModelViewProjectionMatrix等)。自己设置所有缓冲区和着色器稍微多做一些工作,但最终会得到回报。
修改强>
实际上,在你的评论之后,我明白你想要什么。目前尚不清楚你是否想在同一个调用中渲染它们,为此我在片段着色器中建议这样的东西:
uniform mat4 orthographicMatrix;
varying vec3 position;
void main(void) {
vec4 clipSpace = orthographicMatrix * vec4(position, 1.0);
gl_FragColor = vec4(clipSpace.zzz, 1.0);
}
请注意,您不必进行w除法,因为正投影已经是线性的(因此w设置为1)。