#version 460
#extension GL_EXT_ray_tracing : enable

// RTVolume closest-hit — shades the committed procedural sphere hit by
// its surface normal with a fixed sun + ambient, tinted per instance
// (gl_InstanceCustomIndexEXT). Mirrors closesthit.wgsl on the WebGPU
// path.

hitAttributeEXT vec2 attribs;
layout(location = 0) rayPayloadInEXT vec3 hitValue;

const vec3 SUN_DIR_TO_LIGHT = vec3(0.40, 0.85, 0.35);
const vec3 SUN_COLOR        = vec3(1.20, 1.10, 0.95);
const vec3 AMBIENT_COLOR    = vec3(0.16, 0.18, 0.24);

vec3 instanceAlbedo(uint i) {
    uint h = i * 2654435761u;
    return vec3(
        0.35 + 0.6 * float((h >>  0) & 255u) / 255.0,
        0.35 + 0.6 * float((h >>  8) & 255u) / 255.0,
        0.35 + 0.6 * float((h >> 16) & 255u) / 255.0);
}

void main() {
    // Object-space hit point on the unit sphere is its object-space
    // normal; gl_ObjectToWorldEXT's rotation part takes it to world.
    vec3 posObj = gl_ObjectRayOriginEXT + gl_ObjectRayDirectionEXT * gl_HitTEXT;
    vec3 nObj   = normalize(posObj);
    vec3 nWorld = normalize(gl_ObjectToWorldEXT * vec4(nObj, 0.0));

    vec3  albedo  = instanceAlbedo(uint(gl_InstanceCustomIndexEXT));
    vec3  viewDir = -gl_WorldRayDirectionEXT;
    vec3  nFacing = dot(nWorld, viewDir) > 0.0 ? nWorld : -nWorld;
    vec3  sunDir  = normalize(SUN_DIR_TO_LIGHT);
    float nDotL   = max(0.0, dot(nFacing, sunDir));

    hitValue = albedo * (AMBIENT_COLOR + SUN_COLOR * nDotL);
}
