Non ottenere i risultati desiderati con l'implementazione di SSAO


12

Dopo aver implementato il rendering differito, ho tentato la fortuna con un'implementazione SSAO usando questo tutorial . Sfortunatamente, non sto ottenendo nulla che assomigli a SSAO, puoi vedere il mio risultato di seguito.

tentativo ssao fallito

Puoi vedere che si sta formando uno strano modello e non c'è ombra di occlusione dove ci deve essere (cioè tra gli oggetti e sul terreno). Gli shader che ho implementato seguono:


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

Traccio un quad a schermo intero e passo trame di profondità e normali. Le normali sono in RGBA16F con il canale alfa riservato al fattore AO nel passaggio sfocatura. Conservo la profondità in un buffer di profondità non lineare (32F) e ripristino la profondità lineare usando:


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

dove projAB.yè calcolato come:

inserisci qui la descrizione dell'immagine

e projAB.xcome:

inserisci qui la descrizione dell'immagine

Questi sono derivati ​​dalla matrice glm :: prospettiva (gluperspective). z_n e z_f sono la distanza di clip vicina e lontana.

Come descritto nel link che ho pubblicato in alto, il metodo crea campioni in un emisfero con una distribuzione più elevata vicino al centro. Quindi utilizza vettori casuali da una trama per ruotare in modo casuale l'emisfero attorno alla direzione Z e infine lo orienta lungo la normale in corrispondenza del pixel dato. Poiché il risultato è rumoroso, un passaggio di sfocatura segue il passaggio SSAO.

Comunque, la ricostruzione della mia posizione non sembra essere sbagliata poiché ho anche provato a fare lo stesso, ma con la posizione passata da una trama invece di essere ricostruita.

Ho anche provato a giocare con il raggio, la dimensione della trama del rumore e il numero di campioni e con diversi tipi di formati di trama, senza fortuna. Per qualche ragione quando si cambia il raggio, non cambia nulla.

Qualcuno ha qualche suggerimento? Cosa potrebbe andare storto?


Penso che la sfocatura debba essere un passaggio separato. Puoi pubblicare uno screenshot del tuo shader senza la sfocatura?
knight666,

Il passaggio sfocatura è separato, puoi controllare lo screenshot pre-sfocatura .
Grieverheart,

Risposte:


6

Ho trovato il problema. È stato un errore davvero stupido, non sapevo che dovevi specificare glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);per ottenere i valori di profondità corretti e quindi non stavo campionando i valori di Profondità. Ora ho un bel effetto SSAO:

inserisci qui la descrizione dell'immagine


Sentiti libero di contrassegnare questa come la risposta corretta in modo che le persone sappiano che hai trovato la tua soluzione: P
SomeGuy

Sì, purtroppo devo aspettare un giorno per poter contrassegnare la mia risposta come corretta: S.
Grieverheart,

Errore mio, non ho controllato i timestamp.
SomeGuy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.