BVH结构在着色器中无法检测三角形相交但CPP代码运行正常
我正在学习渲染技术,掌握光线追踪后尝试实现BVH加速结构。目前通过派发阴影射线检测三角形相交来测试:射线能成功与AABB盒相交,但无法检测到任何三角形相交;但把着色器代码复制到CPP中运行时,三角形相交检测却能正常工作。
BVH遍历(着色器代码)
void TraceRay(inout RayPayload Payload) { float tMin = FLOAT_MAX; int Stack[MAX_STACK_SIZE]; int StackPtr = 0; Stack[StackPtr++] = 0; while(StackPtr > 0) { int CurrentNode = Stack[--StackPtr]; if (BVHStructure.nodes[CurrentNode].Primitive[0] != -1) // is a leaf { for (int i = 0; i < 20; i++) { if (BVHStructure.nodes[CurrentNode].Primitive[i] == -1) break; if (IntersectTriangle(Payload, BVHStructure.nodes[CurrentNode].Primitive[i])) { Payload.InLight = false; return; } } } else { int Child1 = BVHStructure.nodes[CurrentNode].LeftNode; int Child2 = BVHStructure.nodes[CurrentNode].RightNode; if (Child1 != -1) { float Distance1 = IntersectAABB(Payload, BVHStructure.nodes[Child1].BoundingBox); if (Distance1 != FLOAT_MAX) Stack[StackPtr++] = Child1; } if (Child2 != -1) { float Distance2 = IntersectAABB(Payload, BVHStructure.nodes[Child2].BoundingBox); if (Distance2 != FLOAT_MAX) Stack[StackPtr++] = Child2; } } } }
BVH构建(CPU端CPP代码)
void BVHBuilder::BuildBVH(int NodeIndex, int min, int max) { if (max <= min) return; if (max - min <= 20) { size_t k = 0; BVHNode leafNode{}; for (size_t i = std::max(min, 0); i < max; i++) { leafNode.BoundingBox.MinValue = glm::min(ComputeMinimum(m_TriangleData[i]), leafNode.BoundingBox.MinValue); leafNode.BoundingBox.MaxValue = glm::max(ComputeMaximum(m_TriangleData[i]), leafNode.BoundingBox.MaxValue); leafNode.Primitive[k] = i; k++; } m_Nodes.push_back(leafNode); m_Nodes[NodeIndex].RightNode = m_Nodes.size() - 1; return; } int median = (min + max) / 2; BVHNode LeftChild{}; LeftChild.BoundingBox.MinValue = ComputeMinimum(m_TriangleData[min]); LeftChild.BoundingBox.MaxValue = ComputeMaximum(m_TriangleData[median]); m_Nodes.push_back(LeftChild); m_Nodes[NodeIndex].LeftNode = m_Nodes.size() - 1; BVHNode RightChild{}; RightChild.BoundingBox.MinValue = ComputeMinimum(m_TriangleData[median]); RightChild.BoundingBox.MaxValue = ComputeMaximum(m_TriangleData[max]); m_Nodes.push_back(RightChild); m_Nodes[NodeIndex].RightNode = m_Nodes.size() - 1; BuildBVH(m_Nodes[NodeIndex].LeftNode, min, median); BuildBVH(m_Nodes[NodeIndex].RightNode, median, max); }
阴影射线派发(着色器代码)
RayPayload DispatchShadowRay(in ivec2 Coordinate, in vec3 LightDirection) { RayPayload Payload; Payload.Valid = true; Payload.InLight = true; vec2 NormalizedCoord = vec2(Coordinate) / vec2(WINDOW_WIDTH, WINDOW_HEIGHT); float DepthValue = texture(DepthBuffer, NormalizedCoord).r; if(DepthValue >= 1.0 - EPSILON) { Payload.Valid = false; return Payload; } DepthValue = DepthValue * 2.0 - 1.0; vec4 ViewSpace = InverseProjection * vec4(NormalizedCoord * 2.0 - 1.0, DepthValue, 1.0); ViewSpace /= ViewSpace.w; vec4 WorldSpace = InverseView * ViewSpace; Payload.Origin = WorldSpace.xyz; Payload.Direction = normalize(-LightDirection); Payload.Origin += Payload.Direction * 0.001; TraceRay(Payload); return Payload; }
已做排查:
- 修复着色器存储缓冲区数据对齐问题,无效
- 核对世界空间坐标计算逻辑,未发现错误
- 反复检查AABB相交和IntersectTriangle函数实现,未发现问题
- 使用Nsight、Renderdoc调试,除存储对齐外无有效线索
- BVH由CPU递归构建,三角形已在CPU上完成排序;不确定BVH遍历逻辑是否正确,该逻辑参考资料实现
内容的提问来源于stack exchange,提问作者TooGood
相关产品推荐
相关产品推荐

