Files
LNXSDK/leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl

161 lines
4.3 KiB
Plaintext
Raw Normal View History

2025-01-22 16:18:30 +01:00
#version 450
#include "compiled.inc"
#include "std/math.glsl"
#include "std/gbuffer.glsl"
uniform sampler2D tex;
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0; // Normal, roughness
uniform sampler2D gbuffer1; // basecol, spec
uniform mat4 P;
uniform mat3 V3;
uniform vec2 cameraProj;
2026-08-07 02:04:01 -07:00
uniform vec2 screenSize;
2025-01-22 16:18:30 +01:00
#ifdef _CPostprocess
uniform vec3 PPComp9;
uniform vec3 PPComp10;
#endif
in vec3 viewRay;
in vec2 texCoord;
out vec4 fragColor;
vec3 hitCoord;
float depth;
2026-08-07 02:04:01 -07:00
const int numBinarySearchSteps = 8;
const int maxSteps = 50;
2025-01-22 16:18:30 +01:00
vec2 getProjectedCoord(const vec3 hit) {
vec4 projectedCoord = P * vec4(hit, 1.0);
projectedCoord.xy /= projectedCoord.w;
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
#ifdef _InvY
projectedCoord.y = 1.0 - projectedCoord.y;
#endif
return projectedCoord.xy;
}
float getDeltaDepth(const vec3 hit) {
2026-08-07 02:04:01 -07:00
vec2 tc = getProjectedCoord(hit);
if (tc.x < 0.0 || tc.x > 1.0 || tc.y < 0.0 || tc.y > 1.0)
return -1.0;
depth = textureLod(gbufferD, tc, 0.0).r * 2.0 - 1.0;
2025-01-22 16:18:30 +01:00
vec3 viewPos = getPosView(viewRay, depth, cameraProj);
return viewPos.z - hit.z;
}
2026-08-07 02:04:01 -07:00
vec4 binarySearch(vec3 dir, float stepSize) {
2025-01-22 16:18:30 +01:00
float ddepth;
for (int i = 0; i < numBinarySearchSteps; i++) {
2026-08-07 02:04:01 -07:00
stepSize *= 0.5;
hitCoord -= dir * stepSize;
2025-01-22 16:18:30 +01:00
ddepth = getDeltaDepth(hitCoord);
2026-08-07 02:04:01 -07:00
if (ddepth < 0.0) hitCoord += dir * stepSize;
2025-01-22 16:18:30 +01:00
}
#ifdef _CPostprocess
2026-08-07 02:04:01 -07:00
float maxDist = PPComp9.z;
2025-01-22 16:18:30 +01:00
#else
2026-08-07 02:04:01 -07:00
float maxDist = ssrSearchDist;
2025-01-22 16:18:30 +01:00
#endif
2026-08-07 02:04:01 -07:00
if (abs(ddepth) > maxDist * 0.005) return vec4(0.0);
vec2 hitTC = getProjectedCoord(hitCoord);
if (hitTC.x < 0.0 || hitTC.x > 1.0 || hitTC.y < 0.0 || hitTC.y > 1.0)
return vec4(0.0);
return vec4(hitTC, 0.0, 1.0);
2025-01-22 16:18:30 +01:00
}
vec4 rayCast(vec3 dir) {
#ifdef _CPostprocess
2026-08-07 02:04:01 -07:00
float baseStep = PPComp9.x;
float maxDist = PPComp9.z;
2025-01-22 16:18:30 +01:00
#else
2026-08-07 02:04:01 -07:00
float baseStep = ssrRayStep;
float maxDist = ssrSearchDist;
2025-01-22 16:18:30 +01:00
#endif
2026-08-07 02:04:01 -07:00
float stepSize = baseStep * max(1.0, -viewRay.z * 0.1);
vec3 startPos = hitCoord;
2025-01-22 16:18:30 +01:00
for (int i = 0; i < maxSteps; i++) {
2026-08-07 02:04:01 -07:00
hitCoord += dir * stepSize;
float dist = length(hitCoord - startPos);
if (dist > maxDist) break;
float ddepth = getDeltaDepth(hitCoord);
if (ddepth > 0.0) return binarySearch(dir, stepSize);
stepSize *= 1.03;
2025-01-22 16:18:30 +01:00
}
return vec4(0.0);
}
void main() {
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
2026-08-07 02:04:01 -07:00
float roughness = g0.b;
2025-01-22 16:18:30 +01:00
if (roughness == 1.0) { fragColor.rgb = vec3(0.0); return; }
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
if (spec == 0.0) { fragColor.rgb = vec3(0.0); return; }
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
if (d == 1.0) { fragColor.rgb = vec3(0.0); return; }
vec2 enc = g0.rg;
vec3 n;
n.z = 1.0 - abs(enc.x) - abs(enc.y);
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
n = normalize(n);
vec3 viewNormal = V3 * n;
vec3 viewPos = getPosView(viewRay, d, cameraProj);
2026-08-07 02:04:01 -07:00
float NdotV = clamp(dot(viewNormal, -normalize(viewPos)), 0.0, 1.0);
vec3 reflected = reflect(normalize(viewPos), viewNormal);
2025-01-22 16:18:30 +01:00
hitCoord = viewPos;
2026-08-07 02:04:01 -07:00
vec3 dir = reflected;
2025-01-22 16:18:30 +01:00
vec4 coords = rayCast(dir);
2026-08-07 02:04:01 -07:00
if (coords.w <= 0.0) {
fragColor.rgb = vec3(0.0);
return;
}
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
float screenEdgeFactor = smoothstep(0.5, 0.15, deltaCoords.x)
* smoothstep(0.5, 0.15, deltaCoords.y);
screenEdgeFactor = max(screenEdgeFactor, 0.15);
float hitDepth = textureLod(gbufferD, coords.xy, 0.0).r * 2.0 - 1.0;
vec3 hitViewPos = getPosView(viewRay, hitDepth, cameraProj);
vec3 hitDir = normalize(hitViewPos - viewPos);
float hitNdotV = clamp(dot(viewNormal, -hitDir), 0.0, 1.0);
float hitBackFace = smoothstep(-0.15, 0.3, hitNdotV);
2025-01-22 16:18:30 +01:00
float reflectivity = 1.0 - roughness;
#ifdef _CPostprocess
2026-08-07 02:04:01 -07:00
float falloffExp = PPComp10.x;
float maxDist = PPComp9.z;
2025-01-22 16:18:30 +01:00
#else
2026-08-07 02:04:01 -07:00
float falloffExp = ssrFalloffExp;
float maxDist = ssrSearchDist;
2025-01-22 16:18:30 +01:00
#endif
2026-08-07 02:04:01 -07:00
float distAttenuation = 1.0 - clamp(length(viewPos - hitCoord) / maxDist, 0.0, 1.0);
distAttenuation = pow(distAttenuation, 1.5);
float fresnel = pow(1.0 - NdotV, 5.0);
fresnel = mix(0.04, 1.0, fresnel);
float intensity = pow(reflectivity, falloffExp) * screenEdgeFactor
* smoothstep(0.0, 0.1, -reflected.z)
* distAttenuation
* hitBackFace
* coords.w;
2025-01-22 16:18:30 +01:00
intensity = clamp(intensity, 0.0, 1.0);
2026-08-07 02:04:01 -07:00
2025-01-22 16:18:30 +01:00
vec3 reflCol = textureLod(tex, coords.xy, 0.0).rgb;
reflCol = clamp(reflCol, 0.0, 1.0);
2026-08-07 02:04:01 -07:00
fragColor.rgb = reflCol * intensity * mix(0.5, 1.0, fresnel);
2025-01-22 16:18:30 +01:00
}