1
\$\begingroup\$

When I tried to apply reflections to my scene, I ran into the problem of noise: noise

My fragment shader code:

#version 330 core

uniform sampler2D normalMap; // in view space
uniform sampler2D depthMap; // in view space
uniform sampler2D colorMap;
uniform sampler2D reflectionStrengthMap;
uniform mat4 projection;
uniform mat4 inv_projection;

in vec2 texCoord;

layout (location = 0) out vec4 fragColor;

vec3 calcViewPosition(in vec2 texCoord) {
    // Combine UV & depth into XY & Z (NDC)
    vec3 rawPosition = vec3(texCoord, texture(depthMap, texCoord).r);

    // Convert from (0, 1) range to (-1, 1)
    vec4 ScreenSpacePosition = vec4(rawPosition * 2 - 1, 1);

    // Undo Perspective transformation to bring into view space
    vec4 ViewPosition = inv_projection * ScreenSpacePosition;

    // Perform perspective divide and return
    return ViewPosition.xyz / ViewPosition.w;
}

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

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

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

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

        if(dDepth < 0.0) return projectedCoord.xy;
    }

    return vec2(-1.0f);
}

void main() {
    vec3 normal = texture(normalMap, texCoord).xyz * 2.0 - 1.0;
    float depth = texture(depthMap, texCoord).r;
    vec3 screenPos = 2.0 * vec3(texCoord, depth) - 1.0;
    vec3 viewPos = calcViewPosition(texCoord);

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

    // Ray cast
    vec3 hitPos = viewPos;
    float dDepth; 
    float minRayStep = 0.1f;
    vec2 coords = rayCast(reflected * max(minRayStep, -viewPos.z), hitPos, dDepth);
    if (coords != vec2(-1.0)) fragColor = mix(texture(colorMap, texCoord), texture(colorMap, coords), texture(reflectionStrengthMap, texCoord).r);
    else fragColor = texture(colorMap, texCoord);
}

Normal map: nmap

Reflection strength map (only red chanel): rsmap

\$\endgroup\$
1
\$\begingroup\$

There is usually no magic solution, you will get noise when doing SSR, to avoid it and get better results, you will need to cast multiple rays and interpolate between the different values you get.

Doing that will also allow you to apply different roughness values to your reflections, so they can become more or less blurry.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.