用于透视的倒置几何 gBuffer 位置。正字法可以吗?
Inverted geometry gBuffer positions for perspective. Orthographic is ok?
我有一个延迟渲染器,它似乎工作正常,深度、颜色和阴影正确显示。然而,位置缓冲区对于正交很好,而在使用透视投影时几何显示 'inverted'(或禁用深度)。
我得到以下正字法缓冲区输出。
最终 'shaded' 图片目前看起来正确。
然而,当我使用透视投影时,我得到以下缓冲区...
最终图像很好,虽然我现在没有包含任何位置缓冲区信息(N.B 目前只做 'headlight' 阴影)
虽然最终图像看起来是正确的,但我的位置缓冲区似乎忽略了深度缓冲区...(代码中没有 glDisable(GL_DEPTH_TEST)。
深度和正常缓冲区对我来说看起来不错,只是 'position' 缓冲区似乎忽略了深度?渲染管道在正交和透视方面完全相同,唯一的区别是投影矩阵。
我使用 glm::ortho
和 glm::perspective
并根据场景 AABB 动态计算我的 near/far 剪裁距离。对于正交我的 near/far 分别是 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();
}
这里是 'second pass' 着色器,用于可视化位置缓冲区...
#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);
}
我还没有使用位置缓冲区数据,我知道我可以重建它而不必将它们存储在另一个缓冲区中,但是由于其他原因这些位置对我有用,我想知道为什么它们是为了透视而出来的吗?
你实际写在position buffer里的是clipspace坐标
Position = P * VM * vec4(InPoint, 1.0);
剪辑space坐标是Homogeneous coordinates and transformed to the normaliced device cooridnate (which is a Cartesian coordinate by a Perspective divide。
ndc = gl_Position.xyz / gl_Position.w;
在正交投影中,w
分量为 1,但在透视投影中,w
分量包含一个值,该值取决于(笛卡尔坐标)的 [=15=] 分量(深度) ) 查看 space 坐标。
我建议将标准化的设备坐标存储到位置缓冲区,而不是剪辑 space 坐标。例如:
gBufferPosition = vec4(Position.xyz / Position.w, 1.0);
我有一个延迟渲染器,它似乎工作正常,深度、颜色和阴影正确显示。然而,位置缓冲区对于正交很好,而在使用透视投影时几何显示 'inverted'(或禁用深度)。
我得到以下正字法缓冲区输出。
最终 'shaded' 图片目前看起来正确。
然而,当我使用透视投影时,我得到以下缓冲区...
最终图像很好,虽然我现在没有包含任何位置缓冲区信息(N.B 目前只做 'headlight' 阴影)
虽然最终图像看起来是正确的,但我的位置缓冲区似乎忽略了深度缓冲区...(代码中没有 glDisable(GL_DEPTH_TEST)。
深度和正常缓冲区对我来说看起来不错,只是 'position' 缓冲区似乎忽略了深度?渲染管道在正交和透视方面完全相同,唯一的区别是投影矩阵。
我使用 glm::ortho
和 glm::perspective
并根据场景 AABB 动态计算我的 near/far 剪裁距离。对于正交我的 near/far 分别是 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();
}
这里是 'second pass' 着色器,用于可视化位置缓冲区...
#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);
}
我还没有使用位置缓冲区数据,我知道我可以重建它而不必将它们存储在另一个缓冲区中,但是由于其他原因这些位置对我有用,我想知道为什么它们是为了透视而出来的吗?
你实际写在position buffer里的是clipspace坐标
Position = P * VM * vec4(InPoint, 1.0);
剪辑space坐标是Homogeneous coordinates and transformed to the normaliced device cooridnate (which is a Cartesian coordinate by a Perspective divide。
ndc = gl_Position.xyz / gl_Position.w;
在正交投影中,w
分量为 1,但在透视投影中,w
分量包含一个值,该值取决于(笛卡尔坐标)的 [=15=] 分量(深度) ) 查看 space 坐标。
我建议将标准化的设备坐标存储到位置缓冲区,而不是剪辑 space 坐标。例如:
gBufferPosition = vec4(Position.xyz / Position.w, 1.0);