Артефакты отражений пространства экрана - PullRequest
0 голосов
/ 24 ноября 2018

Когда я внедрил SSR, я столкнулся с проблемой артефактов.Ниже я представляю код и скриншоты.

Фрагмент SSR шейдера:

#version 330 core

uniform sampler2D normalMap; // in view space
uniform sampler2D colorMap;
uniform sampler2D reflectionStrengthMap;
uniform sampler2D positionMap; // in view space
uniform mat4 projection;
uniform vec3 skyColor = vec3(0.1, 0, 0.5);

in vec2 texCoord;

layout (location = 0) out vec4 fragColor;

const int binarySearchCount = 10;
const int rayMarchCount = 30;
const float step = 0.05;
const float LLimiter = 0.2;
const float minRayStep = 0.2;

vec3 getPosition(in vec2 texCoord) {
    return texture(positionMap, texCoord).xyz;
}

vec2 binarySearch(inout vec3 dir, inout vec3 hitCoord, inout float dDepth) {
    float depth;

    vec4 projectedCoord;

    for(int i = 0; i < binarySearchCount; i++) {
        projectedCoord = projection * vec4(hitCoord, 1.0);
        projectedCoord.xy /= projectedCoord.w;
        projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;

        depth = getPosition(projectedCoord.xy).z;

        dDepth = hitCoord.z - depth;

        dir *= 0.5;
        if(dDepth > 0.0)
            hitCoord += dir;
        else
            hitCoord -= dir;    
    }

    projectedCoord = projection * vec4(hitCoord, 1.0);
    projectedCoord.xy /= projectedCoord.w;
    projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;

    return vec2(projectedCoord.xy);
}

vec2 rayCast(vec3 dir, inout vec3 hitCoord, out float dDepth) {
    dir *= step;

    for (int i = 0; i < rayMarchCount; i++) {
        hitCoord += dir;

        vec4 projectedCoord = projection * vec4(hitCoord, 1.0);
        projectedCoord.xy /= projectedCoord.w;
        projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; 

        float depth = getPosition(projectedCoord.xy).z;
        dDepth = hitCoord.z - depth;

        if((dir.z - dDepth) < 1.2 && dDepth <= 0.0) return binarySearch(dir, hitCoord, dDepth);
    }

    return vec2(-1.0);
}

void main() {
    float reflectionStrength = texture(reflectionStrengthMap, texCoord).r;

    if (reflectionStrength == 0) {
        fragColor = texture(colorMap, texCoord);
        return;
    }

    vec3 normal = texture(normalMap, texCoord).xyz;
    vec3 viewPos = getPosition(texCoord);

    // Reflection vector
    vec3 reflected = normalize(reflect(normalize(viewPos), normalize(normal)));

    // Ray cast
    vec3 hitPos = viewPos;
    float dDepth; 
    vec2 coords = rayCast(reflected * max(-viewPos.z, minRayStep), hitPos, dDepth);

    float L = length(getPosition(coords) - viewPos);
    L = clamp(L * LLimiter, 0, 1);
    float error = 1 - L;

    vec3 color = texture(colorMap, coords.xy).rgb * error;

    if (coords.xy != vec2(-1.0)) {
        fragColor = mix(texture(colorMap, texCoord), vec4(color, 1.0), reflectionStrength);
        return;
    }

    fragColor = mix(texture(colorMap, texCoord), vec4(skyColor, 1.0), reflectionStrength);
}

Результат без затемнения (без * error): 1

Результат с затемнением: 2

Примечание: синий заполнен специально для просмотра артефактов

И еще один вопрос, как лучше всего добавить fresnel без вреда для сцены?

...