java - 获取延迟渲染光 channel 的世界位置

标签 java opengl glsl lighting deferred-rendering

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

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

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

Deferred rendering textures 位置(左上)、正常(右上)、漫反射(左下)和深度(右下)。

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

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

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

最后,这是当前结果: Unexpected result

所以我的问题是是否有人可以解释结果或者我应该如何做才能得到正确的结果。我也希望获得该领域的优质资源。

最佳答案

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

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

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

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

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

关于java - 获取延迟渲染光 channel 的世界位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20940195/

相关文章:

java - 如何按先数字字母后数字对字符串列表进行排序

c++ - 在 0x1000A456 (glut32.dll) OpenGL 抛出异常

opengl - Freeglut、OpenGL 和内存

ios - 如何在 iOS 的 OpenGL ES 中正确线性化深度?

ios - 动画着色器值

c# - 我怎样才能避免错误地更新当前对象上的另一个对象?

java - 如何将具有 70 个字段的 java 对象发送到具有相同字段数的对象的 pl sql 过程

Java:何时在方法后面使用括号

c++ - 将 YUV 写入文件会导致重复的帧

ios - OpenGL ES2 : syntax error when using "layout" keyword in vertex shader(iOS)