Как работать с полупрозрачными текстурами в SceneKit? - PullRequest
0 голосов
/ 24 марта 2020

Я хочу сделать волосы с некоторой полупрозрачной текстурой. Но я всегда вижу некоторые артефакты, например, на видео: https://drive.google.com/file/d/1ftl2XRIuuJFurCwndan0K4UMxzn_wvu_/view?usp=sharing Это просто 1 модель OBJ с некоторой текстурой.

Transparency mode - Dual Layer 
Double sided
Blend mode - Alpha 
+ shader with alphatest

artifacts sample

Завершить тестовый проект: https://drive.google.com/file/d/16AHTXJ_1Rw4yBL6U-mFSUcnq_9mtb8wq/view

Если я отключу глубину записи -> стрижка выглядит неправильно. НО этот артефакт устранен. Как это сделать правильно?

PS Если вы знаете, как правильно отобразить его в MetalKit / RealityKit или в другом месте, пожалуйста, ответьте и на этот вопрос. Потому что я вижу эти проблемы и в RealityKit.

1 Ответ

2 голосов
/ 25 марта 2020

Это одна из самых распространенных проблем при рендеринге с прозрачностью. Многие полезные виды альфа-смешивания некоммутативны: порядок, в котором вы рисуете вещи, имеет значение.

При рисовании непрозрачных поверхностей мы используем z-буфер, чтобы определить, какой фрагмент является передним на попиксельной основе. Включите глубину записи / чтения, нарисуйте свои треугольники, и пусть победит ближайший фрагмент. Это работает независимо от порядка рисования.

Когда поверхности полупрозрачны, мы не можем наивно ожидать, что z-буфер автоматически выдаст правильный результат; он может содержать только одно значение на пиксель одновременно. Если мы включаем глубину записи / чтения и рисуем в произвольном порядке, у нас есть хороший шанс отклонить фрагменты, которые должны были внести свой вклад в картину. Это явление проиллюстрировано слева от вашего изображения выше.

С другой стороны, если мы не читаем буфер глубины, у нас есть высокая вероятность неправильного рисования поверх непрозрачной геометрии, которая уже была отрисована что делает полупрозрачные поверхности странно «плавающими» перед объектами, которыми они должны быть перекрыты.

Мы разрешаем эти артефакты, сначала рисуя непрозрачную геометрию с включенной глубиной записи / чтения, затем рисуя полупрозрачные поверхности с отключенной записью глубины. Важно отметить, что, если вы не используете более продвинутую технику, такую ​​как прозрачность, не зависящую от порядка (OIT, которая не является серебряной пулей), вы должны отсортировать свою геометрию, чтобы получить правильное наложение. Это опять-таки связано с тем, что компоновка обычно не является коммутативной.

В 2017 году SceneKit ввел «режимы прозрачности», чтобы упростить рендеринг полупрозрачных объектов, особенно выпуклых, сложность которых, как правило, мала. К сожалению, как упоминалось в 50:07 в , это видео, представляющее функцию , отдельных полигонов, не сортируется при рендеринге, поэтому режимы прозрачности не являются полным решением.

Я подозреваю, что ситуация с RealityKit примерно такая же. Сортировка полигонов при каждом перемещении камеры является дорогостоящей, и это не то, что вы хотите делать для каждого полупрозрачного объекта в каждом сценарии, поэтому эти движки не склонны его поддерживать.

Один из способов получить идеальный рендеринг в этот сложный случай заключается в том, чтобы (1) убедиться, что ваша геометрия не является самопересекающейся (если это так, невозможно будет отсортировать ее для правильного наложения), (2) поместить каждую карту волос в свой собственный узел (брутто, я знаю) и (3) отсортировать вашу геометрию так, чтобы она отображалась спереди назад с использованием двусторонних материалов и режима прозрачности «один слой». Этот шаг сортировки, вероятно, нужно будет выполнить на ЦП, и порядок рендеринга полигонов можно затем передать в SceneKit, задав свойство renderingOrder узлов, составляющих полупрозрачный объект.

В качестве альтернативы Вы можете использовать SCNNodeRendererDelegate API для перехвата рисования геометрии и нарисовать его самостоятельно с помощью Metal. Это позволит выбирать рендеринг с OIT и более эффективно рисовать, используя один узел для представления всего себя sh. Возможно, вам даже удастся перенести шаг сортировки на графический процессор с помощью умного использования SCNSceneRendererDelegate и SCNGeometrySource API s, но это выходит за рамки этого ответа.

...