Не получить желаемых результатов с внедрением SSAO

12

После реализации отложенного рендеринга я попытал счастья с реализацией SSAO, используя этот учебник . К сожалению, я не получаю ничего похожего на SSAO, вы можете увидеть мой результат ниже.

неудачная попытка

Вы можете видеть, что образуется какой-то странный узор, и нет затенения окклюзии там, где это необходимо (т.е. между объектами и на земле). Шейдеры, которые я реализовал, следующие:


#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 с альфа-каналом, зарезервированным для коэффициента АО в проходе размытия. Я храню глубину в нелинейном буфере глубины (32F) и восстанавливаю линейную глубину, используя:


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

где projAB.yрассчитывается как:

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

и projAB.xкак:

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

Они получены из матрицы glm ::спектива (Глуперспектива). z_n и z_f - расстояние ближнего и дальнего клипа.

Как описано в ссылке, которую я разместил сверху, метод создает образцы в полушарии с более высоким распределением, близким к центру. Затем он использует случайные векторы из текстуры для случайного вращения полушария вокруг направления Z и, наконец, ориентирует его вдоль нормали в данном пикселе. Поскольку результат является шумным, проход по размытию следует за проходом SSAO.

В любом случае, моя реконструкция положения не кажется неправильной, так как я тоже пытался сделать то же самое, но с позицией, переданной из текстуры вместо реконструкции.

Я также безуспешно пытался поиграть с Radius, размером текстур шума и количеством сэмплов, а также с различными типами текстурных форматов. Почему-то при изменении радиуса ничего не меняется.

У кого-нибудь есть предложения? Что может быть не так?

Grieverheart
источник
Я думаю, что размытие должно быть отдельным проходом. Можете ли вы опубликовать скриншот вашего шейдера без размытия?
knight666
Проход размытия является отдельным, вы можете проверить скриншот перед размытием .
Grieverheart

Ответы:

6

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

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

Grieverheart
источник
Не стесняйтесь
пометить
Да, к сожалению, я должен подождать один день, чтобы пометить мой ответ как правильный: S.
Grieverheart
Моя ошибка, не проверять метки времени.
SomeGuy