KD-дерево в GLSL

после одного дня попыток понять, как реализовать kd-дерево в OpenGL/GLSL, я очень расстроен...

Я объявляю свои KD-узлы следующим образом в GLSL:

layout(std140) uniform node{
  ivec4 splitPoint;
  int dataPtr;
} nodes[1024];

SplitPoint содержит точку разделения kd-дерева, четвертый элемент вектора содержит 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,256,0) в направлении Y в узле 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);

В этот момент на экране должен появиться образец случайных цветов. Но в большинстве случаев ничего не видно.

Я пытался получить значения от узлов напрямую и получить правильные результаты... поэтому я считаю, что что-то не так с динамической индексацией данных юниформ-блока.

Я надеюсь, что кто-то может мне помочь здесь ... потому что у меня заканчиваются идеи: /

Флориан


person fho    schedule 29.07.2010    source источник


Ответы (1)


Сладкий: glm И макеты :) (Вы случайно не знаете Groovounet?)

Кажется, я вижу здесь некоторые странные вещи

  • Ваш критерий для принятия решения о том, на какой стороне дерева рекурсивно, странен. Что вы ожидаете от этого? Определенно не прогулка по kd-дереву. У вас есть доступ к последней версии ShaderX? Я считаю, что № 5 дает фактический код для этого

  • Ваши данные тоже странные (может быть: вы на 100% уверены в точках разделения?)

Возможно, вам следует проверить, действительно ли учитывается std140. Но у вас С++ Node, кажется, все в порядке.

person Calvin1602    schedule 30.07.2010
comment
- Критерий основан на данных... или их отсутствии. -1 указывает, что в узле нет данных, поэтому мне нужно рекурсивно, как только указатель оказывается на листьях, есть данные - данные просто не нормализуются. Он находится в диапазоне 0..511. Критерий, в котором дочерний элемент должен проходить, основан на простом сравнении плоскости с точкой ( distFromPlane = dot (point-pointOnPlane, normalOfPlane); ). Когда я вручную устанавливаю «n» для узла и вывожу переменную DistanceFromPlane как gl_Fragcolor.r, это рассчитан правильно. Я думаю, что проблема связана с динамическим ветвлением - person fho; 02.08.2010
comment
И: нет, я не знаю, groovounet ;) Но, по крайней мере, glm-векторы прекрасно размещаются в памяти, и вы можете использовать их непосредственно в UBO. - person fho; 02.08.2010
comment
Я имел в виду, что это НЕ обход KD-дерева. В конечном итоге он выберет первый пересекающийся том, но он не обязательно содержит что-либо, не так ли? - person Calvin1602; 02.08.2010
comment
Вы на 100% уверены в splitDir? Как вы его вычисляете? 1 -> +Y, 2->+Z и т. д.? Кстати, вы пока не обновляете его. - person Calvin1602; 02.08.2010
comment
Ах, извините ... да, я удалил код для него выше. Я просто положу его обратно туда. Почему он должен выбирать первый пересекающийся том? Я бы сказал, что он идет прямо к «низу» дерева, где есть данные. - person fho; 05.08.2010
comment
Я имею в виду: первый объем, который пересекает луч, исходящий от камеры. Он идет как к основанию дерева, так и к камере, т.е. узлы ВНУТРИ дерева никогда не будут посещены, независимо от угла обзора. Это может быть или не быть вашей проблемой, но в любом случае я не думаю, что это действительно то, чего вы хотите. - person Calvin1602; 05.08.2010
comment
Нет.... это правда. Идея заключалась в том, чтобы сравнить точку с деревом. Чтобы найти значение, которое лучше всего подходит для этой точки - person fho; 05.08.2010
comment
В этом случае я просто могу предложить вам попробовать маленькое дерево, например, только с 1 листом или 1 корнем и 2 листьями. Извини :/ - person Calvin1602; 06.08.2010
comment
Нет проблем... я думаю, проблема в том, что здесь невозможно выполнить "динамический поиск" из юниформ-объектов. Возможно, было бы лучше, если бы я использовал буфер текстуры для хранения данных. - person fho; 10.08.2010