Это одна из самых распространенных проблем при рендеринге с прозрачностью. Многие полезные виды альфа-смешивания некоммутативны: порядок, в котором вы рисуете вещи, имеет значение.
При рисовании непрозрачных поверхностей мы используем z-буфер, чтобы определить, какой фрагмент является передним на попиксельной основе. Включите глубину записи / чтения, нарисуйте свои треугольники, и пусть победит ближайший фрагмент. Это работает независимо от порядка рисования.
Когда поверхности полупрозрачны, мы не можем наивно ожидать, что z-буфер автоматически выдаст правильный результат; он может содержать только одно значение на пиксель одновременно. Если мы включаем глубину записи / чтения и рисуем в произвольном порядке, у нас есть хороший шанс отклонить фрагменты, которые должны были внести свой вклад в картину. Это явление проиллюстрировано слева от вашего изображения выше.
С другой стороны, если мы не читаем буфер глубины, у нас есть высокая вероятность неправильного рисования поверх непрозрачной геометрии, которая уже была отрисована что делает полупрозрачные поверхности странно «плавающими» перед объектами, которыми они должны быть перекрыты.
Мы разрешаем эти артефакты, сначала рисуя непрозрачную геометрию с включенной глубиной записи / чтения, затем рисуя полупрозрачные поверхности с отключенной записью глубины. Важно отметить, что, если вы не используете более продвинутую технику, такую как прозрачность, не зависящую от порядка (OIT, которая не является серебряной пулей), вы должны отсортировать свою геометрию, чтобы получить правильное наложение. Это опять-таки связано с тем, что компоновка обычно не является коммутативной.
В 2017 году SceneKit ввел «режимы прозрачности», чтобы упростить рендеринг полупрозрачных объектов, особенно выпуклых, сложность которых, как правило, мала. К сожалению, как упоминалось в 50:07 в , это видео, представляющее функцию , отдельных полигонов, не сортируется при рендеринге, поэтому режимы прозрачности не являются полным решением.
Я подозреваю, что ситуация с RealityKit примерно такая же. Сортировка полигонов при каждом перемещении камеры является дорогостоящей, и это не то, что вы хотите делать для каждого полупрозрачного объекта в каждом сценарии, поэтому эти движки не склонны его поддерживать.
Один из способов получить идеальный рендеринг в этот сложный случай заключается в том, чтобы (1) убедиться, что ваша геометрия не является самопересекающейся (если это так, невозможно будет отсортировать ее для правильного наложения), (2) поместить каждую карту волос в свой собственный узел (брутто, я знаю) и (3) отсортировать вашу геометрию так, чтобы она отображалась спереди назад с использованием двусторонних материалов и режима прозрачности «один слой». Этот шаг сортировки, вероятно, нужно будет выполнить на ЦП, и порядок рендеринга полигонов можно затем передать в SceneKit, задав свойство renderingOrder
узлов, составляющих полупрозрачный объект.
В качестве альтернативы Вы можете использовать SCNNodeRendererDelegate
API для перехвата рисования геометрии и нарисовать его самостоятельно с помощью Metal. Это позволит выбирать рендеринг с OIT и более эффективно рисовать, используя один узел для представления всего себя sh. Возможно, вам даже удастся перенести шаг сортировки на графический процессор с помощью умного использования SCNSceneRendererDelegate
и SCNGeometrySource
API s, но это выходит за рамки этого ответа.