Создание заснеженной дороги

Не успело пройти и три месяца, как у меня появилось свободное время написать The Making of Snowy road. Это наполовину мейкинг оф, наполовину урок - решайте сами.

Речь идет вот об этой снежной дороге:

Итак, доброго всем дня, меня зовут Дмитрий Ярков, и сегодня я хочу поделиться с вами техникой создания снежной жижи с использованием Thinking Particles и Multiscatter.
Немного введения. Thinking Particles сегодня знают многие, однако, в основном, эта система по-прежнему остается сложной и загадочной. Не последнюю роль в этом играет интерфейс системы, а также ее внутренняя логика. Тем не менее, Thinking Particles были и остаются самой мощной системой частиц для 3ds max (и не очень дешевой – около 2000$). Я начал изучать ее полгода назад, и с тех пор решил в ней множество задач. Эта система полностью программируема, в ней можно создавать сложные операторы условий, основанные на выражениях (expressions), однако для некоторого круга задач можно обойтись стандартными операторами.
Если вы хотите выучиться работать в данной системе, вам необходимо пройти и усвоить видеокурс Thinking Particles 4 for production. Система настолько многогранна, что невозможно объяснить в двух словах многочасовые лекции этого курса. Можно утешиться тем, что не обязательно смотреть все видео, можно ограничить вводным, и далее перейти к группе «Production Shots» для базового понимания.
Thinking Particles в данном уроке мы используем в качестве решения для создания формы снежных комков, которые будут заполнять дорогу и колеи на ней. А Multiscatter, про который, несомненно, знают все, будем использовать во второй части урока для создания более реалистичной снежной поверхности. Кроме того, мы рассмотрим шейдер VRayFastSSS2 и немного композитинга.

Часть 1: Thinking Particles.

Итак, начнем с моделирования лоу-польной болванки в качестве основания для снежной жижи. Это должен быть замкнутый объем нужной вам формы. В моем случае, всё делалось строго под камеру, поэтому форма получилась несколько изогнутой:

Здесь грубо набросаны будущие колеи и большой сугроб слева. Синяя поверхность – условный «пол», на который будут падать фрагменты снега. Сзади вы видите два лоу-поли колеса от автомобиля, которые проедут по траектории колеи за отрезок времени в 100 кадров. Вот их траектория:

Все эти объекты нужно соответствующим образом назвать и переместить в слой TP_source, чтобы в будущем можно было легко скрыть его.

На этом приготовления закончены, всё остальное мы сделаем в Thinking Particles. Открываем вкладку Create->Geometry->Particle systems->Thinking и создаем систему частиц Thinking Particles в любом месте сцены. Для этого объекта можно создать отдельный слой с названием TP. Внешне Thinking Particles выглядит как скромный крестик с буквами TP, с единственной настройкой Properties внутри панели модификаторов. Нажав на кнопку, мы попадем внутрь системы, где и будем проводить дальнейшие действия.

Поскольку это наполовину урок, наполовину Making of, я не буду показывать скриншоты, демонстрирующие создание программы с нуля. Вместо этого я покажу скриншоты уже готовой программы и объясню, что они означают.

Как вы уже должны представлять по вводному видеокурсу, в левой верхней части окна у нас находятся группы частиц, а в левой нижней группы динамических наборов. Не все новички сразу понимают отличие групп от наборов. Группы позволяют разделять частицы с различными условиями рождения, смерти, просто разные наборы частиц. Они позволяют задавать разные цвета этим группам, разные режима отображения, или же вообще скрывать их. Динамические наборы (Dynamic sets) предназначены для программирования частиц, где частицы каких-либо групп создаются, двигаются и умирают по определенным законам, взаимодействуя друг с другом.

Первый динамический набор, который мы видим на экране, это Birth – рождение частиц:

Все три оператора на основном экране – это операторы рождения Object to particle. Это достаточно специфические операторы. Они переводят любые объекты в частицы, по принципу «один объект – одна частица». Частица помещается в центр объекта и принимает его форму (Particle Shape). Как вы видите в настройках справа, там стоит галочка Instance Shape – это как раз и значит, что частица принимает форму объекта. А также, конкретно для группы Wheels, режим трэкинга переключен на Object to Particle: это означает, что анимация частиц колеса будет наследоваться от анимации колеса.

