Meshgun

Meshgun 

Рендер-гик, застрявший в Neovim

6subscribers

7posts

Основы рендера воды 🌊

Чтобы нарисовать воду, нужно посчитать расстояние от её поверхности до дна в каждом пикселе. Но во время работы фрагментного шейдера известно только собственное значение глубины. Поэтому необходимо разбить рендер на два этапа.

Сначала буфер глубины заполняется вершинными шейдерами непрозрачных объектов (террейн, пропы). И уже после этого запускаются все шейдера, в том числе и водичка.


Идея простая, но есть нюансы.


Текстуру перед использованием нужно перевести в правильный лейаут (shader_optimal, attachment_optimal, ..). Но среди них нет такого, который позволил бы одновременно и сэмплировать текстуру, и использовать её в качестве аттачмента (даже Read-only). Это значит, что передать посчитанный буфер глубины в шейдер воды напрямую не получится, ведь он будет приаттачен к пассу.
Лэйаут attachment_optimal означает, что текстура загружается маленькими кусочками в кэш тайла, так как область записи этого тайла жёстко ограничена и известна заранее. Это позволяет тайлам не зависеть друг от друга и не гонять до основной памяти, пока не закончится пасс.
А вот в шейдере можно получить доступ к произвольному месту текстуры. Кэш работает по-другому, поэтому эти сценарии использования несовместимы.
Чтобы обойти ограничение, проще всего сделать копию буфера из препасса и использовать для сэмплов её. В шейдере с помощью инвертированной матрицы камеры можно восстановить из этого буфера глобальную позицию, чтобы посчитать расстояние до поверхности воды.
Так получится неплохая база, на которую потом можно будет накинуть волны и пену.
P.S. Можно решить это без копирования с помощью расширения, которое позволяет читать значения из аттачмента прямо внутри пасса. Оно добавляет новый лэйаут текстуры (rendering_local_read) и специальный барьер, которые вместе позволяют писать и читать из аттачмента в правильном порядке в рамках тайла (без синхронизаций с основной памятью).
Но увы, процент поддержки 37% даже на Windows, поэтому отложим на будущее.
Go up