init
This commit is contained in:
66
assets/shaders/volumetric.frag
Normal file
66
assets/shaders/volumetric.frag
Normal file
@@ -0,0 +1,66 @@
|
||||
#version 450 core
|
||||
#include "common.glsl"
|
||||
// Half-resolution ray march through height fog. Each step samples the sun
|
||||
// shadow map and canopy cookie, producing physically shadowed light shafts
|
||||
// (god rays). Output: rgb = in-scattered light, a = transmittance.
|
||||
|
||||
in vec2 vUV;
|
||||
layout(binding = 0) uniform sampler2D uDepth;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
float phaseHG(float c, float g) {
|
||||
float g2 = g * g;
|
||||
return (1.0 - g2) / (4.0 * PI * pow(1.0 + g2 - 2.0 * g * c, 1.5));
|
||||
}
|
||||
|
||||
float fogDensity(vec3 p) {
|
||||
float h = exp(-max(p.y - uFogParams.y, 0.0) * uFogParams.x);
|
||||
vec3 drift = vec3(uWind.x, 0.05, uWind.y) * uTime * 0.35;
|
||||
float n = vnoise3(p * 0.16 + drift) * 0.65 + vnoise3(p * 0.45 - drift * 1.7) * 0.35;
|
||||
n = mix(1.0, smoothstep(0.2, 0.8, n) * 1.8, uFogParams.z);
|
||||
return uFogColor.w * h * n;
|
||||
}
|
||||
|
||||
void main() {
|
||||
float d = texture(uDepth, vUV).r;
|
||||
vec3 wp = worldFromDepth(vUV, d);
|
||||
vec3 ro = uCamPos.xyz;
|
||||
vec3 rd = wp - ro;
|
||||
float dist = length(rd);
|
||||
rd /= dist;
|
||||
dist = min(dist, uFogParams2.y);
|
||||
|
||||
int steps = int(uFogParams2.z);
|
||||
float stepLen = dist / float(steps);
|
||||
float jitter = ign(gl_FragCoord.xy);
|
||||
|
||||
float cosT = dot(rd, uSunDir.xyz);
|
||||
// Dual lobe: strong forward scattering + a little back/side so shafts
|
||||
// still read when looking away from the sun. Normalized: isotropic = 1.
|
||||
float phase = (0.75 * phaseHG(cosT, uFogParams.w) + 0.25 * phaseHG(cosT, -0.25)) * 4.0 * PI;
|
||||
vec3 sunL = uSunColor.rgb * uSunDir.w * uFogParams2.x * phase;
|
||||
vec3 ambL = uFogColor.rgb * uSkyZenith.w;
|
||||
|
||||
vec3 scatter = vec3(0.0);
|
||||
float T = 1.0;
|
||||
for (int i = 0; i < steps; ++i) {
|
||||
vec3 p = ro + rd * ((float(i) + jitter) * stepLen);
|
||||
float dens = fogDensity(p);
|
||||
if (dens < 1e-5) continue;
|
||||
// Sparse beam mask: most sun scattering happens inside distinct shafts.
|
||||
float vis = sunShadowFast(p) * shaftCookie(p);
|
||||
vec3 S = (sunL * vis + ambL) * dens;
|
||||
for (int l = 0; l < uLightCount.y; ++l) { // warm haze around fires
|
||||
vec3 dl = uLightPos[l].xyz - p;
|
||||
float r = uLightPos[l].w;
|
||||
float att = max(1.0 - dot(dl, dl) / (r * r), 0.0);
|
||||
att *= att;
|
||||
S += uLightColor[l].rgb * att * att * dens * 0.35;
|
||||
}
|
||||
float Ts = exp(-dens * stepLen);
|
||||
scatter += T * S * (1.0 - Ts) / dens; // energy-conserving step integral
|
||||
T *= Ts;
|
||||
if (T < 0.01) break;
|
||||
}
|
||||
fragColor = vec4(scatter, T);
|
||||
}
|
||||
Reference in New Issue
Block a user