Все три оператора рождения создают частицы в соответствующих группах: wheels (колеса), snow_source (источник снега) и ground (земля).

Далее нам нужно разбить источник снега на объемные фрагменты, которые будут использоваться при рассыпании снежной жижи. Для этого служит следующий динамический набор под названием VB1:

Здесь всё просто: берется группа частиц snow_source и разбивается оператором Volume Break. Как вы видите, в настройках справа стоит галочка Use helper, threshold: 500 cm, group: Wheels. Это означает, что разбиение будет происходить по ходу анимации на расстоянии 500 cm от группы частиц Wheels. Еще ниже мы видим настройку Spreading Size: 80%, Spreading Time: 40. Это означает, что, единожды начавшись на расстоянии 500 cm, разбиение будет на протяжении 40 кадров увеличиваться вплоть до 80% первоначального расстояния. Параметр Raster 0.6 – относительная величина ячеек.

Оператор Volume Break не только разбивает частицы, но и переводит получившиеся осколки в другую группу. В нашем случае это группа frag1. Оператор Scale в конце ветки нужен для уменьшения всех получившихся частиц до 97% от первоначального размера. Это необходимо для облегчения взаимодействия частиц друг с другом. Вот как всё это примерно выглядит посередине анимации:

Здесь зеленый след, постепенно расширяющийся по мере продвижения колеса – как раз результат работы Volume Break. Красный след – это вторичное разбиение в группе VB2:

Здесь уже настройки хитрее, мне сложно будет объяснить каждый оператор, но я взял эти настройки из видеокурса, упомянутого выше. Название урока: «TP4 - Production Shot - 06 - Ground Crumble Setup.avi».

Тем не менее, я смогу объяснить принцип работы этой программы подробнее, чем в том уроке.

Суть в том, что для вторичных разбиений в операторе Volume Break используется не только Helper. Helper, аналогичный предыдущему разбиению, используется только для непосредственного дробления фрагментов в месте соприкасания с колесами. В остальной области используется опция Activate. Когда она равняется100%, разбиению подвергается полностью вся частица, когда 0% - частица разбиению не подвергается. Для каждой частицы значение Activate определяется отдельно и рандомно. Вот как это делается.

Для начала, к исходным частицам применяется оператор Timer. Этот оператор имеет желтый вход Start, куда подключается группа частиц frag1 – результат первичного разбиения. Во вход Particle подключается та же самая группа частиц. Все это означает, что таймер будет запущен для каждой входящей частицы независимо.

Таймер будет отсчитывать определенное количество кадров для каждой частицы – всегда разное за счет оператора Random (возвращает число от 15 до 50, режимanimation), подключенного к входу Frames. Как только отсчет прекращается, Timer передает команду на выход Out, который в свою очередь подключен к входу Onоператора Volume Break, который включается именно в этот момент и именно для этой частицы (благодаря также входу Particle). Но как Volume Break узнает, какой процент Activate нужно включить для этой частицы? Для этого от оператора Timer отходит еще один интересный оператор Value to Time.

Оператор Value to Time изначально предназначен для перевода скалярного значения во временной промежуток. Но его также можно использовать как сложный оператор пропорциональности. На вход подается некоторое значение (Value), которое мы берем из выхода Time Relative (нормализованное время от 0 до 1) оператора Timer. Настройки Value to Time просты:

Входящее значение Value интерполируется между двумя значениями: Value1 и Value2. При Value1 оператор возвращает Time=0, при Value2 оператор возвращаетTime=100 (или в нашем случае число, полученное оператором Random от 30 до 80 в режиме animation). Все средние значения Value интерполируются. Таким образом, на выходе мы получаем случайные значения от 0 до 80 для каждой отдельной частицы, в зависимости от разных условий. Далее посредством оператораFade In (в оригинале он называется Float) мы делаем плавный вход в это значение в течение 100 кадров, ну и, наконец, полученный результат подается на входActivate оператора Volume Break. Результат без использования Helper:

С использованием Helper для дополнительного дробления колеи группой wheels:

Остальные два динамических набора очень просты. Первый это гравитация, которая действует только на группу Active_objects:

