From ea69511e67d0c44969bad78529031385c06cda2c Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 00:47:22 +0000 Subject: [PATCH] Update leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl --- leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl | 559 ++++++++++++++++--- 1 file changed, 479 insertions(+), 80 deletions(-) diff --git a/leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl b/leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl index 694e0f2..96de299 100644 --- a/leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl +++ b/leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl @@ -1,107 +1,506 @@ #version 450 #include "compiled.inc" -#include "std/math.glsl" #include "std/gbuffer.glsl" +#include "std/brdf.glsl" +#include "std/math.glsl" +#ifdef _Clusters +#include "std/clusters.glsl" +#endif +#ifdef _ShadowMap +#include "std/shadows.glsl" +#endif +#ifdef _LTC +#include "std/ltc.glsl" +#endif +#ifdef _LightIES +#include "std/ies.glsl" +#endif +#ifdef _Spot +#include "std/light_common.glsl" +#endif +#include "std/constants.glsl" +uniform sampler2D gbuffer0; +uniform sampler2D gbuffer1; uniform sampler2D gbufferD; -uniform sampler2D gbuffer0; // Normal -// #ifdef _RTGI -// uniform sampler2D gbuffer1; // Basecol -// #endif -uniform mat4 P; -uniform mat3 V3; - +#ifdef _EmissionShaded +uniform sampler2D gbufferEmission; +#endif +uniform sampler2D sveloc; uniform vec2 cameraProj; +uniform vec3 eye; +uniform vec3 eyeLook; +uniform vec2 screenSize; +uniform mat4 invVP; -const float angleMix = 0.5f; -#ifdef _SSGICone9 -const float strength = 2.0 * (1.0 / ssgiStrength); -#else -const float strength = 2.0 * (1.0 / ssgiStrength) * 1.8; +in vec2 texCoord; +in vec3 viewRay; +out vec3 fragColor; + +float metallic; +uint matid; + +#ifdef _SMSizeUniform +//!uniform vec2 smSizeUniform; #endif -in vec3 viewRay; -in vec2 texCoord; -out float fragColor; - -vec3 hitCoord; -vec2 coord; -float depth; -// #ifdef _RTGI -// vec3 col = vec3(0.0); -// #endif -vec3 vpos; - -vec2 getProjectedCoord(vec3 hitCoord) { - vec4 projectedCoord = P * vec4(hitCoord, 1.0); - projectedCoord.xy /= projectedCoord.w; - projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; - #ifdef _InvY - projectedCoord.y = 1.0 - projectedCoord.y; +#ifdef _Clusters +uniform vec4 lightsArray[maxLights * 3]; + #ifdef _Spot + uniform vec4 lightsArraySpot[maxLights * 2]; #endif - return projectedCoord.xy; -} +uniform sampler2D clustersData; +uniform vec2 cameraPlane; +#endif -float getDeltaDepth(vec3 hitCoord) { - coord = getProjectedCoord(hitCoord); - depth = textureLod(gbufferD, coord, 0.0).r * 2.0 - 1.0; - vec3 p = getPosView(viewRay, depth, cameraProj); - return p.z - hitCoord.z; -} +#ifdef _SinglePoint // Fast path for single light +uniform vec3 pointPos; +uniform vec3 pointCol; + #ifdef _ShadowMap + uniform float pointBias; + #endif + #ifdef _Spot + uniform vec3 spotDir; + uniform vec3 spotRight; + uniform vec4 spotData; + #endif +#endif -void rayCast(vec3 dir) { - hitCoord = vpos; - dir *= ssgiRayStep * 2; - float dist = 0.15; - for (int i = 0; i < ssgiMaxSteps; i++) { - hitCoord += dir; - float delta = getDeltaDepth(hitCoord); - if (delta > 0.0 && delta < 0.2) { - dist = distance(vpos, hitCoord); - break; +#ifdef _CPostprocess + uniform vec3 PPComp12; +#endif + +#ifdef _ShadowMap + #ifdef _SinglePoint + #ifdef _Spot + #ifndef _LTC + uniform sampler2DShadow shadowMapSpot[1]; + uniform sampler2D shadowMapSpotTransparent[1]; + uniform mat4 LWVPSpot[1]; + #endif + #else + uniform samplerCubeShadow shadowMapPoint[1]; + uniform samplerCube shadowMapPointTransparent[1]; + uniform vec2 lightProj; + #endif + #endif + #ifdef _Clusters + #ifdef _SingleAtlas + uniform sampler2DShadow shadowMapAtlas; + uniform sampler2D shadowMapAtlasTransparent; + #endif + uniform vec2 lightProj; + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasPoint; + uniform sampler2D shadowMapAtlasPointTransparent; + //!uniform vec4 pointLightDataArray[maxLightsCluster * 6]; + #else + uniform samplerCubeShadow shadowMapPoint[4]; + uniform samplerCube shadowMapPointTransparent[4]; + #endif + #endif + #ifdef _Spot + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasSpot; + uniform sampler2D shadowMapAtlasSpotTransparent; + #endif + #else + uniform sampler2DShadow shadowMapSpot[4]; + uniform sampler2D shadowMapSpotTransparent[4]; + #endif + uniform mat4 LWVPSpotArray[maxLightsCluster]; + #endif + #endif +#endif + +#ifdef _LTC +uniform vec3 lightArea0; +uniform vec3 lightArea1; +uniform vec3 lightArea2; +uniform vec3 lightArea3; +uniform sampler2D sltcMat; +uniform sampler2D sltcMag; +#ifdef _ShadowMap +#ifndef _Spot + #ifdef _SinglePoint + uniform sampler2DShadow shadowMapSpot[1]; + uniform sampler2D shadowMapSpotTransparent[1]; + uniform mat4 LWVPSpot[1]; + #endif + #ifdef _Clusters + uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; + uniform mat4 LWVPSpotArray[maxLightsCluster]; + #endif +#endif +#endif +#endif + +#ifdef _Sun +uniform vec3 sunDir; +uniform vec3 sunCol; + #ifdef _ShadowMap + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasSun; + uniform sampler2D shadowMapAtlasSunTransparent; + #endif + #else + uniform sampler2DShadow shadowMap; + uniform sampler2D shadowMapTransparent; + #endif + uniform float shadowsBias; + #ifdef _CSM + //!uniform vec4 casData[shadowmapCascades * 4 + 4]; + #else + uniform mat4 LWVP; + #endif + #endif // _ShadowMap +#endif + +vec3 sampleLight(const vec3 p, const vec3 n, const vec3 lp, const vec3 lightCol + #ifdef _ShadowMap + , int index, float bias, bool receiveShadow, bool transparent + #endif + #ifdef _Spot + , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right + #endif + ) { + + vec3 ld = lp - p; + vec3 l = normalize(ld); + + vec3 visibility = lightCol; + visibility *= attenuate(distance(p, lp)); + + #ifdef _LTC + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); + visibility *= shadowTest(shadowMapSpot[0], + shadowMapSpotTransparent[0], + lPos.xyz / lPos.w, bias, transparent); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + if (index == 0) visibility *= shadowTest(shadowMapSpot[0], + shadowMapSpotTransparent[0], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 1) visibility *= shadowTest(shadowMapSpot[1], + shadowMapSpotTransparent[1], + , lPos.xyz / lPos.w, bias, transparent); + else if (index == 2) visibility *= shadowTest(shadowMapSpot[2], + shadowMapSpotTransparent[2], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 3) visibility *= shadowTest(shadowMapSpot[3], + shadowMapSpotTransparent[3], + lPos.xyz / lPos.w, bias, transparent); + #endif } + #endif + return visibility; + #endif + + #ifdef _Spot + if (isSpot) { + visibility *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); + visibility *= shadowTest(shadowMapSpot[0], + shadowMapSpotTransparent[0], + lPos.xyz / lPos.w, bias, transparent); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + #ifdef _ShadowMapAtlas + visibility *= shadowTest( + #ifndef _SingleAtlas + shadowMapAtlasSpot, shadowMapAtlasSpotTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + , lPos.xyz / lPos.w, bias, transparent + ); + #else + if (index == 0) visibility *= shadowTest(shadowMapSpot[0], + shadowMapSpotTransparent[0], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 1) visibility *= shadowTest(shadowMapSpot[1], + shadowMapSpotTransparent[1], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 2) visibility *= shadowTest(shadowMapSpot[2], + shadowMapSpotTransparent[2], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 3) visibility *= shadowTest(shadowMapSpot[3], + shadowMapSpotTransparent[3], + lPos.xyz / lPos.w, bias, transparent); + #endif + #endif + } + #endif + return visibility; } - fragColor += dist; - // #ifdef _RTGI - // col += textureLod(gbuffer1, coord, 0.0).rgb * ((ssgiRayStep * ssgiMaxSteps) - dist); - // #endif + #endif + + #ifdef _LightIES + visibility *= iesAttenuation(-l); + #endif + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + #ifndef _Spot + visibility *= PCFCube(shadowMapPoint[0], + shadowMapPointTransparent[0], + ld, -l, bias, lightProj, n, transparent); + #endif + #endif + #ifdef _Clusters + #ifdef _ShadowMapAtlas + visibility *= PCFFakeCube( + #ifndef _SingleAtlas + shadowMapAtlasPoint, shadowMapAtlasPointTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + , ld, -l, bias, lightProj, n, index, transparent + ); + #else + if (index == 0) visibility *= PCFCube(shadowMapPoint[0], + shadowMapPointTransparent[0], + ld, -l, bias, lightProj, n, transparent); + else if (index == 1) visibility *= PCFCube(shadowMapPoint[1], + shadowMapPointTransparent[1], + ld, -l, bias, lightProj, n, transparent); + else if (index == 2) visibility *= PCFCube(shadowMapPoint[2], + shadowMapPointTransparent[2], + ld, -l, bias, lightProj, n, transparent); + else if (index == 3) visibility *= PCFCube(shadowMapPoint[3], + shadowMapPointTransparent[3], + ld, -l, bias, lightProj, n, transparent); + #endif + #endif + } + #endif + + return visibility; } -vec3 tangent(const vec3 n) { - vec3 t1 = cross(n, vec3(0, 0, 1)); - vec3 t2 = cross(n, vec3(0, 1, 0)); - if (length(t1) > length(t2)) return normalize(t1); - else return normalize(t2); +vec3 getVisibility(vec3 p, vec3 n, float depth, vec2 uv) { + vec3 visibility = vec3(0.0); +#ifdef _Sun + #ifdef _ShadowMap + #ifdef _CSM + visibility = shadowTestCascade( + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + shadowMap, shadowMapTransparent + #endif + , eye, p + n * shadowsBias * 10, shadowsBias, false + ); + #else + vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); + if (lPos.w > 0.0) { + visibility = shadowTest( + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + shadowMap, shadowMapTransparent + #endif + , lPos.xyz / lPos.w, shadowsBias, false + ); + } + #endif + #endif +#endif + +#ifdef _SinglePoint + visibility += sampleLight( + p, n, pointPos, pointCol + #ifdef _ShadowMap + , 0, pointBias, true, false + #endif + #ifdef _Spot + , true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight + #endif + ); +#endif + +#ifdef _Clusters + float viewz = linearize(depth, cameraProj); + int clusterI = getClusterI(uv, viewz, cameraPlane); + int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255); + + #ifdef HLSL + viewz += textureLod(clustersData, vec2(0.0), 0.0).r * 1e-9; // TODO: krafix bug, needs to generate sampler + #endif + + #ifdef _Spot + int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255); + int numPoints = numLights - numSpots; + #endif + + for (int i = 0; i < min(numLights, maxLightsCluster); i++) { + int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255); + visibility += sampleLight( + p, + n, + lightsArray[li * 3].xyz, // lp + lightsArray[li * 3 + 1].xyz // lightCol + #ifdef _ShadowMap + // light index, shadow bias, cast_shadows + , li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false + #endif + #ifdef _Spot + , lightsArray[li * 3 + 2].y != 0.0 + , lightsArray[li * 3 + 2].y // spot size (cutoff) + , lightsArraySpot[li * 2].w // spot blend (exponent) + , lightsArraySpot[li * 2].xyz // spotDir + , vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w) // scale + , lightsArraySpot[li * 2 + 1].xyz // right + #endif + ); + } +#endif // _Clusters + return visibility; } +vec3 getWorldPos(vec2 uv, float depth) { + vec4 pos = invVP * vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); + return pos.xyz / pos.w; +} + +vec3 getNormal(vec2 uv) { + vec4 g0 = textureLod(gbuffer0, uv, 0.0); + 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); + return normalize(n); +} + +vec3 calculateIndirectLight(vec2 uv, vec3 pos, vec3 normal, float depth) { + // Simplified visibility - replace with your full visibility function if needed + vec3 sampleColor = textureLod(gbuffer1, uv, 0.0).rgb * getVisibility(pos, normal, depth, uv); + + #ifdef _EmissionShadeless + if (matid == 1) { // pure emissive material, color stored in basecol + sampleColor += textureLod(gbuffer1, uv, 0.0).rgb; + } + #endif + #ifdef _EmissionShaded + #ifdef _EmissionShadeless + else { + #endif + vec3 sampleEmission = textureLod(gbufferEmission, uv, 0.0).rgb; + sampleColor += sampleEmission; // Emission should be added directly + #ifdef _EmissionShadeless + } + #endif + #endif + + return sampleColor; +} + +// Improved sampling parameters +const float GOLDEN_ANGLE = 2.39996323; +const float MAX_DEPTH_DIFFERENCE = 0.9; // More conservative depth threshold +const float SAMPLE_BIAS = 0.01; // Small offset to avoid self-occlusion + void main() { - fragColor = 0; - vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); - float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; + float depth = textureLod(gbufferD, texCoord, 0.0).r; + if (depth >= 1.0) { + fragColor = vec3(0.0); + return; + } + + vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid + unpackFloatInt16(g0.a, metallic, matid); + + vec2 velocity = -textureLod(sveloc, texCoord, 0.0).rg; - 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(V3 * n); + n.z = 1.0 - abs(g0.x) - abs(g0.y); + n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); + n = normalize(n); - vpos = getPosView(viewRay, d, cameraProj); + vec3 pos = getWorldPos(texCoord, depth); + vec3 normal = getNormal(texCoord); + vec3 centerColor = textureLod(gbuffer1, texCoord, 0.0).rgb; - rayCast(n); - vec3 o1 = normalize(tangent(n)); - vec3 o2 = (cross(o1, n)); - vec3 c1 = 0.5f * (o1 + o2); - vec3 c2 = 0.5f * (o1 - o2); - rayCast(mix(n, o1, angleMix)); - rayCast(mix(n, o2, angleMix)); - rayCast(mix(n, -c1, angleMix)); - rayCast(mix(n, -c2, angleMix)); + float radius = ssaoRadius; - #ifdef _SSGICone9 - rayCast(mix(n, -o1, angleMix)); - rayCast(mix(n, -o2, angleMix)); - rayCast(mix(n, c1, angleMix)); - rayCast(mix(n, c2, angleMix)); + vec3 gi = vec3(0.0); + float totalWeight = 0.0; + float angle = fract(sin(dot(texCoord, vec2(12.9898, 78.233))) * 100.0); + + for (int i = 0; i < ssgiSamples; i++) { + // Use quasi-random sequence for better coverage + float r = sqrt((float(i) + 0.5) / float(ssgiSamples)) * radius; + float a = (float(i) * GOLDEN_ANGLE) + angle; + + vec2 offset = vec2(cos(a), sin(a)) * r * radius; + vec2 sampleUV = clamp(texCoord + offset * (BayerMatrix8[int(gl_FragCoord.x + velocity.x) % 8][int(gl_FragCoord.y + velocity.y) % 8] - 0.5) / screenSize, vec2(0.001), vec2(0.999)); + + float sampleDepth = textureLod(gbufferD, sampleUV, 0.0).r; + if (sampleDepth >= 1.0) continue; + + vec3 samplePos = getWorldPos(sampleUV, sampleDepth); + vec3 sampleNormal = getNormal(sampleUV); + + // Apply small bias to sample position to avoid self-occlusion + samplePos += sampleNormal * SAMPLE_BIAS; + + vec3 dir = pos - samplePos; + float dist = length(dir); + + if (abs(pos.z - samplePos.z) > MAX_DEPTH_DIFFERENCE) continue;; + + vec3 sampleColor = calculateIndirectLight(sampleUV, samplePos, sampleNormal, sampleDepth); + float weight = 1.0 / (1.0 + dist * dist * 2.0) * max(dot(sampleNormal, n), 0.0); + + gi += sampleColor * weight; + totalWeight += weight; + } + + // Normalize and apply intensity + if (totalWeight > 0.0) { + gi /= totalWeight; + #ifdef _CPostprocess + gi *= PPComp12.x; + #else + gi *= ssaoStrength; + #endif + } + + #ifdef _EmissionShadeless + if (matid == 1) { // pure emissive material, color stored in basecol + gi += textureLod(gbuffer1, texCoord, 0.0).rgb; + } #endif + #ifdef _EmissionShaded + #ifdef _EmissionShadeless + else { + #endif + gi += textureLod(gbufferEmission, texCoord, 0.0).rgb; + #ifdef _EmissionShadeless + } + #endif + #endif + fragColor = gi / (gi + vec3(1.0)); // Reinhard tone mapping }