C++ GLSL中的KD树
在花了一天的时间试图弄明白如何在OpenGL/GLSL中实现kd树之后,我非常沮丧 我在GLSL中声明我的KD节点,如下所示:C++ GLSL中的KD树,c++,opengl,glsl,kdtree,C++,Opengl,Glsl,Kdtree,在花了一天的时间试图弄明白如何在OpenGL/GLSL中实现kd树之后,我非常沮丧 我在GLSL中声明我的KD节点,如下所示: layout(std140) uniform node{ ivec4 splitPoint; int dataPtr; } nodes[1024]; SplitPoint保存kd树SplitPoint,向量的第四个元素保存splitDirection,形成三维空间中的平面。DataPtr目前只保存树叶中的随机值 整个数组形成一个数组 C++中的结构看起来是这样
layout(std140) uniform node{
ivec4 splitPoint;
int dataPtr;
} nodes[1024];
SplitPoint保存kd树SplitPoint,向量的第四个元素保存splitDirection,形成三维空间中的平面。DataPtr目前只保存树叶中的随机值
整个数组形成一个数组
C++中的结构看起来是这样的:
struct Node{
glm::ivec4 splitPoint;
GLint dataPtr;
GLint padding[3];
};
我相信这是正确的,我将构建的树上传到缓冲区中。作为检查,我将缓冲区映射到主内存并检查值:
0x08AB6890 +0 +256 +0 +1 -1 -858993460 -858993460 -858993460
0x08AB68B0 +256 +0 +0 +0 -1 -858993460 -858993460 -858993460
0x08AB68D0 +256 +256 +0 +0 -1 -858993460 -858993460 -858993460
[...]
0x08AB7070 +0 +0 +0 +0 +2362 -858993460 -858993460 -858993460
到目前为止看起来不错(它实际上表示卷在节点0的y方向上(0256,0)分割,-1表示无数据)
现在,对于树遍历,我尝试了以下方法:
float distanceFromSplitPlane;
while(nodes[n].dataPtr == -1){
// get split direction
vec3 splitDir = vec3(0,0,0);
if(nodes[n].splitDir == 0)
splitDir.x = 1;
else if(nodes[n].splitDir == 1)
splitDir.y = 1;
else
splitDir.z = 1;
// calculate distance of ray starting point to the split plane
distanceFromSplitPlane = dot(startP.xyz-(nodes[n].splitPoint.xyz/511.0), splitDir);
// depending on the side advance in the tree
if(distanceFromSplitPlane >= 0)
n = 2 * n + 1;
else
n = 2 * n + 2;
}
// we should new be located in a leaf node and therefor have a value in dataPtr
gl_FragColor = vec4(dataPtr/6000.0, 0,1,1);
在这一点上,屏幕上应该有一个随机颜色的图案。但在大多数情况下,什么也看不见
我试图直接从节点获取值并获得正确的结果。。。所以我认为,统一块数据的动态索引有问题
我希望有人能在这里帮助我。。。因为我已经没有想法了:/
FlorianSweet:glm和布局:)(你知道Groovounet吗?)
我想我在这里看到了一些奇怪的东西
- 您决定在树的哪一侧递归的标准很奇怪。你期望它做什么?绝对不是kd树上散步。您有权访问最近的ShaderX吗?我相信#5给出了这方面的实际代码
- 你的数据也很奇怪(也许:你100%确定分割点吗?)
也许你应该检查一下std140是否真的被考虑进去了。但是C++节点看起来不错。< /P> -标准是基于数据…或同样的消失-1表示节点中没有数据,因此我必须递归,只要指针在叶子上,就有数据-数据只是没有规范化。它在0到511的范围内。当我手动将“n”设置为节点并将distanceFromPlane变量输出为gl_Fragcolor.r时,要遍历哪个子节点的标准是基于简单的平面到点比较(distanceFromPlane=dot(point pointOnPlane,normalOfPlane);)。我最好的猜测是这个问题与动态分支有关:不,我不知道groovounet;)但至少glm向量在内存中的布局非常完美,您可以在UBOs中直接使用它们。我的意思是,这不是KD树遍历。它最终会选择第一个相交的卷,但它不一定包含任何内容,是吗?您100%确定splitDir吗?你怎么计算呢?1->+Y、2->+Z等?顺便说一句,你不会在这段时间内更新它。啊,对不起。。。是的,我删除了上面的代码。我会把它放回去的。为什么要选择第一个相交体积?我会说它直接进入树的“底部”,那里有数据。