0

我最近开始为我正在开发的引擎构建某种延迟渲染管道,但我一直坚持从深度重建世界位置。我查看了很多示例,其中解释了您需要世界位置纹理或深度纹理,然后才能使用正确的距离和方向计算光。

我的问题是所谓的位置纹理可能是世界位置似乎没有给我正确的数据。因此,我试图找到获得世界位置的替代方法,有些人建议我应该使用深度纹理,但那又如何呢?

为了更清楚,这张图片显示了我当前存储的纹理:

延迟渲染纹理 位置(左上)、正常(右上)、漫反射(左下)和深度(右下)。

对于光通,我尝试使用一种在第一通中使用效果很好的方法。当我尝试使用完全相同的变量对光通使用相同的方法时,它会停止工作。

这是我的几何顶点着色器:

#version 150

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;

in vec4 in_Position;
in vec3 in_Normal;
in vec2 in_TextureCoord;

out vec3 pass_Normals;
out vec4 pass_Position;
out vec2 pass_TextureCoord;
out vec4 pass_Diffuse;

void main(void) {

        pass_Position = viewMatrix * modelMatrix * in_Position;
    pass_Normals = (viewMatrix * modelMatrix * vec4(in_Normal, 0.0)).xyz;
    pass_Diffuse = vec4(1,1,1,1);
    gl_Position = projectionMatrix * pass_Position;

}

几何片段着色器:

#version 150 core

uniform sampler2D texture_diffuse;

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;

in vec4 pass_Position;
in vec3 pass_Normals;
in vec2 pass_TextureCoord;
in vec4 pass_Diffuse;

out vec4 out_Diffuse;
out vec4 out_Position;
out vec4 out_Normals;

void main(void) {
    out_Position = pass_Position;
    out_Normals = vec4(pass_Normals, 1.0);
    out_Diffuse = pass_Diffuse;
}

光顶点着色器:

#version 150

in vec4 in_Position;
in vec2 in_TextureCoord;

out vec2 pass_TextureCoord;

void main( void )
{
    gl_Position = in_Position;
    pass_TextureCoord = in_TextureCoord;

}

光片段着色器:

#version 150 core

uniform sampler2D texture_Diffuse;
uniform sampler2D texture_Normals; 
uniform sampler2D texture_Position;
uniform vec3 cameraPosition;
uniform mat4 viewMatrix;

in vec2 pass_TextureCoord;

out vec4 frag_Color;

void main( void )
{
    frag_Color = vec4(1,1,1,1);
    vec4 image = texture(texture_Diffuse,pass_TextureCoord);
    vec3 position = texture( texture_Position, pass_TextureCoord).rgb;
    vec3 normal = texture( texture_Normals, pass_TextureCoord).rgb;
    frag_Color = image;


    vec3 LightPosition_worldspace = vec3(0,2,0);

    vec3 vertexPosition_cameraspace = position;
    vec3 EyeDirection_cameraspace = vec3(0,0,0) - vertexPosition_cameraspace;

    vec3 LightPosition_cameraspace = ( viewMatrix * vec4(LightPosition_worldspace,1)).xyz;
    vec3 LightDirection_cameraspace = LightPosition_cameraspace + EyeDirection_cameraspace;

    vec3 n = normal;
    vec3 l = normalize( LightDirection_cameraspace );

    float cosTheta = max( dot( n,l ), 0);

    float distance = distance(LightPosition_cameraspace, vertexPosition_cameraspace);

    frag_Color = vec4((vec3(10,10,10) * cosTheta)/(distance*distance)), 1);
    }

最后,这是当前的结果: 意外的结果

所以我的问题是,是否有人可以解释结果或我应该如何获得正确的结果。我也将感谢该地区的良好资源。

4

1 回答 1

4

是的,使用深度缓冲区重建位置是您最好的选择。这将显着降低内存带宽/存储需求。现代硬件偏向于进行着色器计算而不是内存获取(并非总是如此),并且重建每个片段的位置所需的指令总是比从具有足够精度的纹理中获取位置更快地完成。现在,您只需要了解硬件深度缓冲区存储的内容(了解深度范围和透视分布的工作原理)就可以了。

我没有看到任何尝试从您的问题列表中的代码中的深度缓冲区重建世界/视图空间位置。您只是从存储视图空间中位置的缓冲区中采样。由于您在此示例中没有执行重建,因此问题与对视图空间位置的采样有关......您能否更新您的问题以包含 G-Buffer 纹理的内部格式。特别是,您是否使用可以表示负值的格式(这是表示位置所必需的,否则负值被限制为 0)。

最后一点,您的位置也是view-space而不是world-space,训练有素的眼睛可以通过左下角位置缓冲区中的颜色为黑色的方式立即看出这一点。如果你想调试你的位置/法线,你应该将采样的颜色偏置/缩放到可见范围:

([-1.0, 1.0] -> [0.0, 1.0])  // Vec = Vec * 0.5 + 0.5

如果您想更有效地存储普通 G-Buffer(例如,在 8 位定点纹理而不是浮点中),您可能需要在输出一些缓冲区时执行此操作。

于 2014-01-05T23:18:32.073 回答