From 9e2b6014457840048aeeae2c8cafb6b05d1d29c6 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 9 Jul 2025 23:16:54 +0000 Subject: [PATCH] revert 0439dde4a81d3fd1ac2fed91907c14ecba33c8e5 revert Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl --- .../deferred_light/deferred_light.frag.glsl | 973 ++++++++++-------- 1 file changed, 548 insertions(+), 425 deletions(-) diff --git a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl index a1c01f4..73788ff 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl @@ -1,463 +1,586 @@ -//Transparent shadow implemented by Yvain Douard with reference: -//https://wickedengine.net/2018/01/easy-transparent-shadow-maps/comment-page-1/ - -#ifndef _SHADOWS_GLSL_ -#define _SHADOWS_GLSL_ +#version 450 #include "compiled.inc" +#include "std/gbuffer.glsl" +#ifdef _Clusters +#include "std/clusters.glsl" +#endif +#ifdef _Irr +#include "std/shirr.glsl" +#endif +#ifdef _SSS +#include "std/sss.glsl" +#endif +#ifdef _SSRS +#include "std/ssrs.glsl" +#endif -#ifdef _CSM -uniform vec4 casData[shadowmapCascades * 4 + 4]; +uniform sampler2D gbufferD; +uniform sampler2D gbuffer0; +uniform sampler2D gbuffer1; + +#ifdef _gbuffer2 + uniform sampler2D gbuffer2; +#endif +#ifdef _EmissionShaded + uniform sampler2D gbufferEmission; +#endif + +#ifdef _VoxelGI +uniform sampler2D voxels_diffuse; +uniform sampler2D voxels_specular; +#else +#ifdef _VoxelAOvar +uniform sampler2D voxels_ao; +#endif +#endif +#ifdef _VoxelShadow +uniform sampler3D voxels; +uniform sampler3D voxelsSDF; +uniform float clipmaps[10 * voxelgiClipmapCount]; +#endif + +uniform float envmapStrength; +#ifdef _Irr +uniform vec4 shirr[7]; +#endif +#ifdef _Brdf +uniform sampler2D senvmapBrdf; +#endif +#ifdef _Rad +uniform sampler2D senvmapRadiance; +uniform int envmapNumMipmaps; +#endif +#ifdef _EnvCol +uniform vec3 backgroundCol; +#endif + +#ifdef _SSAO +uniform sampler2D ssaotex; +#else +#ifdef _SSGI +uniform sampler2D ssaotex; +#endif +#endif + +#ifdef _SSS +uniform vec2 lightPlane; +#endif + +#ifdef _SSRS +//!uniform mat4 VP; +uniform mat4 invVP; +#endif + +#ifdef _LightIES +//!uniform sampler2D texIES; #endif #ifdef _SMSizeUniform -uniform vec2 smSizeUniform; +//!uniform vec2 smSizeUniform; +#endif + +#ifdef _LTC +//!uniform vec3 lightArea0; +//!uniform vec3 lightArea1; +//!uniform vec3 lightArea2; +//!uniform vec3 lightArea3; +//!uniform sampler2D sltcMat; +//!uniform sampler2D sltcMag; +#ifdef _ShadowMap + #ifdef _SinglePoint + //!uniform sampler2DShadow shadowMapSpot[1]; + //!uniform sampler2D shadowMapSpotTransparent[1]; + //!uniform mat4 LWVPSpot[1]; + #endif + #ifdef _Clusters + //!uniform sampler2DShadow shadowMapSpot[4]; + //!uniform sampler2D shadowMapSpotTransparent[4]; + //!uniform mat4 LWVPSpotArray[4]; + #endif +#endif +#endif + +uniform vec2 cameraProj; +uniform vec3 eye; +uniform vec3 eyeLook; + +#ifdef _Clusters +uniform vec4 lightsArray[maxLights * 3]; + #ifdef _Spot + uniform vec4 lightsArraySpot[maxLights * 2]; + #endif +uniform sampler2D clustersData; +uniform vec2 cameraPlane; #endif #ifdef _ShadowMap - #ifdef _Clusters +#ifdef _SinglePoint + #ifdef _Spot + //!uniform sampler2DShadow shadowMapSpot[1]; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapSpotTransparent[1]; + #endif + //!uniform mat4 LWVPSpot[1]; + #else + //!uniform samplerCubeShadow shadowMapPoint[1]; + #ifdef _ShadowMapTransparent + //!uniform samplerCube shadowMapPointTransparent[1]; + #endif + //!uniform vec2 lightProj; + #endif +#endif +#ifdef _Clusters + #ifdef _ShadowMapAtlas + #ifdef _SingleAtlas + uniform sampler2DShadow shadowMapAtlas; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapAtlasTransparent; + #endif + #endif + #endif + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + //!uniform sampler2DShadow shadowMapAtlasPoint; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapAtlasPointTransparent; + #endif + #endif + //!uniform vec4 pointLightDataArray[maxLightsCluster * 6]; + #else + //!uniform samplerCubeShadow shadowMapPoint[4]; + #ifdef _ShadowMapTransparent + //!uniform samplerCube shadowMapPointTransparent[4]; + #endif + #endif + //!uniform vec2 lightProj; + #ifdef _Spot #ifdef _ShadowMapAtlas - uniform vec4 pointLightDataArray[maxLightsCluster * 6]; + #ifndef _SingleAtlas + //!uniform sampler2DShadow shadowMapAtlasSpot; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapAtlasSpotTransparent; + #endif #endif - #endif -#endif - -#ifdef _ShadowMapAtlas -// https://www.khronos.org/registry/OpenGL/specs/gl/glspec20.pdf // p:168 -// https://www.gamedev.net/forums/topic/687535-implementing-a-cube-map-lookup-function/5337472/ -vec2 sampleCube(vec3 dir, out int faceIndex) { - vec3 dirAbs = abs(dir); - float ma; - vec2 uv; - if(dirAbs.z >= dirAbs.x && dirAbs.z >= dirAbs.y) { - faceIndex = dir.z < 0.0 ? 5 : 4; - ma = 0.5 / dirAbs.z; - uv = vec2(dir.z < 0.0 ? -dir.x : dir.x, -dir.y); - } - else if(dirAbs.y >= dirAbs.x) { - faceIndex = dir.y < 0.0 ? 3 : 2; - ma = 0.5 / dirAbs.y; - uv = vec2(dir.x, dir.y < 0.0 ? -dir.z : dir.z); - } - else { - faceIndex = dir.x < 0.0 ? 1 : 0; - ma = 0.5 / dirAbs.x; - uv = vec2(dir.x < 0.0 ? dir.z : -dir.z, -dir.y); - } - // downscale uv a little to hide seams - // transform coordinates from clip space to texture space - #ifndef _FlipY - return uv * 0.9976 * ma + 0.5; - #else - #ifdef HLSL - return uv * 0.9976 * ma + 0.5; #else - return vec2(uv.x * ma, uv.y * -ma) * 0.9976 + 0.5; + //!uniform sampler2DShadow shadowMapSpot[4]; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapSpotTransparent[4]; #endif + #endif + //!uniform mat4 LWVPSpotArray[maxLightsCluster]; #endif -} +#endif #endif -vec3 PCF(sampler2DShadow shadowMap, - #ifdef _ShadowMapTransparent - sampler2D shadowMapTransparent, - #endif - const vec2 uv, const float compare, const vec2 smSize - #ifdef _ShadowMapTransparent - , const bool transparent - #endif - ) { - vec3 result = vec3(0.0); - result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 1.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(0.0, -1.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv, compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(0.0, 1.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(1.0, -1.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 0.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare)); - result = result.xxx / 9.0; - +#ifdef _Sun +uniform vec3 sunDir; +uniform vec3 sunCol; + #ifdef _ShadowMap + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasSun; #ifdef _ShadowMapTransparent - if (transparent == false) { - vec4 shadowmap_transparent = texture(shadowMapTransparent, uv); - if (shadowmap_transparent.a < compare) - result *= shadowmap_transparent.rgb; - } + uniform sampler2D shadowMapAtlasSunTransparent; #endif - - return result; -} - -float lpToDepth(vec3 lp, const vec2 lightProj) { - lp = abs(lp); - float zcomp = max(lp.x, max(lp.y, lp.z)); - zcomp = lightProj.x - lightProj.y / zcomp; - return zcomp * 0.5 + 0.5; -} - -vec3 PCFCube(samplerCubeShadow shadowMapCube, - #ifdef _ShadowMapTransparent - samplerCube shadowMapCubeTransparent, - #endif - const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n - #ifdef _ShadowMapTransparent - , const bool transparent - #endif - ) { - const float s = shadowmapCubePcfSize; // TODO: incorrect... - float compare = lpToDepth(lp, lightProj) - bias * 1.5; - ml = ml + n * bias * 20; - #ifdef _InvY - ml.y = -ml.y; #endif - vec3 result = vec3(0.0); - result.x = texture(shadowMapCube, vec4(ml, compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(s, s, s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(-s, s, s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(s, -s, s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(s, s, -s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(s, -s, -s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(-s, s, -s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare)); - result = result.xxx / 9.0; - + #else + uniform sampler2DShadow shadowMap; #ifdef _ShadowMapTransparent - if (transparent == false) { - vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml); - if (shadowmap_transparent.a < compare) - result *= shadowmap_transparent.rgb; - } + uniform sampler2D shadowMapTransparent; #endif - - return result; -} - -#ifdef _ShadowMapAtlas -// transform "out-of-bounds" coordinates to the correct face/coordinate system -// https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png -vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) { - if (uv.x < 0.0) { - if (faceIndex == 0) { // X+ - newFaceIndex = 4; // Z+ - } - else if (faceIndex == 1) { // X- - newFaceIndex = 5; // Z- - } - else if (faceIndex == 2) { // Y+ - newFaceIndex = 1; // X- - } - else if (faceIndex == 3) { // Y- - newFaceIndex = 1; // X- - } - else if (faceIndex == 4) { // Z+ - newFaceIndex = 1; // X- - } - else { // Z- - newFaceIndex = 0; // X+ - } - uv = vec2(1.0 + uv.x, uv.y); - } - else if (uv.x > 1.0) { - if (faceIndex == 0) { // X+ - newFaceIndex = 5; // Z- - } - else if (faceIndex == 1) { // X- - newFaceIndex = 4; // Z+ - } - else if (faceIndex == 2) { // Y+ - newFaceIndex = 0; // X+ - } - else if (faceIndex == 3) { // Y- - newFaceIndex = 0; // X+ - } - else if (faceIndex == 4) { // Z+ - newFaceIndex = 0; // X+ - } - else { // Z- - newFaceIndex = 1; // X- - } - uv = vec2(1.0 - uv.x, uv.y); - } - else if (uv.y < 0.0) { - if (faceIndex == 0) { // X+ - newFaceIndex = 2; // Y+ - } - else if (faceIndex == 1) { // X- - newFaceIndex = 2; // Y+ - } - else if (faceIndex == 2) { // Y+ - newFaceIndex = 5; // Z- - } - else if (faceIndex == 3) { // Y- - newFaceIndex = 4; // Z+ - } - else if (faceIndex == 4) { // Z+ - newFaceIndex = 2; // Y+ - } - else { // Z- - newFaceIndex = 2; // Y+ - } - uv = vec2(uv.x, 1.0 + uv.y); - } - else if (uv.y > 1.0) { - if (faceIndex == 0) { // X+ - newFaceIndex = 3; // Y- - } - else if (faceIndex == 1) { // X- - newFaceIndex = 3; // Y- - } - else if (faceIndex == 2) { // Y+ - newFaceIndex = 4; // Z+ - } - else if (faceIndex == 3) { // Y- - newFaceIndex = 5; // Z- - } - else if (faceIndex == 4) { // Z+ - newFaceIndex = 3; // Y- - } - else { // Z- - newFaceIndex = 3; // Y- - } - uv = vec2(uv.x, 1.0 - uv.y); - } else { - newFaceIndex = faceIndex; - } - // cover corner cases too - return uv; -} - -vec3 PCFFakeCube(sampler2DShadow shadowMap, - #ifdef _ShadowMapTransparent - sampler2D shadowMapTransparent, - #endif - const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index - #ifdef _ShadowMapTransparent - , const bool transparent - #endif - ) { - const vec2 smSize = smSizeUniform; // TODO: incorrect... - const float compare = lpToDepth(lp, lightProj) - bias * 1.5; - ml = ml + n * bias * 20; - int faceIndex = 0; - const int lightIndex = index * 6; - const vec2 uv = sampleCube(ml, faceIndex); - vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas - vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system #endif - - if (any(lessThan(uvtiled, vec2(0.0))) || any(greaterThan(uvtiled, vec2(1.0)))) { - return vec3(1.0); // Handle edge cases by returning full light - } - - vec3 result = vec3(0.0); - result.x += texture(shadowMap, vec3(uvtiled, compare)); - // soft shadowing - int newFaceIndex = 0; - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 0.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + uniform float shadowsBias; + #ifdef _CSM + //!uniform vec4 casData[shadowmapCascades * 4 + 4]; + #else + uniform mat4 LWVP; #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, -1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, 1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, -1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 0.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - result = result.xxx / 9.0; - - pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas - uvtiled = pointLightTile.z * uv + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - - #ifdef _ShadowMapTransparent - if (transparent == false) { - vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled); - if (shadowmap_transparent.a < compare) - result *= shadowmap_transparent.rgb; - } - #endif - - return result; -} + #endif // _ShadowMap #endif -vec3 shadowTest(sampler2DShadow shadowMap, - #ifdef _ShadowMapTransparent - sampler2D shadowMapTransparent, - #endif - const vec3 lPos, const float shadowsBias - #ifdef _ShadowMapTransparent - , const bool transparent - #endif - ) { - #ifdef _SMSizeUniform - vec2 smSize = smSizeUniform; - #else - const vec2 smSize = shadowmapSize; +#ifdef _SinglePoint // Fast path for single light +uniform vec3 pointPos; +uniform vec3 pointCol; + #ifdef _ShadowMap + uniform float pointBias; #endif - if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0); - return PCF(shadowMap, - #ifdef _ShadowMapTransparent - shadowMapTransparent, - #endif - lPos.xy, lPos.z - shadowsBias, smSize - #ifdef _ShadowMapTransparent - , transparent - #endif - ); -} - -#ifdef _CSM -mat4 getCascadeMat(const float d, out int casi, out int casIndex) { - const int c = shadowmapCascades; - // Get cascade index - // TODO: use bounding box slice selection instead of sphere - const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3)); - // int ci; - // if (d < casData[c * 4].x) ci = 0; - // else if (d < casData[c * 4].y) ci = 1 * 4; - // else if (d < casData[c * 4].z) ci = 2 * 4; - // else ci = 3 * 4; - // Splits - vec4 comp = vec4( - float(d > casData[c * 4].x), - float(d > casData[c * 4].y), - float(d > casData[c * 4].z), - float(d > casData[c * 4].w)); - casi = int(min(dot(ci, comp), c)); - // Get cascade mat - casIndex = casi * 4; - return mat4( - casData[casIndex ], - casData[casIndex + 1], - casData[casIndex + 2], - casData[casIndex + 3]); - // if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]); - // .. -} - -vec3 shadowTestCascade(sampler2DShadow shadowMap, - #ifdef _ShadowMapTransparent - sampler2D shadowMapTransparent, - #endif - const vec3 eye, const vec3 p, const float shadowsBias - #ifdef _ShadowMapTransparent - , const bool transparent - #endif - ) { - #ifdef _SMSizeUniform - vec2 smSize = smSizeUniform; - #else - const vec2 smSize = shadowmapSize * vec2(shadowmapCascades, 1.0); + #ifdef _Spot + uniform vec3 spotDir; + uniform vec3 spotRight; + uniform vec4 spotData; #endif - const int c = shadowmapCascades; - float d = distance(eye, p); - int casi; - int casIndex; - mat4 LWVP = getCascadeMat(d, casi, casIndex); - vec4 lPos = LWVP * vec4(p, 1.0); - lPos.xyz /= lPos.w; +#endif - vec3 visibility = vec3(1.0); - if (lPos.w > 0.0) visibility = PCF(shadowMap, - #ifdef _ShadowMapTransparent - shadowMapTransparent, - #endif - lPos.xy, lPos.z - shadowsBias, smSize - #ifdef _ShadowMapTransparent - , transparent - #endif - ); +#ifdef _LightClouds +uniform sampler2D texClouds; +uniform float time; +#endif - // Blend cascade - // https://github.com/TheRealMJP/Shadows - const float blendThres = 0.15; - float nextSplit = casData[c * 4][casi]; - float splitSize = casi == 0 ? nextSplit : nextSplit - casData[c * 4][casi - 1]; - float splitDist = (nextSplit - d) / splitSize; - if (splitDist <= blendThres && casi != c - 1) { - int casIndex2 = casIndex + 4; - mat4 LWVP2 = mat4( - casData[casIndex2 ], - casData[casIndex2 + 1], - casData[casIndex2 + 2], - casData[casIndex2 + 3]); +#include "std/light.glsl" - vec4 lPos2 = LWVP2 * vec4(p, 1.0); - lPos2.xyz /= lPos2.w; - vec3 visibility2 = vec3(1.0); - if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, +in vec2 texCoord; +in vec3 viewRay; +out vec4 fragColor; + +void main() { + vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid + + vec3 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); + + float roughness = g0.b; + float metallic; + uint matid; + unpackFloatInt16(g0.a, metallic, matid); + + vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ + vec2 occspec = unpackFloat2(g1.a); + vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor + vec3 f0 = surfaceF0(g1.rgb, metallic); + + float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; + vec3 p = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); + vec3 v = normalize(eye - p); + float dotNV = max(dot(n, v), 0.0); + +#ifdef _gbuffer2 + vec4 g2 = textureLod(gbuffer2, texCoord, 0.0); +#endif + + +#ifdef _MicroShadowing + occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel +#endif + +#ifdef _Brdf + vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; + vec3 F = f0 * envBRDF.x + envBRDF.y; +#else + vec3 F = f0; +#endif + +#ifndef _VoxelAOvar +#ifndef _VoxelGI + // Envmap +#ifdef _Irr + vec3 envl = shIrradiance(n, shirr); + + #ifdef _gbuffer2 + if (g2.b < 0.5) { + envl = envl; + } else { + envl = vec3(0.0); + } + #endif + + #ifdef _EnvTex + envl /= PI; + #endif +#else + vec3 envl = vec3(0.0); +#endif + +#ifdef _Rad + vec3 reflectionWorld = reflect(-v, n); + float lod = getMipFromRoughness(roughness, envmapNumMipmaps); + vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb; +#endif + +#ifdef _EnvLDR + envl.rgb = pow(envl.rgb, vec3(2.2)); + #ifdef _Rad + prefilteredColor = pow(prefilteredColor, vec3(2.2)); + #endif +#endif + + envl.rgb *= albedo; + +#ifdef _Brdf + envl.rgb *= 1.0 - F; //LV: We should take refracted light into account +#endif + +#ifdef _Rad // Indirect specular + envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT +#else + #ifdef _EnvCol + envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0? + #endif +#endif + + envl.rgb *= envmapStrength * occspec.x; + + fragColor.rgb = envl; +#endif +#endif + +#ifdef _VoxelGI + fragColor.rgb = textureLod(voxels_diffuse, texCoord, 0.0).rgb * voxelgiDiff; + if(roughness < 1.0 && occspec.y > 0.0) + fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * F * voxelgiRefl; +#else +#ifdef _VoxelAOvar + fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc; +#endif +#endif + + // Show voxels + // vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99); + // vec3 direction = vec3(0.0, 0.0, -1.0); + // vec4 color = vec4(0.0f); + // for(uint step = 0; step < 400 && color.a < 0.99f; ++step) { + // vec3 point = origin + 0.005 * step * direction; + // color += (1.0f - color.a) * textureLod(voxels, point * 0.5 + 0.5, 0); + // } + // fragColor.rgb += color.rgb; + + // Show SSAO + // fragColor.rgb = texture(ssaotex, texCoord).rrr; + +#ifdef _SSAO + // #ifdef _RTGI + // fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).rgb; + // #else + fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r; + // #endif +#else +#ifdef _SSGI + fragColor.rgb += textureLod(ssaotex, texCoord, 0.0).rgb; +#endif +#endif + +#ifdef _EmissionShadeless + if (matid == 1) { // pure emissive material, color stored in basecol + fragColor.rgb += g1.rgb; + fragColor.a = 1.0; // Mark as opaque + return; + } +#endif +#ifdef _EmissionShaded + #ifdef _EmissionShadeless + else { + #endif + vec3 emission = textureLod(gbufferEmission, texCoord, 0.0).rgb; + fragColor.rgb += emission; + #ifdef _EmissionShadeless + } + #endif +#endif + +#ifdef _Sun + vec3 sh = normalize(v + sunDir); + float sdotNH = max(0.0, dot(n, sh)); + float sdotVH = max(0.0, dot(v, sh)); + float sdotNL = max(0.0, dot(n, sunDir)); + vec3 svisibility = vec3(1.0); + vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) + + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y; + + #ifdef _ShadowMap + #ifdef _CSM + svisibility = shadowTestCascade( + #ifdef _ShadowMapAtlas + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + #ifndef _SingleAtlas + shadowMapAtlasSun + #else + shadowMapAtlas + #endif + #endif + #else #ifdef _ShadowMapTransparent - shadowMapTransparent, + shadowMap, shadowMapTransparent + #else + shadowMap #endif - lPos.xy, lPos.z - shadowsBias, smSize + #endif + , eye, p + n * shadowsBias * 10, shadowsBias #ifdef _ShadowMapTransparent - , transparent + , false #endif ); + #else + vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); + if (lPos.w > 0.0) { + svisibility = shadowTest( + #ifdef _ShadowMapAtlas + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + #ifndef _SingleAtlas + shadowMapAtlasSun + #else + shadowMapAtlas + #endif + #endif + #else + #ifdef _ShadowMapTransparent + shadowMap, shadowMapTransparent + #else + shadowMap + #endif + #endif + , lPos.xyz / lPos.w, shadowsBias + #ifdef _ShadowMapTransparent + , false + #endif + ); + } + #endif + #endif - float lerpAmt = smoothstep(0.0, blendThres, splitDist); - return mix(visibility2, visibility, lerpAmt); + #ifdef _VoxelShadow + svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, -g2.rg).r) * voxelgiShad; + #endif + + #ifdef _SSRS + // vec2 coords = getProjectedCoord(hitCoord); + // vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy); + // float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0); + svisibility *= traceShadowSS(sunDir, p, gbufferD, invVP, eye); + #endif + + #ifdef _LightClouds + svisibility *= textureLod(texClouds, vec2(p.xy / 100.0 + time / 80.0), 0.0).r * dot(n, vec3(0,0,1)); + #endif + + #ifdef _MicroShadowing + // See https://advances.realtimerendering.com/other/2016/naughty_dog/NaughtyDog_TechArt_Final.pdf + svisibility *= clamp(sdotNL + 2.0 * occspec.x * occspec.x - 1.0, 0.0, 1.0); + #endif + + fragColor.rgb += sdirect * sunCol * svisibility; + +// #ifdef _Hair // Aniso +// if (matid == 2) { +// const float shinyParallel = roughness; +// const float shinyPerpendicular = 0.1; +// const vec3 v = vec3(0.99146, 0.11664, 0.05832); +// vec3 T = abs(dot(n, v)) > 0.99999 ? cross(n, vec3(0.0, 1.0, 0.0)) : cross(n, v); +// fragColor.rgb = orenNayarDiffuseBRDF(albedo, roughness, dotNV, dotNL, dotVH) + wardSpecular(n, h, dotNL, dotNV, dotNH, T, shinyParallel, shinyPerpendicular) * spec; +// } +// #endif + + #ifdef _SSS + if (matid == 2) { + #ifdef _CSM + int casi, casindex; + mat4 LWVP = getCascadeMat(distance(eye, p), casi, casindex); + #endif + fragColor.rgb += fragColor.rgb * SSSSTransmittance( + LWVP, p, n, sunDir, lightPlane.y, + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + shadowMapAtlasSun + #else + shadowMapAtlas + #endif + #else + shadowMap + #endif + );//TODO implement transparent shadowmaps into the SSSSTransmittance() } - return visibility; - // Visualize cascades - // if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0); - // if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0); - // if (ci == 8) albedo.rgb = vec3(0.0, 0.0, 1.0); - // if (ci == 12) albedo.rgb = vec3(1.0, 1.0, 0.0); -} + #endif + +#endif // _Sun + +#ifdef _SinglePoint + + fragColor.rgb += sampleLight( + p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0 + #ifdef _ShadowMap + , 0, pointBias, true + #ifdef _ShadowMapTransparent + , false + #endif + #endif + #ifdef _Spot + , true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight + #endif + #ifdef _VoxelShadow + , voxels, voxelsSDF, clipmaps, -g2.rg + #endif + #ifdef _MicroShadowing + , occspec.x + #endif + #ifdef _SSRS + , gbufferD, invVP, eye + #endif + ); + + #ifdef _Spot + #ifdef _SSS + if (matid == 2) fragColor.rgb += fragColor.rgb * SSSSTransmittance(LWVPSpot[0], p, n, normalize(pointPos - p), lightPlane.y, shadowMapSpot[0]);//TODO implement transparent shadowmaps into the SSSSTransmittance() + #endif + #endif + #endif -#endif \ No newline at end of file + +#ifdef _Clusters + float viewz = linearize(depth * 0.5 + 0.5, cameraProj); + int clusterI = getClusterI(texCoord, 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); + fragColor.rgb += sampleLight( + p, + n, + v, + dotNV, + lightsArray[li * 3].xyz, // lp + lightsArray[li * 3 + 1].xyz, // lightCol + albedo, + roughness, + occspec.y, + f0 + #ifdef _ShadowMap + // light index, shadow bias, cast_shadows + , li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0 + #ifdef _ShadowMapTransparent + , false + #endif + #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 + #ifdef _VoxelShadow + , voxels, voxelsSDF, clipmaps, -g2.rg + #endif + #ifdef _MicroShadowing + , occspec.x + #endif + #ifdef _SSRS + , gbufferD, invVP, eye + #endif + ); + } +#endif // _Clusters + fragColor.a = 1.0; // Mark as opaque +}