После некоторых копаний я нашел решение. Важно понимать, что дерево BVH не исключает возможности оценки всех листьев.
Реализация № 3 ниже, использует ссылки попадания и пропуска. Ящики должны быть отсортированы таким образом, чтобы в худшем случае все они запрашивались в правильном порядке (поэтому достаточно одного цикла). Однако ссылки используются для пропуска узлов, которые не нужно оценивать. Когда текущий узел является листовым узлом, выполняются фактические треугольные пересечения.
- ссылка удара ~ к какому узлу перейти в случае попадания (зеленый внизу)
- ссылка мисс ~, к какому узлу перейти в случае пропуска (красный внизу)
* +1012 *
Изображение взято с здесь . Соответствующая статья и исходный код также есть на странице профессора Тошии Хачисуки . Эта же концепция также описана в этой статье, упомянутой в слайдах .
# 3 Дерево BVH с ссылками Hit и Miss
Мне пришлось расширить данные, которые передаются в шейдер с помощью ссылок. Кроме того, для правильного хранения дерева потребовалось некоторое автономное переключение. Сначала я попытался использовать цикл while (цикл до box_index_next
равен -1), что снова привело к безумному замедлению. В любом случае, работает достаточно быстро:
int box_index_next = 0;
for (int box_index = 0; box_index < boxes_count; box_index++) {
if (box_index != box_index_next) {
continue;
}
bool hit = intersect_box(boxes[box_index], ray);
bool leaf = boxes[box_index].ids_count > 0;
if (hit) {
box_index_next = boxes[box_index].links.x; // hit link
} else {
box_index_next = boxes[box_index].links.y; // miss link
}
if (hit && leaf) {
uint a = boxes[box_index].ids_offset;
uint b = a + boxes[box_index].ids_count;
for (uint j = a; j < b; j++) {
uint triangle_id = triangle_references[j];
// triangle intersection code ...
}
}
}
Этот код примерно в 3 раза медленнее, чем быстрая, но некорректная реализация # 1. Это несколько ожидаемо, теперь скорость зависит от реального дерева, а не от оптимизации GPU. Рассмотрим, например, вырожденный случай, когда треугольники выровнены вдоль оси: луч в одном и том же направлении может пересекаться со всеми треугольниками, тогда необходимо оценить все листья дерева.
Prof. Тошия Хатисука предлагает дальнейшую оптимизацию для таких случаев в своих полях (стр. 36 и далее): один хранит несколько версий дерева BVH, пространственно отсортированных по x, -x, y, -y, z и - г. Для обхода необходимо выбрать правильную версию на основе луча. Тогда можно прекратить обход, как только треугольник с листа пересекается, поскольку все оставшиеся узлы, которые необходимо посетить, будут пространственно позади этого узла (с точки зрения луча).