Last active
April 18, 2021 08:29
-
-
Save rbnelr/f3fe704b706c56048337b58c1ee44260 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// flip coordinate space such that ray is always positive (simplifies stepping logic) | |
// keep track of flip via flipmask | |
bool3 ray_neg = dir < 0.0; | |
float3 flipped = ray_neg ? -pos : pos; | |
int3 flipmask = ray_neg ? -1 : 0; | |
float3 absDir = abs(dir); | |
float dist = 0.0; | |
int skipLOD = 0; | |
// get initial coordinate based on flipped coordinate | |
int3 mapPos = floor(flipped); | |
mapPos &= 0xffffffff << skipLOD; | |
for (;;) { | |
int3 unflipped = (mapPos ^ flipmask) >> skipLOD; // unflipped mapPos shifted down for texture indexing | |
// read octree cell at unflipped coord with current skipLOD | |
int voxel = texelFetch(octree, unflipped, skipLOD).r; | |
if (voxel != AIR) { | |
// non-air octree cell | |
if (skipLOD == 0) | |
break; // found solid leaf voxel | |
// decend octree | |
skipLOD--; | |
int3 mid_planes = mapPos + (1 << skipLOD); | |
// upate coord by determining which child octant is entered first | |
// by comparing ray hit against middle plane hits | |
float3 tmidv = ((float3)mid_planes - flipped) / absDir; | |
mapPos = tmidv < hitDistance.xxx ? mid_planes : mapPos; | |
// have decended one level of the octree, instead of stepping | |
// go back repeat outer loop until fully air cell is found or non-air leaf voxel is found | |
} else { | |
float3 exit_planes = mapPos + rayMoveIterations; | |
float3 exit_distances = (exit_planes - flipped) / absDir; | |
hitDistance = min(min(exit_distances.x, exit_distances.y), exit_distances.z); | |
// step on axis where exit distance is lowest | |
int stepcoord; | |
if (t0v.x == dist) { | |
mapPos.x = exit_planes.x; | |
stepcoord = mapPos.x; | |
} else if (t0v.y == dist) { | |
mapPos.y = exit_planes.y; | |
stepcoord = mapPos.y; | |
} else { | |
mapPos.z = exit_planes.z; | |
stepcoord = mapPos.z; | |
} | |
// step up to highest changed octree parent cell | |
mip = firstbitlow(stepcoord); | |
// round down mapPos to lower corner of (potential) parent cell | |
mapPos &= ROUNDMASK << mip; | |
rayDistance--; | |
//// exit when either stepped out of world or max ray dist reached | |
insideBounds = rayDistance > 0 && | |
mapPos.x < (dir.x < 0 ? 0 : _WorldBounds.x) && | |
mapPos.y < (dir.y < 0 ? 0 : _WorldBounds.y) && | |
mapPos.z < (dir.z < 0 ? 0 : _WorldBounds.z); | |
} | |
} | |
// handle hit |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment