#version 430 compatibility
/* VertaLux - LPV STAGE 1: INJECTION ONLY (no propagation).
   For EACH LPV cell (128^3) it samples the cascade-0 voxels covering it (1 LPV cell = 2 voxels per
   axis since LPV_SCALE = 2*VOXEL_SCALE) and writes lightImg:
     - SOURCE (radiance, a=2) if an emissive voxel (voxel.a>1.5) falls inside (brightest wins);
     - SOLID (a=1) otherwise if a solid voxel (voxel.a>0.5) falls inside (blocks the Stage 2 flood);
     - EMPTY (0) otherwise.
   Auto-detected by Iris from the filename (composite slot). Runs after shadow (which voxelizes)
   and before composite1..composite5 (which read). No shaders.properties entry needed.
   Gated on EMISSIVE_LPV: at 0 the kernel returns immediately, so the fallback costs nothing. */
#include "/lib/settings.glsl"
#include "/lib/common.glsl"

layout(local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
const ivec3 workGroups = ivec3(16, 16, 16);   // 16*8 = 128 per axis

uniform vec3 cameraPosition;
layout(rgba16f) uniform image3D voxelImg;     // cascade-0 voxel grid (read)
layout(rgba16f) uniform image3D lightImg;     // LPV field (written)

#include "/lib/lpv.glsl"

void main() {
#if EMISSIVE_LPV == 0
    return; // LPV chain disabled -> no work at all (128^3 dispatch would just write zeros)
#endif
    ivec3 c = ivec3(gl_GlobalInvocationID);
    if (any(greaterThanEqual(c, ivec3(LPV_RES)))) return;
#if EMISSIVE_LPV == 1
    vec3 wc = lpvCellToWorld(c);
    vec3 bestE = vec3(0.0);
    bool isSrc = false;
    bool solid = false;
    // 8 sub-points (LPV cell corners) at +-0.5*VOXEL_SCALE: covers the 2x2x2 voxels underneath.
    for (int k = 0; k < 8; k++) {
        vec3 off = (vec3(k & 1, (k >> 1) & 1, (k >> 2) & 1) - 0.5) * VOXEL_SCALE;
        vec4 v = sampleVoxC0(wc + off);
        if (v.a > 1.5) { isSrc = true; if (luma(v.rgb) > luma(bestE)) bestE = v.rgb; }
        else if (v.a > 0.5) solid = true;
    }
    vec4 o;
    if (isSrc)      o = vec4(bestE, 2.0);            // SOURCE
    else if (solid) o = vec4(0.0, 0.0, 0.0, 1.0);    // SOLID (occludes the Stage 2 flood)
    else            o = vec4(0.0);                    // EMPTY
    imageStore(lightImg, c, o);
#endif
    // EMISSIVE_LPV=0 is handled by the early return above; no #else branch here.
}
