#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)); }