Я в основном преуспел в переносе реализации Marching Cubes с CPU на вычислительные шейдеры OpenGL, но я еще не справился с нормой и задаюсь вопросом, как лучше это сделать.
Моя реализация имеет дело именно с бинарными полями (я пытаюсь смоделировать трехмерные фрактальные функции, у которых пока нет оценки расстояния), поэтому методы градиентной и прямой разницы не будут работать. Я поделился рабочими вершинами, и моя реализация ЦП использует метод Quilez, описанный здесь, чтобы накапливать грани лица на каждую соседнюю вершину.
Я мог бы просто перенести эту реализацию на другой шейдер, но проблема, которую я вижу в этом, заключается в огромном количестве необходимых атомарных элементов. Так как мы можем использовать атомики только для скалярных целочисленных типов, и я не могу придумать способ суммировать 3 подписанных целых в 1 суммируемым образом, это означает, что 3 оси * 3 вершины = 9 атомных добавок на вызов шейдера. Конечно, они будут распространяться по всей памяти, так что это не похоже на удары по одному атомному счетчику 9 раз, но все равно это чертовски много.
Другой альтернативой является запуск вызова шейдера для каждого многоугольника и построение списка нормалей лица (я мог бы, вероятно, упаковать в x10y10z10 таким образом), затем шейдер для каждой вершины, чтобы накапливать все нормали соседних граней. Это было бы огромным занятием памяти, хотя пространство хранения индексов лица должно было бы 12 int на вершину, чтобы иметь дело с худшим случаем. Существует также проблема того, как записать в это хранилище, не прибегая к атомарности, чтобы выяснить, сколько граней уже записано в определенную вершину.
У кого-нибудь есть лучшие идеи о том, как это сделать?
источник