// MinecraftPT — IRC_CS (Irradiance Cache Update) // Updates the 3D irradiance cache: traces a few rays per cell toward the sky, // stores ambient + direct light contributions, blends over time. #include "/Lib/Settings.glsl" #include "/Lib/Utilities.glsl" #include "/Lib/BasicFunctions/LightingConstants.glsl" #include "/Lib/PathTracing/Voxelizer/VoxelProfile.glsl" #include "/Lib/PathTracing/Tracer/ShadowTracing.glsl" #include "/Lib/BasicFunctions/PrecomputedAtmosphere.glsl" #ifdef PT_IRC const ivec3 workGroups = ivec3(int(ceil(float(ircResolution) / 4.0))); layout (local_size_x = 4, local_size_y = 4, local_size_z = 4) in; layout (rgba16f) uniform writeonly image3D img_irradianceCache3D; layout (rgba16f) uniform readonly image3D img_irradianceCache3D_Alt; uniform sampler3D voxelData3D; void main(){ ivec3 texel = ivec3(gl_GlobalInvocationID.xyz); if (any(greaterThanEqual(texel, ivec3(ircResolution)))){ return; } // World position of this cache cell vec3 cellPos = (vec3(texel) + 0.5) / float(ircResolution); vec3 worldPos = (cellPos - 0.5) * voxelDistance + cameraPosition; // Voxel occupancy check — don't cache inside solid blocks vec3 voxelCoord = cellPos * voxelResolution; vec4 voxelData = texelFetch(voxelData3D, ivec3(clamp(voxelCoord, vec3(0.0), vec3(voxelResolution - 1.0))), 0); float voxelID = DecodeVoxelID(voxelData.z); if (voxelID > 1.0 && voxelID < 999.0){ // Solid — keep old value return; } // Sample sky irradiance from multiple directions (hemisphere) vec3 irradiance = vec3(0.0); for (int i = 0; i < PT_IRC_SPP; i++){ // Deterministic sample directions over hemisphere float phi = 6.28318 * hash1(vec3(texel) + float(i) * 1.7); float cosTheta = hash1(vec3(texel) * 2.0 + float(i) * 3.1); float sinTheta = sqrt(1.0 - cosTheta * cosTheta); vec3 dir = vec3(cos(phi) * sinTheta, cosTheta, sin(phi) * sinTheta); // Trace toward sky — if not blocked, add sky light vec3 voxelPos = WorldToVoxel(worldPos) + dir * 0.5; float visibility = SimpleShadowTracing(voxelPos, dir); // Sky radiance in this direction (analytic) vec3 skyRadiance = GetSkyRadiance(dir, GetSunDirWorld()); irradiance += skyRadiance * visibility; } irradiance /= float(PT_IRC_SPP); // Sun contribution (direct) vec3 sunDir = GetSunDirWorld(); float sunVis = SimpleShadowTracing(WorldToVoxel(worldPos), sunDir); irradiance += GetSunIrradiance() * sunVis * max(sunDir.y, 0.0); // Blend with previous (temporal smoothing), ping-pong by frame parity bool evenFrame = (frameCounter % 2) == 0; vec3 prev = evenFrame ? texelFetch(img_irradianceCache3D_Alt, texel, 0).rgb : texelFetch(img_irradianceCache3D, texel, 0).rgb; irradiance = mix(prev, irradiance, PT_IRC_BLENDWEIGHT); if (evenFrame){ imageStore(img_irradianceCache3D, texel, vec4(irradiance, 1.0)); }else{ imageStore(img_irradianceCache3D_Alt, texel, vec4(irradiance, 1.0)); } } #endif