8

我有一对 GLSL 着色器,可以为我提供场景中对象的深度图。我现在得到的是每个像素到相机的距离。我需要的是获得从像素到相机平面的距离。让我用一张小图来说明

   *          |--*
  /           |
 /            |
C-----*       C-----*
 \            |
  \           |
   *          |--*

3 个星号是像素,C 是相机。星号线是“深度”。在第一种情况下,我得到了从像素到相机的距离。第二,我希望得到每个像素到平面的距离。

必须有一种方法可以通过使用一些投影矩阵来做到这一点,但我很难过。

这是我正在使用的着色器。注意 eyePosition 是 camera_position_object_space。

顶点着色器:

void main() {
    position = gl_Vertex.xyz;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

像素着色器:

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);
}
4

3 回答 3

16

你真的在努力做到这一点。只需将事物转换为相机空间,然后从那里开始工作。

varying float distToCamera;

void main()
{
    vec4 cs_position = glModelViewMatrix * gl_Vertex;
    distToCamera = -cs_position.z;
    gl_Position = gl_ProjectionMatrix * cs_position;
}

在相机空间(一切都与相机的位置/方向相关的空间)中,到顶点的平面距离只是 Z 坐标的负值(负 Z 越高越远)。

所以你的片段着色器甚至不需要eyePosition;“深度”直接来自顶点着色器。

于 2013-04-21T22:46:19.957 回答
3

投影后的 W 分量包含进入场景的正交深度。您不需要为此使用单独的模型视图和投影矩阵:

varying float distToCamera;

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    distToCamera = gl_Position.w;
}
于 2013-05-30T13:58:49.260 回答
1

你暗示的是正交投影。您当前正在使用透视投影。实际上,您没有像素到相机的真实距离,而是视锥体中像素的 z 位置。在渲染的纹理上,最终的 z 深度在 [-1,1] 范围内被渲染,它描述了它在 NDC 空间中的 z 分量。

如您所知,您的所有点都使用透视投影“朝向”(实际上是在近平面上)投影到相机。您想要的是将它们正交投影到近平面。这个链接详细描述了两个投影矩阵,矩阵的最终结果在底部。您的着色器应该能够很好地处理新的投影矩阵。只要确保您的 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)。

于 2013-04-21T15:03:09.740 回答