armory/Shaders/volumetric_light/volumetric_light.frag.glsl
N8n5h 7463de6140 Add cast_shadow to lightArray data
This was done to undo the hardcoded nature of "receiveShadows", which
doesn't play nice when you have multiple lights of the same type and
one or several have cast_shadow set to false.

By simply "passing" the cast_shadow parameter within the lightArray it
was possible to detect lights that don't cast shadows before actually
wasting gpu cycles to render shadows with garbage data.

Support for deferred desktop and mobile, and forward was added.
2021-03-14 23:20:57 -03:00

149 lines
3.8 KiB
GLSL

// http://sebastien.hillaire.free.fr/index.php?option=com_content&view=article&id=72&Itemid=106
#version 450
#include "compiled.inc"
#include "std/gbuffer.glsl"
#include "std/shadows.glsl"
#ifdef _Clusters
#include "std/clusters.glsl"
#endif
uniform sampler2D gbufferD;
uniform sampler2D snoise;
#ifdef _Clusters
uniform vec4 lightsArray[maxLights * 3];
#ifdef _Spot
uniform vec4 lightsArraySpot[maxLights];
#endif
uniform sampler2D clustersData;
uniform vec2 cameraPlane;
#endif
#ifdef _ShadowMap
#ifdef _SinglePoint
#ifdef _Spot
uniform sampler2DShadow shadowMapSpot[1];
uniform mat4 LWVPSpot[1];
#else
uniform samplerCubeShadow shadowMapPoint[1];
uniform vec2 lightProj;
#endif
#endif
#ifdef _Clusters
uniform samplerCubeShadow shadowMapPoint[4];
uniform vec2 lightProj;
#ifdef _Spot
uniform sampler2DShadow shadowMapSpot[4];
uniform mat4 LWVPSpot[maxLightsCluster];
#endif
#endif
#endif
#ifdef _Sun
uniform vec3 sunDir;
uniform vec3 sunCol;
#ifdef _ShadowMap
uniform sampler2DShadow shadowMap;
uniform float shadowsBias;
#ifdef _CSM
//!uniform vec4 casData[shadowmapCascades * 4 + 4];
#else
uniform mat4 LWVP;
#endif
#endif // _ShadowMap
#endif
#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 vec2 spotData;
#endif
#endif
uniform vec2 cameraProj;
uniform vec3 eye;
uniform vec3 eyeLook;
in vec2 texCoord;
in vec3 viewRay;
out float fragColor;
const float tScat = 0.08;
const float tAbs = 0.0;
const float tExt = tScat + tAbs;
const float stepLen = 1.0 / volumSteps;
const float lighting = 0.4;
void rayStep(inout vec3 curPos, inout float curOpticalDepth, inout float scatteredLightAmount, float stepLenWorld, vec3 viewVecNorm) {
curPos += stepLenWorld * viewVecNorm;
const float density = 1.0;
float l1 = lighting * stepLenWorld * tScat * density;
curOpticalDepth *= exp(-tExt * stepLenWorld * density);
float visibility = 0.0;
#ifdef _Sun
#ifdef _CSM
mat4 LWVP = mat4(casData[4], casData[4 + 1], casData[4 + 2], casData[4 + 3]);
#endif
vec4 lPos = LWVP * vec4(curPos, 1.0);
lPos.xyz /= lPos.w;
visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias));
#endif
#ifdef _SinglePoint
#ifdef _Spot
vec4 lPos = LWVPSpot[0] * vec4(curPos, 1.0);
visibility = shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, pointBias);
float spotEffect = dot(spotDir, normalize(pointPos - curPos)); // lightDir
if (spotEffect < spotData.x) { // x - cutoff, y - cutoff - exponent
visibility *= smoothstep(spotData.y, spotData.x, spotEffect);
}
#else
vec3 ld = pointPos - curPos;
visibility = PCFCube(shadowMapPoint[0], ld, -normalize(ld), pointBias, lightProj, vec3(0.0));
#endif
#endif
#ifdef _Clusters
#endif
scatteredLightAmount += curOpticalDepth * l1 * visibility;
}
void main() {
float pixelRayMarchNoise = textureLod(snoise, texCoord * 100, 0.0).r * 2.0 - 1.0;
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
vec3 p = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
vec3 viewVec = p - eye;
float worldPosDist = length(viewVec);
vec3 viewVecNorm = viewVec / worldPosDist;
float startDepth = 0.1;
startDepth = min(worldPosDist, startDepth);
float endDepth = 20.0;
endDepth = min(worldPosDist, endDepth);
vec3 curPos = eye + viewVecNorm * startDepth;
float stepLenWorld = stepLen * (endDepth - startDepth);
float curOpticalDepth = exp(-tExt * stepLenWorld);
float scatteredLightAmount = 0.0;
curPos += stepLenWorld * viewVecNorm * pixelRayMarchNoise;
for (float l = stepLen; l < 0.99999; l += stepLen) { // Do not do the first and last steps
rayStep(curPos, curOpticalDepth, scatteredLightAmount, stepLenWorld, viewVecNorm);
}
fragColor = scatteredLightAmount * volumAirTurbidity;
}