Ne pas obtenir les résultats souhaités avec la mise en œuvre de SSAO


12

Après avoir implémenté le rendu différé, j'ai tenté ma chance avec une implémentation SSAO en utilisant ce tutoriel . Malheureusement, je ne reçois rien qui ressemble à SSAO, vous pouvez voir mon résultat ci-dessous.

échec de la tentative de ssao

Vous pouvez voir qu'il y a un motif étrange qui se forme et qu'il n'y a pas d'ombrage d'occlusion là où il doit y en avoir (c'est-à-dire entre les objets et au sol). Les shaders que j'ai mis en place sont les suivants:


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

Je dessine un quad en plein écran et passe des textures Profondeur et Normal. Les normales sont en RGBA16F avec le canal alpha réservé au facteur AO dans la passe de flou. Je stocke la profondeur dans un tampon de profondeur non linéaire (32F) et récupère la profondeur linéaire en utilisant:


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

projAB.yest calculé comme:

entrez la description de l'image ici

et projAB.xcomme:

entrez la description de l'image ici

Celles-ci sont dérivées de la matrice glm :: perspective (gluperspective). z_n et z_f sont la distance du clip proche et lointain.

Comme décrit dans le lien que j'ai posté en haut, la méthode crée des échantillons dans un hémisphère avec une distribution plus élevée près du centre. Il utilise ensuite des vecteurs aléatoires à partir d'une texture pour faire pivoter l'hémisphère de manière aléatoire autour de la direction Z et l'oriente finalement le long de la normale au pixel donné. Le résultat étant bruyant, une passe de flou suit la passe SSAO.

Quoi qu'il en soit, ma reconstruction de position ne semble pas être fausse puisque j'ai également essayé de faire la même chose mais avec la position passée d'une texture au lieu d'être reconstruite.

J'ai également essayé de jouer avec le rayon, la taille de la texture du bruit et le nombre d'échantillons et avec différents types de formats de texture, sans succès. Pour une raison quelconque lors du changement de rayon, rien ne change.

Est-ce que quelqu'un a des suggestions? Qu'est-ce qui pourrait mal tourner?


Je pense que le flou doit être un passage séparé. Pouvez-vous publier une capture d'écran de votre shader sans le flou?
knight666

La passe de flou est séparée, vous pouvez vérifier la capture d'écran avant le flou .
Grieverheart

Réponses:


6

J'ai trouvé le problème. C'était une erreur vraiment stupide, je ne savais pas que vous deviez spécifier glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);pour obtenir les valeurs de profondeur correctes et donc, je n'échantillonnais pas les valeurs de profondeur. Maintenant, j'obtiens un bel effet SSAO:

entrez la description de l'image ici


N'hésitez pas à marquer cela comme la bonne réponse pour que les gens sachent que vous avez trouvé votre solution: P
SomeGuy

Oui, malheureusement, je dois attendre un jour pour pouvoir signaler ma réponse comme correcte: S.
Grieverheart

Mon erreur, je n'ai pas vérifié les horodatages.
SomeGuy
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.