Второй это ShapeCollision, позволяющий частицам взаимодействовать по физическим законам:

ShapeCollision применяется ко всем группам, то есть, в данном случае, к общей группе SC.

Теперь наша программа готова. Зайдя в Master Dynamic Set, мы можем выбрать путь для сохранения кэша и нажать Simulate. По окончании симуляции мы можем проиграть нашу анимацию. Вот так она выглядит у меня:

Вот как выглядит последний кадр симуляции:

Мы должны взять только этот кадр и далее работать с ним как с обычной геометрией. Но TP не позволяет просто так сконвертировать себя в Editable Mesh. Придется зайти в Master Dynamic Set и нажать галку Groups as object, тогда каждая группа превратится в отдельный объект с тем же названием. После этого можно сконвертировать полученные объекты в Editable Mesh, а оригинальную систему Thinking Particles удалить – она нам больше не понадобится. Соблюдайте осторожность и сохраняйтесь перед этими действиями.

Часть 2: шейдинг и рендер.
Теперь мы получили чистую геометрию, причем разбитую на группы. Основных групп у нас две: крупные и маленькие фрагменты. Вот как это выглядит:

Сейчас это больше похоже на камень, чем на снег (кто хочет раскрошить асфальт, тому на заметку). Первое что мы сделаем, это применим TurboSmooth. Геометрия тяжелая, поэтому соблюдайте осторожность:
Теперь можно приступать к первичному шейдингу и рендеру. Настройка освещения выглядит незатейливо:
Три источника света с разных сторон, мощностью примерно 2 единицы, цвет белый. Рендер VRay. Мы всегда настраиваем рендер без ГИ, поэтому все настройки по умолчанию: Adaptive DMC, Linear Multiply и т.д. Рендер сермата:
По-прежнему похоже на булыжники. Ничего, Multiscatter и шейдинг это исправят. Приступим к шейдингу этих булыжников.
На всех снежных объектах в этой сцене у меня используется один и тот же шейдер VRayFastSSS2. Единственная разница между ними заключается в использовании разных карт. На крупные и маленькие фрагменты у меня накладываются текстуры разной яркости. Рассмотрим сначала общий шейдер:
Все настройки видно на скриншоте. В данном проекте у меня очень большие единицы измерения (сцена в 10 или даже 100 раз больше оригинального масштаба), поэтому не пугайтесь цифр вроде Scatter radius: 1000 cm. Для общего цвета поверхности самая важная настройка это Sub Surface Color, на которую можно положить карту. Довольно важный параметр Phase function управляет распределением света внутри поверхности - обо всём этом можно прочитать в официальном руководстве VRay. Не забудьте выставить красивый свет перед настройкой, иначе ничего не получится.

На скриншоте видно, что на параметре SSS color лежит карта Composite. Эта карта применяется к большим фрагментам:
Тут по скриншоту видно, что основной цвет поверхности светло-серый, и лишь по заранее нарисованной маске колеи накладывается текстура грязи, которую я выложу здесь:
На бамп накладывается такая же карта. Кусочек рендера:
Мы видим, что по краям наши фрагменты светло-серые, а ближе к колее начинает проявляться текстура грязи.
Для мелких фрагментов используется почти такой же шейдер, но с более темной текстурой на SSS color:
И нойзовой карте на бамп:

Кусочек рендера:

Здесь видно, что колея стала полностью грязной, в то время как боковины более чистыми. Но одновременно с этим, мелкие фрагменты более темные, чем крупные - это вносит разнообразие. Тем не менее, этого недостаточно - поверхность выглядит слишком гладкой и ледяной.
Настало время добавить Multiscatter. Перед этим нужно нарисовать объекты для рассадки. Чем меньше и разнообразнее будут эти объекты, тем лучше будет выглядеть итоговая поверхность. Мы нарисовали 50 вот таких булыжников:
Эти штуки имитируют комочки снега, слипшиеся между собой. Далее рассаживаем мультискаттером эти комочки по всей геометрии сцены: frag1, frag2, базовой плоскости. У меня получилось по 300.000 комков на каждый объект. Разброс по масштабированию примерно 50%, и разброс по осям поворота 100%.
Поскольку Multiscatter берет материалы прямо с объектов рассадки, материал на всех трех мультискаттерах один - тот самый базовый шейдер, который описывался выше, причем без карт. Однако, внутри самого мультискаттера есть параметр Object Color, куда можно бросить уже знакомую нам карту Composite:
Благодаря этой карте, Multiscatter делает разброс по цветам комков, лежащих на колее.
Рендер:
Как мы видим, теперь наши ледяные фрагменты покрыты неоднородной поверхностью снежной жижи, которая выглядит детализированной и насыщенной за счет сложной геометрии комков. Настало время композа.

