// RTVolume closest-hit (runs in SHADE). Shades the procedural sphere by // its surface normal with a fixed sun + ambient, tinted per instance. // // Payload declared here so the assembler sees it before wfPayload / SHADE. struct Payload { color: vec3, }; const SUN_DIR_TO_LIGHT: vec3 = vec3(0.40, 0.85, 0.35); const SUN_COLOR: vec3 = vec3(1.20, 1.10, 0.95); const AMBIENT_COLOR: vec3 = vec3(0.16, 0.18, 0.24); fn instanceAlbedo(i: u32) -> vec3 { let h = i * 2654435761u; return vec3( 0.35 + 0.6 * f32((h >> 0u) & 255u) / 255.0, 0.35 + 0.6 * f32((h >> 8u) & 255u) / 255.0, 0.35 + 0.6 * f32((h >> 16u) & 255u) / 255.0); } fn closesthit_main(ray: RayDesc, hit: HitInfo, payload: ptr) { // Object-space hit point on the unit sphere is its object-space normal. let posObj = hit.objectRayOrigin + hit.objectRayDirection * hit.t; let nObj = normalize(posObj); let nWorld = normalize(vec3( dot(hit.objectToWorldR0.xyz, nObj), dot(hit.objectToWorldR1.xyz, nObj), dot(hit.objectToWorldR2.xyz, nObj))); let albedo = instanceAlbedo(hit.customIndex); let viewDir = -ray.direction; let nFacing = select(-nWorld, nWorld, dot(nWorld, viewDir) > 0.0); let sunDir = normalize(SUN_DIR_TO_LIGHT); let nDotL = max(0.0, dot(nFacing, sunDir)); rtAccumulate(albedo * (AMBIENT_COLOR + SUN_COLOR * nDotL)); }