Создание общих вершинных нормалей на GPU

9

Я в основном преуспел в переносе реализации Marching Cubes с CPU на вычислительные шейдеры OpenGL, но я еще не справился с нормой и задаюсь вопросом, как лучше это сделать.

Моя реализация имеет дело именно с бинарными полями (я пытаюсь смоделировать трехмерные фрактальные функции, у которых пока нет оценки расстояния), поэтому методы градиентной и прямой разницы не будут работать. Я поделился рабочими вершинами, и моя реализация ЦП использует метод Quilez, описанный здесь, чтобы накапливать грани лица на каждую соседнюю вершину.

Я мог бы просто перенести эту реализацию на другой шейдер, но проблема, которую я вижу в этом, заключается в огромном количестве необходимых атомарных элементов. Так как мы можем использовать атомики только для скалярных целочисленных типов, и я не могу придумать способ суммировать 3 подписанных целых в 1 суммируемым образом, это означает, что 3 оси * 3 вершины = 9 атомных добавок на вызов шейдера. Конечно, они будут распространяться по всей памяти, так что это не похоже на удары по одному атомному счетчику 9 раз, но все равно это чертовски много.

Другой альтернативой является запуск вызова шейдера для каждого многоугольника и построение списка нормалей лица (я мог бы, вероятно, упаковать в x10y10z10 таким образом), затем шейдер для каждой вершины, чтобы накапливать все нормали соседних граней. Это было бы огромным занятием памяти, хотя пространство хранения индексов лица должно было бы 12 int на вершину, чтобы иметь дело с худшим случаем. Существует также проблема того, как записать в это хранилище, не прибегая к атомарности, чтобы выяснить, сколько граней уже записано в определенную вершину.

У кого-нибудь есть лучшие идеи о том, как это сделать?

русс
источник

Ответы:

5

Для решения только для nVidia вы можете использовать встроенные функции с плавающей запятой (например, NvInterlockedAddFp32) Разблокировка встроенных функций графического процессора в HLSL | NVIDIA Developer

Я пробовал это на 80.000 вершинной сетки, и это довольно быстро (что-то вроде 1 или 2 мс на GTX980M, если я правильно помню)

Остерегайтесь компиляции ваших шейдеров в релизе, чтобы встроенные функции работали (из-за ошибки / ограничения nvidia)

Также остерегайтесь расщепления вершин (например, из-за несплошности ультрафиолетовых лучей), вам придется справляться с ними, иначе у вас будут нежелательные твердые края в УФ-швах.

Турнир по Флоренту
источник
Поскольку вопрос старый, я задам вам вопрос :-) Для чего, как я понимаю, просто наличие информации о смежности для каждой вершины было недостаточно для русской?
Андреас
Это было для моего дипломного проекта в прошлом году, в итоге я просто пошел тупым путем и использовал целочисленные атомарные добавления, увеличил масштаб, чтобы максимизировать точность, а затем нормализовался для плавающих векторов. Не удалось найти способ составления списка граней вокруг каждой вершины без выделения места в худшем случае и использования атомных счетчиков для создания списков в любом случае. Это, вероятно , неэффективна , как ад , но я до сих пор есть несколько порядков величины ускорения от версии CPU и знак первого класса , так что я была счастлива с ним достаточно :)
Russ