Advertisement
Zgragselus

MultiLevelBVH Traversal

Apr 11th, 2021
315
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.78 KB | None | 0 0
  1. struct TopLevelNode
  2. {
  3.     unsigned int bvh_index;
  4.     unsigned int pad[3];
  5.     float4 mat0;
  6.     float4 mat1;
  7.     float4 mat2;
  8.     float4 mat3;
  9. };
  10.  
  11. // Transform vector with a 4x4 matrix.
  12. float4 mul4x1(float4 vec, float4 mat0, float4 mat1, float4 mat2, float4 mat3)
  13. {
  14.     float4 out;
  15.  
  16.     // Assume vec.w = 1 to save a multiplication
  17.     out.x = mat0.x * vec.x + mat1.x * vec.y + mat2.x * vec.z + mat3.x;
  18.     out.y = mat0.y * vec.x + mat1.y * vec.y + mat2.y * vec.z + mat3.y;
  19.     out.z = mat0.z * vec.x + mat1.z * vec.y + mat2.z * vec.z + mat3.z;
  20.     out.w = 1.0f;
  21.  
  22.     return out;
  23. }
  24.  
  25. // Transform vector with a 3x3 rotation matrix.
  26. // This function ignores the 4 row/col of the matrix.
  27. float4 mul3x1(float4 vec, float4 mat0, float4 mat1, float4 mat2)
  28. {
  29.     float4 out;
  30.  
  31.     out.x = mat0.x * vec.x + mat1.x * vec.y + mat2.x * vec.z;
  32.     out.y = mat0.y * vec.x + mat1.y * vec.y + mat2.y * vec.z;
  33.     out.z = mat0.z * vec.x + mat1.z * vec.y + mat2.z * vec.z;
  34.     out.w = 0.0f;
  35.    
  36.     return out;
  37. }
  38.  
  39. float4 TraceRay_MultiLevel(float4 ray_origin,
  40.     float4 ray_direction,
  41.     __global float4* triangles,
  42.     __global struct BVHStackNode* nodes,
  43.     __global unsigned int* indices,
  44.     __global struct TopLevelNode* toplevelData)
  45. {
  46.     float4 o = ray_origin;
  47.     float4 d = ray_direction;
  48.     float4 inv = native_recip(d);
  49.     float4 oinv = o * inv;
  50.    
  51.     int stack[BVH_STACK_SIZE];
  52.     int stack_ptr = 0;
  53.     int meshbvh_stack_ptr = -1;
  54.     stack[stack_ptr] = 0xffffffff;
  55.     int node_id = 0;
  56.  
  57.     float tmin = 0.0f;
  58.     float tmax = 10000.0f;
  59.     float bU = 0.0f;
  60.     float bV = 0.0f;
  61.     float dist = tmax;
  62.  
  63.     float leaf = 0.0f;
  64.     int id = -1;
  65.  
  66.     do
  67.     {
  68.         __global struct BVHStackNode* n = &(nodes[node_id]);
  69.         int prim_count = n->prim_count;
  70.  
  71.         // Interior node
  72.         if (prim_count == 0)
  73.         {
  74.             // Fetch children bounding boxes
  75.             float4 n0xy = n->n0xy;
  76.             float4 n1xy = n->n1xy;
  77.             float4 nz = n->nz;
  78.  
  79.             // Test against child AABBs
  80.             float c0lox = n0xy.x * inv.x - oinv.x;
  81.             float c0hix = n0xy.y * inv.x - oinv.x;
  82.             float c0loy = n0xy.z * inv.y - oinv.y;
  83.             float c0hiy = n0xy.w * inv.y - oinv.y;
  84.             float c0loz = nz.x   * inv.z - oinv.z;
  85.             float c0hiz = nz.y   * inv.z - oinv.z;
  86.             float c1loz = nz.z   * inv.z - oinv.z;
  87.             float c1hiz = nz.w   * inv.z - oinv.z;
  88.             float c0min = max(max(min(c0lox, c0hix), min(c0loy, c0hiy)), max(min(c0loz, c0hiz), tmin));
  89.             float c0max = min(min(max(c0lox, c0hix), max(c0loy, c0hiy)), min(max(c0loz, c0hiz), tmax));
  90.             float c1lox = n1xy.x * inv.x - oinv.x;
  91.             float c1hix = n1xy.y * inv.x - oinv.x;
  92.             float c1loy = n1xy.z * inv.y - oinv.y;
  93.             float c1hiy = n1xy.w * inv.y - oinv.y;
  94.             float c1min = max(max(min(c1lox, c1hix), min(c1loy, c1hiy)), max(min(c1loz, c1hiz), tmin));
  95.             float c1max = min(min(max(c1lox, c1hix), max(c1loy, c1hiy)), min(max(c1loz, c1hiz), tmax));
  96.  
  97.             bool traverseChild0 = (c0max >= c0min);
  98.             bool traverseChild1 = (c1max >= c1min);
  99.            
  100.             // If no children was hit, get node from stack
  101.             if (!traverseChild0 && !traverseChild1)
  102.             {
  103.                 if (stack_ptr == meshbvh_stack_ptr)
  104.                 {
  105.                     meshbvh_stack_ptr = -1;
  106.                     o = ray_origin;
  107.                     d = ray_direction;
  108.                     inv = native_recip(d);
  109.                     oinv = o * inv;
  110.                 }
  111.  
  112.                 node_id = stack[stack_ptr];
  113.                 stack_ptr--;
  114.             }
  115.             else if (traverseChild0 || traverseChild1)
  116.             {
  117.                 unsigned int first_child = node_id + 1;
  118.                 unsigned int second_child = n->second_child;
  119.                 node_id = (traverseChild0) ? first_child : second_child;
  120.  
  121.                 if (traverseChild0 && traverseChild1)
  122.                 {
  123.                     if (c1min < c0min)
  124.                     {
  125.                         node_id = second_child;
  126.                         stack_ptr++;
  127.                         stack[stack_ptr] = first_child;
  128.                     }
  129.                     else
  130.                     {
  131.                         stack_ptr++;
  132.                         stack[stack_ptr] = second_child;
  133.                     }
  134.                 }
  135.             }
  136.         }
  137.         else if (prim_count < 0)
  138.         {
  139.             meshbvh_stack_ptr = stack_ptr;
  140.  
  141.             unsigned int bottom_level_offset = n->prim_offset;
  142.             __global unsigned int *bottom_level_ids = &indices[bottom_level_offset];
  143.            
  144.             int bottom_levels_count = -prim_count;
  145.            
  146.             int bvh_offset = bottom_level_ids[0];
  147.             int bvh_index = toplevelData[bvh_offset].bvh_index;
  148.  
  149.             node_id = bvh_index;
  150.  
  151.             o = mul4x1(ray_origin, toplevelData[bvh_offset].mat0, toplevelData[bvh_offset].mat1, toplevelData[bvh_offset].mat2, toplevelData[bvh_offset].mat3);
  152.             d = mul3x1(ray_direction, toplevelData[bvh_offset].mat0, toplevelData[bvh_offset].mat1, toplevelData[bvh_offset].mat2);
  153.             inv = native_recip(d);
  154.             oinv = o * inv;
  155.         }
  156.         // Leaf node
  157.         else
  158.         {
  159.             unsigned int prim_offset = n->prim_offset;
  160.             __global unsigned int *prims_ids = &indices[prim_offset];
  161.            
  162.             for (int n = 0; n < prim_count; n++)
  163.             {
  164.                 // Don't trash cache by reading index through it
  165.                 int tri_idx = prims_ids[n] * 3;
  166.                 float4 r = triangles[tri_idx + 0];
  167.                 float4 p = triangles[tri_idx + 1];
  168.                 float4 q = triangles[tri_idx + 2];
  169.  
  170.                 float o_z = r.w - o.x * r.x - o.y * r.y - o.z * r.z;
  171.                 float i_z = 1.0f / (d.x * r.x + d.y * r.y + d.z * r.z);
  172.                 float t = o_z * i_z;
  173.  
  174.                 if (t > tmin && t < tmax)
  175.                 {
  176.                     float o_x = p.w + o.x * p.x + o.y * p.y + o.z * p.z;
  177.                     float d_x = d.x * p.x + d.y * p.y + d.z * p.z;
  178.                     float u = o_x + t * d_x;
  179.  
  180.                     if (u >= 0.0f && u <= 1.0f)
  181.                     {
  182.                         float o_y = q.w + o.x * q.x + o.y * q.y + o.z * q.z;
  183.                         float d_y = d.x * q.x + d.y * q.y + d.z * q.z;
  184.                         float v = o_y + t * d_y;
  185.  
  186.                         if (v >= 0.0f && u + v <= 1.0f)
  187.                         {
  188.                             tmax = t;
  189.                             bU = u;
  190.                             bV = v;
  191.                             id = prims_ids[n];
  192.                         }
  193.                     }
  194.                 }
  195.             }
  196.            
  197.             if (stack_ptr == meshbvh_stack_ptr)
  198.             {
  199.                 meshbvh_stack_ptr = -1;
  200.                 o = ray_origin;
  201.                 d = ray_direction;
  202.                 inv = native_recip(d);
  203.                 oinv = o * inv;
  204.             }
  205.  
  206.             node_id = stack[stack_ptr];
  207.             stack_ptr--;
  208.         }
  209.     }
  210.     while (node_id != 0xffffffff);
  211.  
  212.     return (float4)(bU, bV, tmax, as_float(id));
  213. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement