有没有人跟我一起经历过关于 OpenGL 中的 ssao 的事情?

问题描述

大部分着色器代码都遵循LearnopenGL的说明。我可以确保传入着色器的 g 缓冲区和噪声数据是正确的。看起来像是某种错位,但我真的想不通为什么会这样。

misplace ssao

#version 450 core
out float OUT_FragColor;

in vec2 TexCoords;

uniform sampler2D g_position;
uniform sampler2D g_normal;
uniform sampler2D noise_texture;

struct CameraInfo
{
    vec4 position;
    mat4 view;
    mat4 projection;
};
layout(std140,binding = 0) uniform Camera
{
    CameraInfo camera;
};


float radius = 0.5;
float bias = 0.025;

uniform int noise_tex_size;

void main()
{
    const vec2 noise_scale = vec2(1280.0/noise_tex_size,720.0/noise_tex_size); 

    vec3 frag_pos = texture(g_position,TexCoords).xyz;
    vec3 normal = normalize(texture(g_normal,TexCoords).xyz);
    vec3 random_vec = normalize(texture(noise_texture,TexCoords * noise_scale).xyz);   

    vec3 tangent = normalize(random_vec - normal * dot(random_vec,normal));   
    vec3 bitangent = cross(normal,tangent);    
    mat3 TBN = mat3(tangent,bitangent,normal);

    float occlusion = 0.f;

    for(int i = 0; i < sample_array.length(); ++i)
    {
        vec3 sample_pos = TBN * sample_array[i].xyz;
        sample_pos = frag_pos + sample_pos * radius;    
        
        vec4 offset = vec4(sample_pos,1.0);
        offset = camera.projection * offset; // from view to clip-space
        offset.xyz /= offset.w; // perspective divide ?????
        offset.xyz = offset.xyz * 0.5 + 0.5; // transform to range 0.0 - 1.0
        float sample_depth = texture(g_position,offset.xy).z;

        float range_check = smoothstep(0.f,1.f,radius / abs(frag_pos.z - sample_depth));  
        occlusion += (sample_depth >= sample_pos.z + bias ? 1.0 : 0.0) * range_check; //ignore sample points that too near the origin point
    }

    

    occlusion = 1.f - (occlusion / sample_array.length());  
    OUT_FragColor = occlusion;
}

解决方法

将 g_postion 和 g_normal 转化为模型空间

FragPos = (camera.view * vec4(WorldPos,1.0)).xyz;
mat4 normal_matrix = camera.view * mat4(transpose(inverse(mat3(model))));   
FragNormal = mat3(normal_matrix) * normal;