屏幕空间反射伪像

时间:2018-11-24 11:17:38

标签: opengl glsl raytracing raycasting post-processing

实施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的最佳方法是什么?

0 个答案:

没有答案