Основы рендера воды 🌊
Чтобы нарисовать воду, нужно посчитать расстояние от её поверхности до дна в каждом пикселе. Но во время работы фрагментного шейдера известно только собственное значение глубины. Поэтому необходимо разбить рендер на два этапа.
Сначала буфер глубины заполняется вершинными шейдерами непрозрачных объектов (террейн, пропы). И уже после этого запускаются все шейдера, в том числе и водичка.
Идея простая, но есть нюансы.
Текстуру перед использованием нужно перевести в правильный лейаут (shader_optimal, attachment_optimal, ..). Но среди них нет такого, который позволил бы одновременно и сэмплировать текстуру, и использовать её в качестве аттачмента (даже Read-only). Это значит, что передать посчитанный буфер глубины в шейдер воды напрямую не получится, ведь он будет приаттачен к пассу.
Лэйаут attachment_optimal означает, что текстура загружается маленькими кусочками в кэш тайла, так как область записи этого тайла жёстко ограничена и известна заранее. Это позволяет тайлам не зависеть друг от друга и не гонять до основной памяти, пока не закончится пасс.