100 lines
3.0 KiB
HLSL
100 lines
3.0 KiB
HLSL
|
|
/*
|
|
* origin: Point hit on the node
|
|
* dir: Camera view direction (ray direction)
|
|
* incAxis: Last axis that was used to increment position
|
|
* addr: Number given by node, brick offset in brick array
|
|
*/
|
|
vec4 castBricks(vec3 origin, vec3 start, vec3 dir, vec3 incAxis, uint addr)
|
|
{
|
|
vec3 o = origin;
|
|
|
|
// Change scale
|
|
origin = start - origin;
|
|
origin += dir*0.00001;
|
|
origin *= 32;
|
|
|
|
// Same as in casting nodes
|
|
vec3 pos = floor(origin);
|
|
vec3 rayInv = 1.0/dir;
|
|
vec3 raySign = sign(dir);
|
|
vec3 dist = (pos-origin+0.5 + raySign*0.5) * rayInv;
|
|
ivec3 offset = ivec3(0, 0, (addr-1)*32);
|
|
|
|
for(int i=0;i<110;i++)
|
|
{
|
|
// Get brick
|
|
uint brick = texelFetch(_BricksTexture, offset+ivec3(pos), 0).r;
|
|
if(brick != 0)
|
|
{
|
|
// Hit point
|
|
vec3 mini = (pos-origin+0.5 - raySign*0.5) * rayInv;
|
|
float len = max(mini.x, max(mini.y, mini.z));
|
|
vec3 hitPoint = (origin + dir * len) / 32.0 + o;
|
|
|
|
// Normal vector (negate previous increment axis and mult by sign)
|
|
vec3 normal = -incAxis * raySign;
|
|
return vec4(solve(hitPoint, dir, normal, brick-1), 1.0);
|
|
}
|
|
|
|
// Get new closest axis to increment
|
|
incAxis = step(dist.xyz, dist.yzx) * step(dist.xyz, dist.zxy);
|
|
dist += incAxis * raySign * rayInv;
|
|
pos += incAxis * raySign;
|
|
|
|
// Check for bounds
|
|
if(pos.x < 0 || pos.y < 0 || pos.z < 0) { break; }
|
|
if(pos.x > 31 || pos.y > 31 || pos.z > 31) { break; }
|
|
}
|
|
|
|
return vec4(1.0,0.0,0.5,0.0);
|
|
}
|
|
|
|
/*
|
|
* origin: Camera position
|
|
* dir: Ray coming from camera position going through currently drawn pixel
|
|
*/
|
|
vec3 castNodes(vec3 origin, vec3 dir)
|
|
{
|
|
// Round input pos to nearest voxel
|
|
vec3 pos = floor(origin);
|
|
// Inverse ray direction
|
|
vec3 rayInv = 1.0/dir;
|
|
// Sign of the ray direction, to know where to increment pos
|
|
vec3 raySign = sign(dir);
|
|
// Distance to next voxel in grid
|
|
vec3 dist = (pos-origin+0.5 + raySign*0.5) * rayInv;
|
|
|
|
// Closest axis to increment in grid will be stored here (x=1 or y=1 or z=1)
|
|
vec3 incAxis = vec3(0,0,0);
|
|
|
|
// Iterate
|
|
for(int i=0;i<110;i++)
|
|
{
|
|
// Get node
|
|
uint node = texelFetch(_NodesTexture, ivec3(pos), 0).r;
|
|
if(node != 0)
|
|
{
|
|
// Hit point
|
|
vec3 mini = (pos-origin+0.5 - raySign*0.5) * rayInv;
|
|
float len = max(0.0, max(mini.x, max(mini.y, mini.z)));
|
|
vec3 hitPoint = origin + dir * len;
|
|
|
|
// Cast brick
|
|
vec4 result = castBricks(pos, hitPoint, dir, incAxis, node);
|
|
if(result.a > 0.0) return result.rgb;
|
|
}
|
|
|
|
// Get new closest axis to increment
|
|
incAxis = step(dist.xyz, dist.yzx) * step(dist.xyz, dist.zxy);
|
|
dist += incAxis * raySign * rayInv;
|
|
pos += incAxis * raySign;
|
|
|
|
// Outside bounds
|
|
//if(pos.x < 0 || pos.y < 0 || pos.z < 0) { break; }
|
|
// if(pos.x > 1 || pos.y > 1 || pos.z > 1) { break; }
|
|
}
|
|
|
|
// Not found
|
|
return vec3(0.0, 0.0, 0.0);
|
|
} |