test(vulkan-rt): port RTVolume example to native Vulkan (#33)

Regression test for the procedural BLAS path: the same 3x3x3 grid of
unit-box AABBs runs through a PROCEDURAL_HIT_GROUP_KHR group whose GLSL
intersection shader (reportIntersectionEXT) turns each box into a
radius-1 sphere, the any-hit shader punches the spherical-checkerboard
cut-out (visible proof non-opaque geometry runs any-hit), and the
closest-hit shades per-instance tints — the WebGPU example behavior
reproduced natively. Fixed camera in raygen.glsl; the WebGPU/DOM path is
unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
catbot 2026-06-13 00:17:37 +00:00
commit 40c4184d41
8 changed files with 357 additions and 18 deletions

View file

@ -0,0 +1,38 @@
#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);
}