Часть 3: композ.

Для полноценного композа нам понадобятся каналы. Вот какие каналы я использовал для этого изображения:
Как видите, RGB не использовалось вовсе. Сначала я смешал FastSSS2 с Reflection:
Получился почти бьюти-пасс, но чуть темнее за счет отсутствия канала Lighting - я решил его не использовать. Кстати, Reflection я накладывал не целиком на всю картинку, а отдельно на большие и маленькие фрагменты.
Затем высветлил по маске некоторые части колеи для пущего разнообразия:
Это – самая спорная часть, потому что в видео маску пришлось анимировать в соответствии с перспективой, что нельзя назвать веселой работой.
Потом я добавил текстуру колеи. Ее пришлось рендерить отдельно на лоу-поли плашках, а потом подмешивать к финалу по маскам. Вот рендер колеи:
Здесь не только текстура, но и Blend-материал с отражением на месте замерзших луж. Композ дороги:

 
Здесь, опять же, дорога подмешивается по мягким маскам, которые затем придется анимировать вручную.
Далее я взял и увеличил яркость теней в 3 раза:

Далее цветокоррекция в синюю гамму отдельно по теням и свету:
 
 
 Затем тонирование всей картинки слегка в зеленый оттенок, контраст, виньетирование, аберрации обязательно:
 
 
Ну и, наконец, мы получили рендер снежной жижи, очень разнообразной за счет своей изначальной структуры, усиленной неоднородностью мультискаттера и колеями.
Если этот туториал кому-то непонятен, или кто-то считает, что я плохо или небрежно объяснил сложные моменты, прошу отписаться в комментах - буду рад исправить вместе с вами.
 
775 0 850 34
6
2013-04-25
Спасибо за мейк. Очень познавательно. Только я не нашел конечный ролик.
2013-04-25
Где-то недавно как раз видел этот ролик) Вы его случаем в группу на фейсбуке у кебаса не выкладывали?)
2013-04-25
[b]Masterpiece[/b], конечного ролика пока в сети нет, как появится, обязательно покажу. И потом, здесь мы создаем статику, в этом уроке нет цели создать динамику снежной жижи. Получившаяся анимация разбиения дороги посредством Thinking Particles - побочный продукт :) В реальности, если бы мы хотели сделать действительно полноценно анимированную снежную жижу, думаю, там использовались бы уже другие инструменты, вроде наяда. Хотя в этом ролике у нас колеса взаимодействуют с получившейся геометрией путем вторичной симуляции и композа. [b]Pit3ds[/b], на кебас мы ничего не выкладывали. Единственное, что я выкладывал на фейсбук, в ЖЖ, на вимео - это небольшой брейкдаун по данной дороге. Вот он [url]https://vimeo.com/64587182[/url]
2013-05-06
супер, как раз что надо!
2013-05-29
Всё круто! Но интересует честно говоря больше способ рендеринга и настройки. Про обычные рендеры всё уже разжевано 10 раз и я и сам так могу), но вот как добится такой-же резкости и бокен эффекта как на финалке?! Уже не первый раз вижу такой рендер и все никак не могу понять как так сделать.
2013-06-05
[b]ShInIGameR[/b], прошу прощения за поздний ответ. Давайте определимся: на финале нет эффекта боке, есть только аберрации. Резкость действительно присутствует, но тут не вижу ничего сложного - просто свет подчеркивает каждый кристаллик снега, и плюс небольшой шарп на посте. В остальном, каких-то сильных секретов нет: лайтсетап показан на одной из картинок, а настройки рендера самые обычные, я использую всегда Linear Multiply. Кстати, конкретно в данном случае, возможно, это Exponential.
RENDER.RU