Crafter.Graphics/examples/RTVolume/closesthit.glsl

41 lines
1.5 KiB
Text
Raw Normal View History

2026-07-22 18:09:06 +02:00
//SPDX-License-Identifier: MIT
//SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
#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);
}