No obtener los resultados deseados con la implementación de SSAO


12

Después de haber implementado el renderizado diferido, probé suerte con una implementación SSAO usando este Tutorial . Desafortunadamente, no obtengo nada que se parezca a SSAO, puedes ver mi resultado a continuación.

intento fallido de ssao

Puede ver que se está formando un patrón extraño y no hay sombreado de oclusión donde sea necesario (es decir, entre los objetos y en el suelo). Los sombreadores que implementé son los siguientes:


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

Dibujo un quad de pantalla completa y paso texturas de profundidad y normal. Las normales están en RGBA16F con el canal alfa reservado para el factor AO en el paso borroso. Almaceno la profundidad en un búfer de profundidad no lineal (32F) y recupero la profundidad lineal usando:


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

donde projAB.yse calcula como:

ingrese la descripción de la imagen aquí

y projAB.xcomo:

ingrese la descripción de la imagen aquí

Estos se derivan de la matriz glm :: perspective (gluperspective). z_n y z_f son la distancia de recorte cercana y lejana.

Como se describe en el enlace que publiqué en la parte superior, el método crea muestras en un hemisferio con una distribución más alta cerca del centro. Luego usa vectores aleatorios de una textura para rotar el hemisferio aleatoriamente alrededor de la dirección Z y finalmente lo orienta a lo largo de la normalidad en el píxel dado. Como el resultado es ruidoso, un pase borroso sigue al pase SSAO.

De todos modos, la reconstrucción de mi posición no parece estar mal ya que también intenté hacer lo mismo, pero la posición pasó de una textura en lugar de ser reconstruida.

También intenté jugar con el Radio, el tamaño de la textura de ruido y el número de muestras y con diferentes tipos de formatos de textura, sin suerte. Por alguna razón al cambiar el Radio, nada cambia.

¿Alguien tiene alguna sugerencia? ¿Qué podría estar yendo mal?


Creo que el desenfoque debe ser un pase separado. ¿Puedes publicar una captura de pantalla de tu sombreador sin el desenfoque?
knight666

El pase de desenfoque es independiente, puede verificar la captura de pantalla previa al desenfoque .
Grieverheart

Respuestas:


6

Encontré el problema. Fue un error realmente estúpido, no sabía que tenía que especificar glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);para obtener los valores de profundidad correctos y, por lo tanto, no estaba muestreando los valores de profundidad. Ahora obtengo un buen efecto SSAO:

ingrese la descripción de la imagen aquí


Siéntase libre de marcar esto como la respuesta correcta para que las personas sepan que ha encontrado su solución: P
SomeGuy

Sí, desafortunadamente tengo que esperar un día para poder marcar mi respuesta como correcta: S.
Grieverheart

Mi error, no verificó las marcas de tiempo.
SomeGuy
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.