Keine gewünschten Ergebnisse bei der Implementierung von SSAO

12

Nachdem ich das verzögerte Rendern implementiert hatte, versuchte ich mein Glück mit einer SSAO-Implementierung unter Verwendung dieses Lernprogramms . Leider bekomme ich nichts, was aussieht wie SSAO, Sie können mein Ergebnis unten sehen.

fehlgeschlagen ssao atempt

Sie können sehen, dass sich ein seltsames Muster bildet und es keine Okklusionsschattierung gibt, wo dies erforderlich ist (dh zwischen den Objekten und auf dem Boden). Die von mir implementierten Shader folgen:


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

Ich zeichne ein Vollbild-Quad und übergebe Tiefen- und Normaltexturen. Normalen sind in RGBA16F, wobei der Alpha-Kanal für den AO-Faktor im Unschärfepass reserviert ist. Ich speichere die Tiefe in einem nichtlinearen Tiefenpuffer (32F) und stelle die lineare Tiefe wieder her mit:


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

wo projAB.ywird berechnet als:

Bildbeschreibung hier eingeben

und projAB.xals:

Bildbeschreibung hier eingeben

Diese leiten sich aus der Matrix glm :: perspective (gluperspective) ab. z_n und z_f sind die nahen und fernen Clipabstände.

Wie in dem Link beschrieben, den ich oben gepostet habe, erstellt die Methode Proben in einer Halbkugel mit höherer Verteilung nahe der Mitte. Anschließend werden zufällige Vektoren aus einer Textur verwendet, um die Hemisphäre zufällig um die Z-Richtung zu drehen und sie schließlich entlang der Normalen am angegebenen Pixel auszurichten. Da das Ergebnis verrauscht ist, folgt auf den SSAO-Durchgang ein Weichzeichnungsdurchgang.

Wie auch immer, meine Positionsrekonstruktion scheint nicht falsch zu sein, da ich auch versucht habe, das Gleiche zu tun, wobei jedoch die Position von einer Textur übergeben wurde, anstatt rekonstruiert zu werden.

Ich habe auch versucht, mit dem Radius, der Rauschtexturgröße und der Anzahl der Samples und mit verschiedenen Texturformaten zu spielen, ohne Erfolg. Aus irgendeinem Grund ändert sich beim Ändern des Radius nichts.

Hat jemand irgendwelche Vorschläge? Was könnte schief gehen?

Grieverheart
quelle
Ich denke, die Unschärfe muss ein separater Pass sein. Können Sie einen Screenshot Ihres Shaders ohne die Unschärfe veröffentlichen?
Knight666
Der Blur-Pass ist separat, Sie können den Pre-Blur- Screenshot überprüfen .
Grieverheart

Antworten:

6

Ich habe das Problem gefunden. Es war ein wirklich dummer Fehler, ich wusste nicht, dass Sie angeben müssen glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);, um die richtigen Tiefenwerte zu erhalten, und daher habe ich die Tiefenwerte nicht abgetastet. Jetzt bekomme ich einen schönen SSAO-Effekt:

Bildbeschreibung hier eingeben

Grieverheart
quelle
Fühlen Sie sich frei, dies als die richtige Antwort zu markieren, damit die Leute wissen, dass Sie Ihre Lösung gefunden haben: P
markieren,
Ja, leider muss ich eines Tages warten, um meine Antwort als richtig kennzeichnen zu können: S.
Grieverheart
Mein Fehler, habe die Zeitstempel nicht überprüft.
SomeGuy