Home
API reference

volumetricFogFragmentShader

strata-game-library/shaders

strata-game-library/shaders


strata-game-library/shaders / volumetricFogFragmentShader

Variable: volumetricFogFragmentShader

const volumetricFogFragmentShader: "\n uniform sampler2D tDepth;\n uniform sampler2D tDiffuse;\n uniform float uCameraNear;\n uniform float uCameraFar;\n uniform vec3 uFogColor;\n uniform float uFogDensity;\n uniform float uFogHeight;\n uniform float uFogFalloff;\n uniform float uTime;\n uniform vec3 uLightDirection;\n uniform vec3 uLightColor;\n uniform float uScatteringStrength;\n uniform vec2 uResolution;\n uniform vec3 uCameraPosition;\n uniform mat4 uProjectionMatrixInverse;\n uniform mat4 uViewMatrixInverse;\n \n varying vec2 vUv;\n \n \n// Hash function\nfloat hash(vec3 p) {\n p = fract(p * vec3(443.897, 441.423, 437.195));\n p += dot(p, p.yxz + 19.19);\n return fract((p.x + p.y) * p.z);\n}\n\n// 3D Value noise\nfloat noise(vec3 p) {\n vec3 i = floor(p);\n vec3 f = fract(p);\n f = f * f * (3.0 - 2.0 * f);\n \n float n = mix(\n mix(\n mix(hash(i + vec3(0,0,0)), hash(i + vec3(1,0,0)), f.x),\n mix(hash(i + vec3(0,1,0)), hash(i + vec3(1,1,0)), f.x),\n f.y\n ),\n mix(\n mix(hash(i + vec3(0,0,1)), hash(i + vec3(1,0,1)), f.x),\n mix(hash(i + vec3(0,1,1)), hash(i + vec3(1,1,1)), f.x),\n f.y\n ),\n f.z\n );\n return n;\n}\n\n// FBM (Fractal Brownian Motion)\nfloat fbm(vec3 p, int octaves) {\n float value = 0.0;\n float amplitude = 0.5;\n float frequency = 1.0;\n \n for (int i = 0; i < 6; i++) {\n if (i >= octaves) break;\n value += amplitude * noise(p * frequency);\n amplitude *= 0.5;\n frequency *= 2.0;\n }\n \n return value;\n}\n\n \n // Convert depth buffer value to linear depth\n float linearizeDepth(float depth) {\n float z = depth * 2.0 - 1.0;\n return (2.0 * uCameraNear * uCameraFar) / (uCameraFar + uCameraNear - z * (uCameraFar - uCameraNear));\n }\n \n // Reconstruct world position from depth\n vec3 getWorldPosition(vec2 uv, float depth) {\n vec4 clipSpace = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);\n vec4 viewSpace = uProjectionMatrixInverse * clipSpace;\n if (abs(viewSpace.w) < 0.0001) {\n return vec3(0.0);\n }\n viewSpace /= viewSpace.w;\n vec4 worldSpace = uViewMatrixInverse * viewSpace;\n return worldSpace.xyz;\n }\n \n // Height-based fog density\n float getFogDensity(vec3 pos) {\n float heightFactor = exp(-uFogFalloff * max(0.0, pos.y - uFogHeight));\n \n // Add noise for volumetric look\n float noiseVal = fbm(pos * 0.05 + vec3(uTime * 0.02, 0.0, uTime * 0.01), 3);\n \n return uFogDensity * heightFactor * (0.5 + 0.5 * noiseVal);\n }\n \n // Light scattering (Mie/Rayleigh approximation)\n float getMieScattering(vec3 rayDir, vec3 lightDir) {\n float cosAngle = dot(rayDir, lightDir);\n float g = 0.7; // Anisotropy factor\n float phase = (1.0 - g * g) / pow(1.0 + g * g - 2.0 * g * cosAngle, 1.5);\n return phase * 0.25;\n }\n \n void main() {\n vec4 sceneColor = texture2D(tDiffuse, vUv);\n float depth = texture2D(tDepth, vUv).r;\n \n // Skip sky (depth = 1)\n if (depth >= 1.0) {\n gl_FragColor = sceneColor;\n return;\n }\n \n vec3 worldPos = getWorldPosition(vUv, depth);\n vec3 rayDir = normalize(worldPos - uCameraPosition);\n float rayLength = length(worldPos - uCameraPosition);\n \n // Raymarch through fog\n #define MAX_STEPS 32\n float stepSize = rayLength / float(MAX_STEPS);\n \n vec3 fogAccum = vec3(0.0);\n float transmittance = 1.0;\n vec3 currentPos = uCameraPosition;\n \n vec3 lightDir = normalize(uLightDirection);\n \n for (int i = 0; i < MAX_STEPS; i++) {\n currentPos += rayDir * stepSize;\n \n float density = getFogDensity(currentPos);\n \n if (density > 0.001) {\n // Light scattering\n float scatter = getMieScattering(rayDir, lightDir);\n vec3 lightContribution = uLightColor * scatter * uScatteringStrength;\n \n // Accumulate fog color with light\n vec3 fogSample = uFogColor + lightContribution;\n \n float absorption = density * stepSize;\n fogAccum += fogSample * transmittance * absorption;\n transmittance *= exp(-absorption);\n \n if (transmittance < 0.01) break;\n }\n }\n \n // Blend fog with scene\n vec3 finalColor = sceneColor.rgb * transmittance + fogAccum;\n \n gl_FragColor = vec4(finalColor, 1.0);\n }\n"

Defined in: volumetrics.ts:73