倒置的几何gBuffer透视图位置。正交可以吗?

问题描述 投票:3回答:1

我有一个延迟渲染器,看起来可以正常工作,深度,颜色和阴影正确显示。但是,位置缓冲区适合正交投影,而使用透视投影时,几何显示为“倒置”(或禁用深度)。

我将获得以下拼写的缓冲区输出。

depth

normals

positions

最终的“阴影”图像当前看起来正确。

enter image description here

但是,当我使用透视投影时,会出现以下缓冲区...

enter image description here

enter image description here

enter image description here

最终图像很好,尽管目前我没有合并任何位置缓冲区信息(N.B目前仅进行'大灯'阴影)

enter image description here

虽然最终图像看起来正确,但是深度缓冲区似乎被我的位置缓冲区忽略了……(代码中没有glDisable(GL_DEPTH_TEST)。

深度和普通缓冲区在我看来还可以,只是'位置'缓冲区似乎忽略了深度?渲染管道的正交和透视图完全相同,唯一的不同是投影矩阵。

我使用glm::orthoglm::perspective,并根据AABB场景实时计算我的近/远剪切距离。对于正交,我的近/远分别是1和11.4734,对于透视,我的近/远分别是11.0875和22.5609 ...宽度和高度值相同,透视投影的fov是45。

在绘制任何几何图形之前,我确实有这些调用...

glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

我用于将不同的图层合成为渲染管线的一部分。

我在这里做错什么了吗?还是我误会了什么?

这是我的着色器...gBuffer的顶点着色器...

#version 430 core

layout (std140) uniform MatrixPV
{
    mat4 P;
    mat4 V;
};

layout(location = 0) in vec3 InPoint;
layout(location = 1) in vec3 InNormal;
layout(location = 2) in vec2 InUV;

uniform mat4 M;

out vec4 Position;
out vec3 Normal;
out vec2 UV;

void main()
{
    mat4 VM = V * M;
    gl_Position = P * VM * vec4(InPoint, 1.0);
    Position = P * VM * vec4(InPoint, 1.0);
    Normal = mat3(M) * InNormal;
    UV = InUV;
}

gBuffer的片段着色器...

#version 430 core

layout(location = 0) out vec4 gBufferPicker;
layout(location = 1) out vec4 gBufferPosition;
layout(location = 2) out vec4 gBufferNormal;
layout(location = 3) out vec4 gBufferDiffuse;

in vec3 Normal;
in vec4 Position;

vec4 Diffuse();
uniform vec4 PickerColour;

void main()
{
    gBufferPosition = Position;
    gBufferNormal = vec4(Normal.xyz, 1.0);
    gBufferPicker = PickerColour;
    gBufferDiffuse = Diffuse();
}

这是“第二遍”着色器,用于可视化位置缓冲区...

#version 430 core

uniform sampler2D debugBufferPosition;

in vec2 UV;
out vec4 frag;

void main()
{
    vec3 val = texture(debugBufferPosition, UV).xyz;
    frag = vec4(val.xyz, 1.0);
}

我还没有使用位置缓冲区数据,我知道我可以重建它而不必将它们存储在另一个缓冲区中,但是由于其他原因,这些位置对我很有用,我想知道为什么它们会出来因为它们是透视图?

c++ opengl glsl glm-math opengl-4
1个回答
1
投票

您实际上在位置缓冲区中写的是剪辑空间坐标

Position = P * VM * vec4(InPoint, 1.0);

剪辑空间坐标是Homogeneous coordinates,并转换为归一化设备坐标(通过Cartesian coordinatePerspective divide

ndc = gl_Position.xyz / gl_Position.w;

在正交投影时,w分量为1,但在透视投影时,w分量包含一个值,该值取决于(笛卡尔)视图空间坐标的z分量(深度)。

我建议将标准化的设备坐标存储到位置缓冲区,而不是剪辑空间坐标。例如:

gBufferPosition = vec4(Position.xyz / Position.w, 1.0);
© www.soinside.com 2019 - 2024. All rights reserved.