В этой статье я опишу создание простейшего волюметрического тумана (Volumetric fog) с помощью программы Render Monkey от компании ATI.
Волюметрический туман – это туман, который может принимать любую форму, например, чайника. В принципе форма тумана зависит от формы используемого меша (Mesh). Этот туман можно использовать для различных эффектов, например, создание лайт шафтов (Light Shaft), создание облаков, призраков и др.
Немного теории.
Первым делом для создания такого тумана необходимо вычислить толщину тумана. Для этого необходимо вычислить глубину меша в каждой точке, путем вычисления глубины передних и задних полигонов модели. Для этого нам потребуются два прохода. В первом проходе вычисляется глубина передних полигонов, поэтому мы делаем обход вершин по часовой стрелке. Во втором проходе вычисляется глубина задних полигонов, поэтому нам необходимо сделать обход вершин против часовой стрелки. Результат обеих проходов рендерится в разные текстуры. Также для обоих проходов необходимо включить блендинг для совмещения результатов и отключить Z-buffer. После того, как глубина найдена, необходимо найти разницу между глубиной передних и задних полигонов, и умножить ее на коэффициент туманности. В итоге у вас должна получиться примерно то что изображено на картинке чуть выше.
Реализация.
Начнем с первой части шейдера, которая будет рендерить в текстуру глубину передних полигонов. Она будет выглядеть так:
В вертекстном шейдере нужно вернуть глубину трансформированной вершины. Для этого нужно координату Z разделить на большое число, чтобы получить число в пределах от 0 до 1. И передать ее как текстурную координату в пиксельный шейдер. Который в свою очередь просто возвращает ее в качестве цвета. Второй шейдер идентичный первому, за исключением того, что обход вершин происходит против часовой стрелки, поэтому вычисляется глубина задних полигонов. Если вы делаете эффект не в Render Monkey, то стейты нужно менять в проходах, вот так:
После того, как у нас готовы две текстуры с отрендеренеми в них глубинами меша необходимо найти толщину тумана. Для этого создаем третий проход. Вертексный шейдер будет выглядеть вот так:
Немного о текстурных координатах. Здесь я установил координаты таким образом, чтобы туман растягивался по всей поверхности квадрата, на который выводится результат программы. Как видно, это обычный вертексный шейдер, который возвращает позицию вершины и текстурные координаты. В пиксельном же шейдере находится разница полученных глубин и умножается на коэффициент туманности:
Конечно выглядит не очень привлекательно, это потому что глубина возвращается в качестве одной компоненты. Если немного поэкспериментировать с возвращаемой глубиной, можно получить улучшенный вариант: