我当前正在尝试在片段着色器中实现路径示踪剂,该片段着色器利用非常简单的BVH
BVH交集的代码基于以下想法:
bool BVHintersects( Ray ray ) {
Object closestObject;
vec2 toVisit[100]; // using a stack to keep track which node should be tested against the current ray
int stackPointer = 1;
toVisit[0] = vec2(0.0, 0.0); // coordinates of the root node in the BVH hierarcy
while(stackPointer > 0) {
stackPointer--; // pop the BVH node to examine
if(!leaf) {
// examine the BVH node and eventually update the stackPointer and toVisit
}
if(leaf) {
// examine the leaf and eventually update the closestObject entry
}
}
}
上述代码的问题是,在第二盏灯上弹跳时,发生了非常奇怪的事情开始发生,假设我正在以这种方式计算灯光:
vec3 color = vec3(0.0);
vec3 normal = vec3(0.0);
// first light bounce
bool intersects = BVHintersect(ro, rd, color, normal);
vec3 lightPos = vec3(5, 15, 0);
// updating ray origin & direction
ro = ro + rd * (t - 0.01);
rd = normalize(lightPos - ro);
// second light bounce used only to calculate shadows
bool shadowIntersects = BVHintersect(ro, rd, color, normal);
bvhintersect的第二个电话将无限期地运行,因为while循环从未退出,但是从我在第二个电话上进行的许多测试中,我敢肯定,stackpointer最终会成功地返回0,实际上,如果我放置以下代码在while循环下:
int iterationsMade = 0;
while(stackPointer > 0) {
iterationsMade++;
if(iterationsMade > 100) {
break;
}
// the rest of the loop
// after the functions ends it also returns "iterationsMade"
变量"迭代"始终低于100,while循环不会无限地运行,但是明智的是,即使我做了" 100"迭代,即使"迭代效果"永远不会比说10或20。硬编码的" 100"到更大的价值将线性降低性能
这种行为的可能原因是什么?第二个呼吁bvhintersect将其陷入其中的原因是什么,如果循环效果不超过10-20次迭代?
bvhintersect函数的源:https://pastebin.com/60syrqaz
所以,关于着色器中的循环(或大多数simd情况(有一个有趣的事情:
整个浪潮至少需要执行的时间与最慢的线程一样。因此,如果一个线程需要进行〜100次迭代,则它们都进行了100次迭代。根据您的平台和编译器,循环可能会展开100次迭代(或您选择的任何上限(。break
之后的任何内容都不会影响最终输出,但是将必须处理展开的循环的其余部分。并非总是可能的。
有多种方法,但也许最直接的是在最大迭代值较低的多个通过中进行此操作。
我还将通过编译器运行您的着色器并查看生成的代码。与不同的最大迭代进行比较,并查看诸如编译的着色器的长度之类的内容。
有关更多信息,请参见此答案。