Skip to content

Instantly share code, notes, and snippets.

@ALEXMORF
Created April 1, 2020 07:05
Show Gist options
  • Save ALEXMORF/218443f22c8e52e2ffcb09f7e642cb96 to your computer and use it in GitHub Desktop.
Save ALEXMORF/218443f22c8e52e2ffcb09f7e642cb96 to your computer and use it in GitHub Desktop.
ray_result RayTraceBottomLevel(float3 Ro, float3 Rd, float3 InvRd,
bool StopOnAnyHit,
ray_result RayState, uint Stack[STACK_SIZE],
int StackIndex,
RWStructuredBuffer<bvh_node> BLASBuffer,
RWStructuredBuffer<prim> PrimBuffer,
int InstanceIndex,
int NodeOffset, int PrimOffset)
{
int StackBase = StackIndex;
int Cursor = StackBase;
Stack[++Cursor] = 0;
while (Cursor > StackBase)
{
uint NodeIndex = Stack[Cursor--];
bvh_node Node = BLASBuffer[NodeOffset+NodeIndex];
uint PrimCount = GetPrimCount(Node.Data);
float BoxT = RayIntersectBox(Ro, InvRd, Node.Min, Node.Max);
if (BoxT < RayState.ClosestT)
{
if (PrimCount == 0) // internal node
{
uint Axis = GetAxis(Node.Data);
if (Rd[Axis] > 0.0)
{
Stack[++Cursor] = Node.Offset;
Stack[++Cursor] = NodeIndex + 1;
}
else
{
Stack[++Cursor] = NodeIndex + 1;
Stack[++Cursor] = Node.Offset;
}
}
else // instance leaf
{
for (int PrimI = 0; PrimI < PrimCount; ++PrimI)
{
prim P = PrimBuffer[PrimOffset+Node.Offset+PrimI];
float3 Res = RayIntersectTri(Ro, Rd,
P.Verts[0],
P.Verts[1],
P.Verts[2]);
float T = Res.x;
if (T > 0.0 && T < RayState.ClosestT)
{
RayState.ClosestT = T;
RayState.InstanceIndex = InstanceIndex;
RayState.PrimID = P.ID;
RayState.UV = Res.yz;
if (StopOnAnyHit)
{
return RayState;
}
}
}
}
}
}
return RayState;
}
ray_result RayTraceTwoLevel(float3 Ro, float3 Rd, float3 InvRd,
float Extent,
bool StopOnAnyHit,
StructuredBuffer<bvh_node> TLASBuffer,
StructuredBuffer<instance> InstanceBuffer,
RWStructuredBuffer<bvh_node> BLASBuffer,
RWStructuredBuffer<prim> PrimBuffer)
{
ray_result RayState = InitRayResult();
RayState.ClosestT = Extent;
uint Stack[STACK_SIZE];
int Cursor = -1;
Stack[++Cursor] = 0;
while (Cursor >= 0 && Cursor < STACK_SIZE)
{
uint NodeIndex = Stack[Cursor--];
bvh_node Node = TLASBuffer[NodeIndex];
uint PrimCount = GetPrimCount(Node.Data);
float BoxT = RayIntersectBox(Ro, InvRd, Node.Min, Node.Max);
if (BoxT < RayState.ClosestT)
{
if (PrimCount == 0) // internal node
{
uint Axis = GetAxis(Node.Data);
if (Rd[Axis] > 0.0)
{
Stack[++Cursor] = Node.Offset;
Stack[++Cursor] = NodeIndex + 1;
}
else
{
Stack[++Cursor] = NodeIndex + 1;
Stack[++Cursor] = Node.Offset;
}
}
else // instance leaf
{
int InstanceIndex = Node.Offset;
instance Instance = InstanceBuffer[InstanceIndex];
float3 InstanceRo = mul(float4(Ro, 1.0), Instance.InvT.Data).xyz;
float3 InstanceRd = mul(float4(Rd, 0.0), Instance.InvT.Data).xyz;
float3 InstanceInvRd = rcp(InstanceRd);
RayState = RayTraceBottomLevel(InstanceRo, InstanceRd,
InstanceInvRd,
StopOnAnyHit,
RayState,
Stack, Cursor,
BLASBuffer, PrimBuffer,
InstanceIndex,
Instance.NodeOffset,
Instance.PrimOffset);
if (StopOnAnyHit && RayState.ClosestT < Extent)
{
return RayState;
}
}
}
}
return RayState;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment