pub const PROBE_COMMON: &str = "// Reflection-probe sampling, spliced into a shader at its PROBE_COMMON marker\n// (see slang_source.rs). The second half of the probe splice: PROBE_TYPES\n// declares the records ahead of a shader\'s bindings, this reads the bound set.\n//\n// Two hooks the including shader must provide, because both differ per binding\n// model: `PROBE_SET` names the bound ProbeSet, and `probe_cube_sample_bias`\n// samples probe cube `i` (the cube array is combined on Metal and Vulkan,\n// split into an array plus one sampler on DXIL). Nothing here may spell either\n// marker -- the splice would reintroduce it.\n\n// Box-parallax sample of probe cube `i`: intersect the world-space reflection\n// ray with the probe\'s influence box and re-anchor the sample direction at that\n// hit relative to the capture point, so a static captured cube tracks a moving\n// camera. Falls back to the raw ray when the probe has no baked box\n// (box_min.w <= 0.5) or the box does not lie ahead of the ray. `lod` rides as\n// the texture bias, the same semantics the prefilter-cube tap uses.\nfloat3 sample_probe_radiance(uint i, ProbeUniforms probe, float3 world_pos, float3 R, float lod)\n{\n float3 sample_dir = R;\n if (probe.box_min.w > 0.5)\n {\n float3 inv_r = 1.0 / R;\n float3 t_max = (probe.box_max.xyz - world_pos) * inv_r;\n float3 t_min = (probe.box_min.xyz - world_pos) * inv_r;\n float3 t_far = max(t_max, t_min);\n float dist = min(min(t_far.x, t_far.y), t_far.z);\n if (dist > 0.0)\n {\n float3 hit = world_pos + R * dist;\n sample_dir = hit - probe.probe_pos.xyz;\n }\n }\n return probe_cube_sample_bias(i, sample_dir, lod);\n}\n\n// Blend weight of probe `i` at `world_pos`: 1 deep inside its influence box, 0.5\n// on the surface, 0 a margin outside. The margin scales with the box, so a small\n// probe fades over a short distance and a room-sized one over a longer one.\nfloat probe_weight(uint i, float3 world_pos)\n{\n float3 c = 0.5 * (PROBE_SET.probes[i].box_min.xyz + PROBE_SET.probes[i].box_max.xyz);\n float3 he = 0.5 * (PROBE_SET.probes[i].box_max.xyz - PROBE_SET.probes[i].box_min.xyz);\n // Signed distance to the box surface: positive inside, negative out.\n float3 q = abs(world_pos - c) - he;\n float sd = -(length(max(q, float3(0.0))) + min(max(q.x, max(q.y, q.z)), 0.0));\n float margin = max(PROBE_BLEND_MARGIN * min(he.x, min(he.y, he.z)), 1e-4);\n return smoothstep(-margin, margin, sd);\n}\n\n// Whether any probe\'s influence reaches `world_pos`.\n//\n// A caller that has a sky tier below the probe set should consult this rather\n// than reading `PROBE_SET.count` alone: `probe_set_specular`\'s no-coverage\n// fallback is the nearest probe by capture distance, with no distance or\n// box-size limit, so for a surface far outside every box it returns a capture of\n// somewhere else entirely. A wide pool with the world\'s only probe inside a crate\n// floating over it is the case that found this. The sky is the better answer\n// there, and this is what lets the caller pick it.\nbool probe_set_covers(float3 world_pos)\n{\n for (uint i = 0u; i < PROBE_SET.count; i++)\n {\n if (probe_weight(i, world_pos) > 0.0)\n {\n return true;\n }\n }\n return false;\n}\n\n// Probe radiance for `world_pos` along world-space ray `R`, blended across\n// every probe covering the point (partition of unity); the result is the\n// weight-normalised sum of each probe\'s box-projected sample. Where no box\n// covers, falls back to the nearest probe by capture distance -- see\n// `probe_set_covers` for when a caller should avoid asking at all.\nfloat3 probe_set_specular(float3 world_pos, float3 R, float lod)\n{\n float3 acc = float3(0.0);\n float wsum = 0.0;\n float near_d = 1e30;\n uint near_i = 0u;\n for (uint i = 0u; i < PROBE_SET.count; i++)\n {\n float w = probe_weight(i, world_pos);\n if (w > 0.0)\n {\n acc += w * sample_probe_radiance(i, PROBE_SET.probes[i], world_pos, R, lod);\n wsum += w;\n }\n float d = distance(world_pos, PROBE_SET.probes[i].probe_pos.xyz);\n if (d < near_d)\n {\n near_d = d;\n near_i = i;\n }\n }\n if (wsum > 0.0)\n {\n return acc / wsum;\n }\n return sample_probe_radiance(near_i, PROBE_SET.probes[near_i], world_pos, R, lod);\n}\n";Expand description
probe_common.slang.