#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_shader_image_load_formatted : enable
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable
#extension GL_EXT_descriptor_heap : enable
#extension GL_EXT_nonuniform_qualifier : enable

// Specialization constant set from descriptorHeap.bufferStartElement —
// shared with closesthit.glsl. The TLAS lives at descriptor_heap slot
// `bufferStart` (it's an SSBO-typed entry), the per-frame output image
// at heap slot 0.
layout(constant_id = 0) const uint16_t bufferStart = 0us;
layout(descriptor_heap) uniform accelerationStructureEXT topLevelAS[];
layout(descriptor_heap) uniform writeonly image2D image[];

layout(location = 0) rayPayloadEXT vec3 hitValue;

void main() {
    uvec2 pixel      = gl_LaunchIDEXT.xy;
    uvec2 resolution = gl_LaunchSizeEXT.xy;
    vec2  uv         = (vec2(pixel) + 0.5) / vec2(resolution);
    vec2  ndc        = uv * 2.0 - 1.0;

    // Camera positioned to look down the Sponza atrium axis. Sponza-OBJ
    // from McGuire's archive is roughly 30 units wide × 13 tall × 18 deep,
    // axis-aligned, with the floor near y=0 and the atrium centered on
    // origin. -X faces the long end, so we sit inside looking +X.
    vec3  origin    = vec3(-10.0, 5.0, 0.0);
    float aspect    = float(resolution.x) / float(resolution.y);
    float fov       = radians(70.0);
    float tanHalf   = tan(fov * 0.5);
    vec3  direction = normalize(vec3(
        ndc.x * aspect * tanHalf,
        -ndc.y * tanHalf,
        1.0));

    // Rotate +Z forward → +X forward (90° about Y).
    direction = vec3(direction.z, direction.y, -direction.x);

    traceRayEXT(
        topLevelAS[bufferStart],
        gl_RayFlagsNoneEXT,
        0xff,
        0, 0, 0,
        origin,
        0.001,
        direction,
        10000.0,
        0);

    imageStore(image[0], ivec2(pixel), vec4(hitValue, 1.0));
}
