Não obtendo os resultados desejados com a implementação do SSAO

12

Depois de implementar a renderização adiada, tentei a sorte com uma implementação do SSAO usando este tutorial . Infelizmente, não estou recebendo nada parecido com SSAO, você pode ver meu resultado abaixo.

tentativa ssao com falha

Você pode ver que há algum padrão estranho se formando e não há sombreamento de oclusão onde precisa haver (ou seja, entre os objetos e no chão). Os shaders que implementei seguem:


#VS
#version 330 core

uniform mat4 invProjMatrix;

layout(location = 0) in vec3 in_Position;
layout(location = 2) in vec2 in_TexCoord;

noperspective out vec2 pass_TexCoord;
smooth out vec3 viewRay;

void main(void){
    pass_TexCoord = in_TexCoord;
    viewRay = (invProjMatrix * vec4(in_Position, 1.0)).xyz;
    gl_Position = vec4(in_Position, 1.0);
}

#FS
#version 330 core

uniform sampler2D DepthMap;
uniform sampler2D NormalMap;
uniform sampler2D noise;

uniform vec2 projAB;
uniform ivec3 noiseScale_kernelSize;
uniform vec3 kernel[16];
uniform float RADIUS;
uniform mat4 projectionMatrix;

noperspective in vec2 pass_TexCoord;
smooth in vec3 viewRay;

layout(location = 0) out float out_AO;

vec3 CalcPosition(void){
    float depth = texture(DepthMap, pass_TexCoord).r;
    float linearDepth = projAB.y / (depth - projAB.x);
    vec3 ray = normalize(viewRay);
    ray = ray / ray.z;
    return linearDepth * ray;
}

mat3 CalcRMatrix(vec3 normal, vec2 texcoord){
    ivec2 noiseScale = noiseScale_kernelSize.xy;
    vec3 rvec = texture(noise, texcoord * noiseScale).xyz;
    vec3 tangent = normalize(rvec - normal * dot(rvec, normal));
    vec3 bitangent = cross(normal, tangent);

    return mat3(tangent, bitangent, normal);
}

void main(void){

    vec2 TexCoord = pass_TexCoord;
    vec3 Position = CalcPosition();
    vec3 Normal = normalize(texture(NormalMap, TexCoord).xyz);

    mat3 RotationMatrix = CalcRMatrix(Normal, TexCoord);

    int kernelSize = noiseScale_kernelSize.z;

    float occlusion = 0.0;

    for(int i = 0; i < kernelSize; i++){
        // Get sample position
        vec3 sample = RotationMatrix * kernel[i];
        sample = sample * RADIUS + Position;
        // Project and bias sample position to get its texture coordinates
        vec4 offset = projectionMatrix * vec4(sample, 1.0);
        offset.xy /= offset.w;
        offset.xy = offset.xy * 0.5 + 0.5;
        // Get sample depth
        float sample_depth = texture(DepthMap, offset.xy).r;
        float linearDepth = projAB.y / (sample_depth - projAB.x);
        if(abs(Position.z - linearDepth ) < RADIUS){
            occlusion += (linearDepth <= sample.z) ? 1.0 : 0.0;
        }
    }
    out_AO = 1.0 - (occlusion / kernelSize);
}

Eu desenho um quad em tela cheia e passo as texturas Depth e Normal. As normais estão em RGBA16F com o canal alfa reservado para o fator AO na passagem de desfoque. Armazeno a profundidade em um buffer de profundidade não linear (32F) e recupero a profundidade linear usando:


float linearDepth = projAB.y / (depth - projAB.x);

onde projAB.yé calculado como:

insira a descrição da imagem aqui

e projAB.xcomo:

insira a descrição da imagem aqui

Estes são derivados da matriz glm :: perspective (gluperspective). z_n e z_f são a distância do clipe próximo e distante.

Conforme descrito no link que publiquei na parte superior, o método cria amostras em um hemisfério com maior distribuição perto do centro. Em seguida, ele usa vetores aleatórios de uma textura para girar o hemisfério aleatoriamente em torno da direção Z e finalmente o orienta ao longo do normal no pixel especificado. Como o resultado é barulhento, um passe de desfoque segue o passe do SSAO.

De qualquer forma, minha reconstrução de posição não parece estar errada, pois também tentei fazer o mesmo, mas com a posição passada de uma textura em vez de ser reconstruída.

Eu também tentei brincar com o Radius, tamanho da textura do ruído e número de amostras e com diferentes tipos de formatos de textura, sem sorte. Por alguma razão, ao alterar o raio, nada muda.

Alguém tem alguma sugestão? O que poderia dar errado?

Grieverheart
fonte
Eu acho que o desfoque precisa ser um passe separado. Você pode postar uma captura de tela do seu shader sem desfocar?
precisa
O passe de desfoque é separado, você pode verificar a captura de tela antes do desfoque .
Grieverheart

Respostas:

6

Eu encontrei o problema Foi um erro realmente estúpido, eu não sabia que você precisava especificar glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);para obter os valores corretos de profundidade e, portanto, não estava amostrando os valores de profundidade. Agora eu recebo um bom efeito SSAO:

insira a descrição da imagem aqui

Grieverheart
fonte
Sinta-se à vontade para sinalizar isso como a resposta correta para que as pessoas saibam que você encontrou sua solução: P
SomeGuy
Sim, infelizmente tenho que esperar um dia para poder sinalizar minha resposta como correta: S.
Grieverheart
Meu erro, não verifiquei os carimbos de data e hora.
usar o seguinte código