Не отримати бажаних результатів при впровадженні SSAO


12

Після впровадження відкладеної візуалізації я спробував удачу з реалізацією SSAO, використовуючи цей Підручник . На жаль, я не отримую нічого подібного до SSAO, ви можете побачити мій результат нижче.

невдалий ssao atempt

Ви можете бачити, що існує якась дивна картина, і там немає затінення оклюзії там, де потрібно (тобто між предметами та на землі). Я застосував шейдери:


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

Я малюю повноекранний квадратик і передаю текстури «Глибина» та «Нормальне». Нормали знаходяться в RGBA16F з альфа-каналом, зарезервованим для AO-коефіцієнта в проході розмиття. Я зберігаю глибину в нелінійному буфері глибини (32F) і відновлюю лінійну глибину, використовуючи:


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

де projAB.yобчислюється як:

введіть тут опис зображення

і projAB.xяк:

введіть тут опис зображення

Вони отримані з матриці glm :: перспектива (глуперспектива). z_n і z_f - близька і далека відстань кліпу.

Як описано у посиланні, яке я розмістив у верхній частині, метод створює зразки у півкулі з більш високим розподілом близько до центру. Потім він використовує випадкові вектори від текстури для обертання півсфери випадковим чином навколо напрямку Z і, нарешті, орієнтує його вздовж норми в заданому пікселі. Оскільки в результаті шумно, за пропуском SSAO слідує розмиття.

У будь-якому випадку, моя реконструкція позиції не здається помилковою, оскільки я також намагався робити те саме, але з позицією, переданою з текстури, а не з реконструкцією.

Я також спробував грати з радіусом, розміром текстури шуму та кількістю зразків та різними форматами текстур, не пощастивши. Чомусь при зміні Радіуса нічого не змінюється.

Хтось має якісь пропозиції? Що може піти не так?


Я думаю, що розмиття має бути окремим пропуском. Чи можете ви опублікувати скріншот свого шейдера без розмиття?
лицар666

Пропуск розмиття окремий, ви можете перевірити скріншот попереднього розмиття .
Grieverheart

Відповіді:


6

Я знайшов проблему. Це була дійсно дурна помилка, я не знав, що вам потрібно вказати, glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);щоб отримати правильні значення глибини, і, таким чином, я не відбирав вибіркові значення глибини. Тепер я отримую хороший ефект SSAO:

введіть тут опис зображення


Не соромтеся позначити це правильною відповіддю, щоб люди знали, що ви знайшли ваше рішення: P
SomeGuy

Так, на жаль, мені доводиться чекати один день, щоб я міг позначити свою відповідь правильною: S.
Grieverheart

Моя помилка, не перевірив часові позначки.
SomeGuy
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.