Tidak mendapatkan hasil yang diinginkan dengan implementasi SSAO

12

Setelah menerapkan rendering yang ditangguhkan, saya mencoba keberuntungan saya dengan implementasi SSAO menggunakan Tutorial ini . Sayangnya, saya tidak mendapatkan apa pun yang terlihat seperti SSAO, Anda dapat melihat hasil saya di bawah ini.

gagal ssao atempt

Anda dapat melihat ada beberapa pola yang membentuk aneh dan tidak ada bayangan oklusi di mana perlu ada (yaitu di antara objek dan di tanah). Shader yang saya laksanakan mengikuti:


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

Saya menggambar quad layar penuh dan melewati tekstur Kedalaman dan Normal. Normalnya ada di RGBA16F dengan saluran alfa disediakan untuk faktor AO dalam blur pass. Saya menyimpan kedalaman dalam buffer Kedalaman non linier (32F) dan memulihkan kedalaman linear menggunakan:


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

dimana projAB.ydihitung sebagai:

masukkan deskripsi gambar di sini

dan projAB.xsebagai:

masukkan deskripsi gambar di sini

Ini diturunkan dari matriks glm :: perspective (gluperspective). z_n dan z_f adalah jarak klip dekat dan jauh.

Seperti yang dijelaskan dalam tautan yang saya posting di atas, metode ini membuat sampel di belahan bumi dengan distribusi yang lebih tinggi di dekat pusat. Kemudian menggunakan vektor acak dari tekstur untuk memutar belahan bumi secara acak di sekitar arah Z dan akhirnya mengarahkannya sepanjang normal pada piksel yang diberikan. Karena hasilnya berisik, blur pass mengikuti pass SSAO.

Bagaimanapun, rekonstruksi posisi saya sepertinya tidak salah karena saya juga mencoba melakukan hal yang sama tetapi dengan posisi yang dilewatkan dari tekstur bukannya direkonstruksi.

Saya juga mencoba bermain dengan Radius, ukuran tekstur noise dan jumlah sampel dan dengan berbagai jenis format tekstur, tanpa hasil. Untuk beberapa alasan ketika mengubah Radius, tidak ada yang berubah.

Adakah yang punya saran? Apa yang salah?

Grieverheart
sumber
Saya pikir blur perlu lulus secara terpisah. Bisakah Anda memposting tangkapan layar shader Anda tanpa blur?
knight666
Blur pass terpisah, Anda dapat memeriksa tangkapan layar pre-blur .
Grieverheart

Jawaban:

6

Saya menemukan masalahnya. Itu kesalahan yang sangat bodoh, saya tidak tahu Anda harus menentukan glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);untuk mendapatkan nilai kedalaman yang benar dan dengan demikian, saya tidak mengambil sampel nilai Kedalaman. Sekarang saya mendapatkan efek SSAO yang bagus:

masukkan deskripsi gambar di sini

Grieverheart
sumber
Jangan ragu untuk menandai ini sebagai jawaban yang benar sehingga orang tahu Anda telah menemukan solusi Anda: P
SomeGuy
Ya, sayangnya saya harus menunggu satu hari untuk dapat menandai jawaban saya sebagai yang benar: S.
Grieverheart
Kesalahan saya, tidak memeriksa cap waktu.
SomeGuy