#version 450 #include "compiled.inc" uniform sampler2D tex; uniform sampler2D tex2; #ifdef _Veloc uniform sampler2D sveloc; #endif in vec2 texCoord; out vec4 fragColor; const float SMAA_REPROJECTION_WEIGHT_SCALE = 30.0; // TODO: Move to a utility bool isInvalidValue(float v) { return (v != v) || (v > 65000.0) || (v < -65000.0); } bool hasInvalidValues(vec3 v) { return isInvalidValue(v.x) || isInvalidValue(v.y) || isInvalidValue(v.z); } void main() { vec4 current = textureLod(tex, texCoord, 0.0); current.rgb = clamp(current.rgb, vec3(0.0), vec3(10.0)); current.a = clamp(current.a, 0.0, 1.0); if (hasInvalidValues(current.rgb)) { current = vec4(0.0, 0.0, 0.0, 1.0); } #ifdef _Veloc // Velocity is assumed to be calculated for motion blur, so we need to inverse it for reprojection vec2 velocity = -textureLod(sveloc, texCoord, 0.0).rg; velocity = clamp(velocity, vec2(-1.0), vec2(1.0)); if (isInvalidValue(velocity.x) || isInvalidValue(velocity.y)) { velocity = vec2(0.0); } #ifdef _InvY velocity.y = -velocity.y; #endif // Reproject current coordinates and fetch previous pixel vec2 prevCoord = texCoord + velocity; prevCoord = clamp(prevCoord, vec2(0.0), vec2(1.0)); vec4 previous = textureLod(tex2, prevCoord, 0.0); previous.rgb = clamp(previous.rgb, vec3(0.0), vec3(10.0)); previous.a = clamp(previous.a, 0.0, 1.0); if (hasInvalidValues(previous.rgb)) { previous = current; // Fallback to current frame if previous is corrupted } #ifdef _SMAA float currentAlpha = clamp(current.a, 0.0, 1.0); float previousAlpha = clamp(previous.a, 0.0, 1.0); float delta = abs(currentAlpha * currentAlpha - previousAlpha * previousAlpha) / 5.0; delta = clamp(delta, 0.0, 1.0); // Ensure delta is in valid range #else const float delta = 0.0; #endif float weight = 0.5 * clamp(1.0 - sqrt(max(delta, 0.0)) * SMAA_REPROJECTION_WEIGHT_SCALE, 0.0, 1.0); vec3 blended = mix(current.rgb, previous.rgb, weight); blended = clamp(blended, vec3(0.0), vec3(10.0)); if (hasInvalidValues(blended)) { blended = current.rgb; } fragColor = vec4(blended, 1.0); #else vec4 previous = textureLod(tex2, texCoord, 0.0); previous.rgb = clamp(previous.rgb, vec3(0.0), vec3(10.0)); if (hasInvalidValues(previous.rgb)) { previous.rgb = current.rgb; } vec3 blended = mix(current.rgb, previous.rgb, 0.5); blended = clamp(blended, vec3(0.0), vec3(10.0)); if (hasInvalidValues(blended)) { blended = current.rgb; } fragColor = vec4(blended, 1.0); #endif }