The traverser shader checks if the current voxel contains elements (triangles). If triangles are found, the ray is set to a “wait” state, those triangles are ready to be checked for intersection, but during ray traversal there is nothing more to do, they are rejected for further traversal operations. If current voxel is empty, next voxel will be calculated using the voxel traversal program. The information if triangles are in voxels, is stored in the “Voxel Index” texture. A value of -1 means there are no triangles to check, otherwise it contains a value pointing to a “Grid Element” Texture, containing the list of triangles for that voxel. If the end of the grid is reached, the ray is set to a “overflow” state and is not processed anymore.
Ray States| state-name | state # | description |
| active | -10 |
traverse Grid |
| wait | >= 0 |
ready to check intersections. |
| dead | -50 |
ray doesn’t hit grid (was already rejected in voxel precalculation) |
| inactive | -20 |
a valid hit point was found |
| overflow | -30 |
traversal left voxel space (no valid hits) |
float intersect(Ray r, Triangle tri, out vec4 ret)
{
vec3 edge1, edge2, tvec, pvec, qvec;
float det;
float result = -1.0;
ret = vec4(0.0,0.0,0.0,0.0);
qvec = vec3(0.0,0.0,0.0);
edge1 = tri.B-tri.A;
edge2 = tri.C-tri.A;
pvec = cross(r.direction, edge2);
det = dot(edge1, pvec);
if (det > _EPSILON_)
{
result = 1.0;
tvec = r.startpoint - tri.A;
ret.x = dot(tvec, pvec);
if (ret.x < 0.0 || ret.x > det) result = -1.0;
if (result > 0.0)
{
qvec = cross(tvec, edge1);
ret.y = dot(r.direction, qvec);
if ((ret.y < 0.0) || ((ret.x + ret.y) > det)) result = -1.0;
}
}
if (det < -_EPSILON_)
{
result = 1.0;
tvec = r.startpoint - tri.A;
ret.x = dot(tvec, pvec);
if (ret.x > 0.0 || ret.x < det) result = -1.0;
if (result > 0.0)
{
qvec = cross(tvec, edge1);
ret.y = dot(r.direction, qvec);
if ((ret.y > 0.0) || ((ret.x + ret.y) < det)) result = -1.0;
}
}
if (result > 0.0)
{
ret.z = dot(edge2, qvec);
ret /= det;
}
if (ret.z<_EPSILON_) result = -1.0;
return result;
}
//-----------------------------------------------
// return value: |
// Voxel coordinates -> world coordinates // World Coordinates Voxel (start- and end-point) // Calculate texture coordinate of array element (2D Texture -> 1D Array) |
void intersect_check(inout Ray r, inout Triangle tri, inout vec4 raydir, inout vec4 raypos,
inout vec4 voxel, inout vec4 uvt)
vec3 intersect_result;
float intersecttest = intersect(r,tri, intersect_result);
// calculate voxel bounds
vec3 v1 = voxel.xyz * _len + g1; //voxelbounds(voxel.xyz, v1, v2);
vec3 v2 = v1 + _len;
vec3 hitpoint = raypos.xyz + raydir.xyz*intersect_result.z;
bool c0 = inbox(hitpoint, v1,v2);
bool c1 = (uvt.z >= intersect_result.z);
bool c2 = (intersecttest > 0.0);
bool c3 = (elementnum != raypos.w); // don't test same element twice
bool c4 = c0 && c1 && c2 && c3;
if (c4)
{
uvt.xyz = intersect_result.xyz;
uvt.w = elementnum;
raypos.w = elementnum;
}
}
} |