Играя три года назад в Deus Ex: Mankind Divided, я заметил небольшой трюк и написал о нём твит. Сегодня я наконец превратил его в полноценную статью. Догадываетесь, о чём она будет?
Источник: Deus Ex: Mankind Divided
Правильный ответ: рельеф красиво сливается с камнем! Позвольте рассказать подробнее: обычно когда объекты и рельеф пересекаются друг с другом, можно увидеть границу резкого пересечения. Однако в Deus Ex присутствует красивый плавный переход между рельефом и объектом:
Смешение объектов с рельефом — не особо свежая идея. Вот список:
Я сам описывал интересную технику для деревьев в Torchlight [ссылка]
Есть потрясающая техника смешения цветов и даже нормалей рельефа с мешем (известная по Battlefront 2) [ссылка]
Тема на TigSource о смешении рельефа в Zelda: BotW и Farcry 5 [ссылка]
Смешение рельефа при помощи Unreal Realtime Virtual Texturing (RVT) [ссылка]
Любопытный эксперимент по использованию Pixel Depth Offset и дизеринга для смешения рельефа и объекта [ссылка]
В трюке Deus Ex мне нравится то, что это простой хак (я обожаю подобные трюки!).
Давайте взглянем на несколько примеров, возможно, вы сами догадаетесь, что здесь происходит:
Источник: Deus Ex: Mankind Divided
В рельефе используется просвечивающий материал! Поэтому можно использовать простой depth fade (чем ближе пиксель к непрозрачной поверхности, тем прозрачнее он становится), и он сможет плавно сливаться с объектами (непрозрачными).
Вместо выполнения простого depth fade, EmilMeiton описывает усовершенствованный способ: «применение "сырого" буфера глубин для смешения объектов работает, однако результат сильно зависит от угла камеры относительно к земле. […] Я осознал, что можно просто обратить этот эффект, вычислив касательную угла между нормалью к рельефу и направлением взгляда (вектором камеры), поделив на неё ранее использованное расстояние (между рельефом и объектом). Это неидеально, но намного лучше, чем предыдущие решения»
Позвольте сказать несколько слов о том, почему меня удивило использование здесь просвечивающего материала:
Перерисовка. Мы постоянно слышим: будьте аккуратнее с прорисовкой! Избегайте крупных частиц!! Это убивает производительность!!!!111 Поэтому применение рельефа (который чаще всего занимает не менее половины экрана) с просвечивающим материалом казалось мне контринтуитивным.
Сортировка. У просвечивающих объектов обычно возникают проблемы с сортировкой. В видео ниже это проявляется как полигоны, которые видны сквозь полигоны, расположенные ближе:
Такие проблемы сортировки обычно возникают при наложении просвечивающих поверхностей.
Примечание: в Unreal недавно появилось Order Independent Translucency, что может в корне изменить ситуацию!
Всё это оказалось для меня сюрпризом, потому что обычно рендеринг рельефа выглядит так:
Источник: GTA V Graphics Study Эдриана Корреже
Как видите, рельеф непрозрачен и отрисовывается на очень ранних этапах. Это логично, потому что потом не придётся рендерить всё, что находится за уже отрендеренными пикселями. Эдриан прислал мне ещё один пример из Metal Gear Solid V, в котором рельеф рендерится первым, чтобы избежать рендеринга всего, что за ним находится — это преимущество было бы потеряно в случае Deus Ex, где рельеф рендерится последним.
Когда я впервые увидел использованную в Deus Ex методику, я задал вопрос в Twitter, на который ответил Бен Голус (здесь и здесь) (просто на случай, если вам нужны подробности).
Давайте рассмотрим перечисленные выше проблемы (перерисовку и сортировку):
Перерисовка
Вот моё предположение о том, почему в данном случае перерисовка не стала огромной проблемой:
Дело касается только одного слоя. Обычно когда художников предупреждают о перерисовке, их просят избегать пересечения слишком большого количества просвечивающих слоёв, чтобы один пиксель не обрабатывался при рендеринге пятьдесят раз из-за того, что эту область закрывают пятьдесят частиц.
Помогает то, что рельеф очень плоский, поэтому мы никогда не видим, как он пересекает сам себя (ситуации из показанного мной выше примера сортировки, где холмы накладываются друг на друга, в Deus Ex никогда не происходит):
Проблемы сортировки
Я только что написал, что сортировка в Deus Ex не должна быть проблемой благодаря плоскому рельефу. Тем не менее, мне бы хотелось показать, процесс рендеринга в Deus Ex и продемонстрировать пример того, как можно решить потенциальные проблемы с сортировкой (например, если рельеф содержит накладывающиеся друг на друга холмы).
Как обычно и бывает в рендеринге в реальном времени, сначала идут все непрозрачные объекты. Обычно в их список входит и рельеф (см. выше пример из GTA V), но в Deus Ex всё иначе! Здесь есть несколько участков оранжевого песка, но вскоре они будут перекрыты:
Этап 1: Непрозрачные объекты
Этап 1: Непрозрачные объекты (буфер глубин)
Теперь рельеф отрисовывается поверх. Он имеет просвечивающий материал, позволяющий выполнять плавное смешение с непрозрачной геометрией. Обратите внимание, что он тоже рендерится в буфер глубин! Это сделано специально! Обычно для просвечивающих объектов так не делают (подробнее см. здесь), но это нормально, потому что мы знаем, что за пикселями рельефа больше ничего не будет рендериться.
Этап 2: Просвечивающий рельеф
Следующими этапами будут тени, освещение, другие просвечивающие элементы, например, частицы, и, разумеется, UI. Но всё это нас пока не интересует.
Мне бы хотелось подчеркнуть, насколько важно, что рельеф (просвечивающий) записывается в буфер глубин, поскольку это решает две задачи:
1. Позволяет избежать проблем с сортировкой. Сравнивая новые отрисовываемые пиксели с уже имеющейся информацией о глубинах, мы можем отбрасывать те пиксели, которые находятся за уже отрендеренными:
Обычные проблемы сортировки с пересекающимися просвечивающими поверхностями.
Отсутствие проблем благодаря отбрасыванию пикселей, находящихся за другими поверхностями.
Я создал туториал о том, как создать показанный выше пример, чтобы избежать проблем с сортировкой.
Как говорилось ранее, мой пример очень гористый, однако рельеф в Deus Ex достаточно плоский! Поэтому теоретически в этом конкретном случае рендеринг рельефа (просвечивающего) в буфер глубин был бы не нужен, потому что проблем с сортировкой не ожидается. Однако мы можем использовать информацию о глубинах для кое-чего ещё:
2. Depth Fade для частиц. В примере ниже показаны: типичные проблемы с сортировкой (слева), их «решение» принудительной отрисовкой поверх (в центре) и самый красивый способ заставить частицу «реагировать» на рельеф, выполнив красивый (справа):
Повторюсь: выполнение такого depth fade вполне нормально, когда речь идёт о частице, близкой к **непрозрачному** объекту, потому что они всегда рендерятся в буфер глубин, а **просвечивающие** объекты наподобие нашего рельефа обычно себя так не ведут!
Мой материал, использующий customDepth для depth fade.
А вот, как это выглядит в игре. Эффект пыли имеет плавный переход в рельеф:
Кстати…
В Legend of Zelda: BotW используется схожая техника; вот тема, в которой flogelz воссоздаёт смешение рельефа. Он не использует просвечивающий материал для рельефа, а смешивает всё в GBuffer, но порядок рендеринга такой же: сначала всё остальное, потом рельеф.
Бен Голус: «Сначала рендерится всё в сцене, затем рельеф; и то, и другое в одни GBuffer.»
Подведём итог
В Deus Ex применяется красивый хак для смешения рельефа и объектов. Рендеринг рельефа в нём имеет три особенности:
Рельеф рендерится после всех непрозрачных объектов
Для рельефа используется просвечивающий материал
Рельеф рендерится в буфер глубин (обычно это происходит только с непрозрачными объектами)
Это сделано, чтобы:
Избежать проблем с сортировкой
Плавно смешать рельеф с объектами
Плавно смешивать другие просвечивающие элементы наподобие частиц с рельефом (просвечивающим)
Могут возникнуть следующие проблемы:
Потенциально лишняя трата ресурсов на рендеринг непрозрачных объектов, потому что они полностью перекрыты рельефом (но в случае Deus Ex это не так)
Если присмотреться, хак достаточно заметен, потому что он зависит от угла между камерой и рельефом