130 lines
4.0 KiB
GLSL
130 lines
4.0 KiB
GLSL
#include "/Lib/Settings.glsl"
|
|
#include "/Lib/Utilities.glsl"
|
|
// MinecraftPT — Shadow Tracing
|
|
// Direct sunlight shadow rays: march from surface toward the sun through the
|
|
// voxel grid. Soft penumbra via distance-weighted ray length.
|
|
|
|
#ifndef SHADOW_TRACING_GLSL
|
|
#define SHADOW_TRACING_GLSL
|
|
|
|
#include "/Lib/PathTracing/Tracer/TracingUtilities.glsl"
|
|
|
|
float ShadowTracing(vec3 viewPos, vec3 worldPos, vec3 vertexNormal, vec3 lightVector, float lightMap){
|
|
float shadow = 1.0;
|
|
|
|
vec3 voxelPos = WorldToVoxel(worldPos);
|
|
voxelPos += vertexNormal * (-viewPos.z * 0.0003);
|
|
|
|
if (clamp(voxelPos, vec3(0.0), vec3(voxelResolution)) == voxelPos){
|
|
lightMap = saturate(1.0 - lightMap * 2.0);
|
|
vec2 shadowWeight = vec2(
|
|
4.0 - 2.0 * saturate(lightMap - viewPos.z * 0.01),
|
|
0.2 + 0.5 * saturate(lightMap - viewPos.z * 0.01)
|
|
);
|
|
|
|
Ray ray = PackRay(voxelPos, lightVector);
|
|
|
|
vec3 voxelCoord = floor(ray.ori);
|
|
vec3 totalStep = (ray.sdir * (voxelCoord - ray.ori + 0.5) + 0.5) * abs(ray.rdir);
|
|
float rayLength = 0.0;
|
|
vec3 tracingNext;
|
|
|
|
bool hit = false;
|
|
|
|
for (int i = 0; i < 64; i++){
|
|
if (clamp(voxelCoord, vec3(0.0), vec3(voxelResolution - 0.5)) != voxelCoord) break;
|
|
|
|
vec4 voxelData = texelFetch(voxelData3D, ivec3(voxelCoord), 0);
|
|
float voxelID = DecodeVoxelID(voxelData.z);
|
|
|
|
// Full block or cutout shape
|
|
if (voxelID >= 999.0){
|
|
hit = rayLength > 0.0;
|
|
}else if (voxelID < 1000.0 && voxelID > 1.0){
|
|
float rawID = 1000.0 - voxelID;
|
|
rayLength = minVec3(totalStep);
|
|
hit = HitShape_Lite(ray, voxelCoord, rawID, rayLength);
|
|
}
|
|
|
|
if (hit){
|
|
shadow = saturate((rayLength - shadowWeight.y) * shadowWeight.x);
|
|
break;
|
|
}
|
|
|
|
// Sparse skip
|
|
float marker = voxelData.z;
|
|
if (marker > 0.60 && marker < 0.92){
|
|
float skipSize = marker > 0.90 ? 8.0 : (marker > 0.70 ? 4.0 : 2.0);
|
|
vec3 nextBoundary = floor((voxelCoord + 1.0) / skipSize) * skipSize;
|
|
vec3 distToBoundary = (nextBoundary - voxelCoord) * abs(ray.rdir);
|
|
float tSkip = minVec3(distToBoundary) + 1e-4;
|
|
rayLength += tSkip;
|
|
vec3 stepVec = ray.sdir * abs(ray.rdir) * tSkip;
|
|
ray.ori += stepVec;
|
|
voxelCoord = floor(ray.ori);
|
|
totalStep = (ray.sdir * (voxelCoord - ray.ori + 0.5) + 0.5) * abs(ray.rdir);
|
|
continue;
|
|
}
|
|
|
|
rayLength = minVec3(totalStep);
|
|
tracingNext = step(totalStep, vec3(rayLength));
|
|
voxelCoord += tracingNext * ray.sdir;
|
|
totalStep += tracingNext * abs(ray.rdir);
|
|
}
|
|
}
|
|
|
|
return shadow;
|
|
}
|
|
|
|
// Simplified version for IRC / light sampling (no soft penumbra)
|
|
float SimpleShadowTracing(vec3 voxelPos, vec3 lightVector){
|
|
Ray ray = PackRay(voxelPos, lightVector);
|
|
|
|
vec3 voxelCoord = floor(ray.ori);
|
|
vec3 totalStep = (ray.sdir * (voxelCoord - ray.ori + 0.5) + 0.5) * abs(ray.rdir);
|
|
float rayLength = 0.0;
|
|
vec3 tracingNext;
|
|
|
|
bool hit = false;
|
|
|
|
for (int i = 0; i < 64; i++){
|
|
if (clamp(voxelCoord, vec3(0.0), vec3(voxelResolution - 0.5)) != voxelCoord) break;
|
|
|
|
vec4 voxelData = texelFetch(voxelData3D, ivec3(voxelCoord), 0);
|
|
float voxelID = DecodeVoxelID(voxelData.z);
|
|
|
|
if (voxelID >= 999.0){
|
|
hit = rayLength > 0.0;
|
|
}else if (voxelID < 1000.0 && voxelID > 1.0){
|
|
float rawID = 1000.0 - voxelID;
|
|
rayLength = minVec3(totalStep);
|
|
hit = HitShape_Lite(ray, voxelCoord, rawID, rayLength);
|
|
}
|
|
|
|
if (hit) break;
|
|
|
|
// Sparse skip
|
|
float marker = voxelData.z;
|
|
if (marker > 0.60 && marker < 0.92){
|
|
float skipSize = marker > 0.90 ? 8.0 : (marker > 0.70 ? 4.0 : 2.0);
|
|
vec3 nextBoundary = floor((voxelCoord + 1.0) / skipSize) * skipSize;
|
|
vec3 distToBoundary = (nextBoundary - voxelCoord) * abs(ray.rdir);
|
|
float tSkip = minVec3(distToBoundary) + 1e-4;
|
|
rayLength += tSkip;
|
|
vec3 stepVec = ray.sdir * abs(ray.rdir) * tSkip;
|
|
ray.ori += stepVec;
|
|
voxelCoord = floor(ray.ori);
|
|
totalStep = (ray.sdir * (voxelCoord - ray.ori + 0.5) + 0.5) * abs(ray.rdir);
|
|
continue;
|
|
}
|
|
|
|
rayLength = minVec3(totalStep);
|
|
tracingNext = step(totalStep, vec3(rayLength));
|
|
voxelCoord += tracingNext * ray.sdir;
|
|
totalStep += tracingNext * abs(ray.rdir);
|
|
}
|
|
|
|
return float(!hit);
|
|
}
|
|
|
|
#endif |