Видео доклад (нажмите, что бы проиграть):
Прежде, чем начать разбор инструментов, которые используются при глубоком композитинге в нюке, хотелось бы вкратце рассказать в общем, что такое глубокий композ, и чем он отличается от обычного?
По сути своей, глубокий композитинг представляет собой принципиально иной способ визуализации и работы с визуальными элементами. Что мы имеем при работе с обычными изображениями? Чаще всего применяться обычный метод иерархии слоев, когда одно изображение находиться поверх другого с использованием альфа-канала или масок. Всё довольно просто и понятно, даже для начинающего специалиста.
Однако методы и инструментарии компоузерских программ постоянно меняются и совершенствуются под давлением всё новых и новых обязанностей, которые на них ложатся. Эти обязанности давно уже вышли за пределы простого сведения цветов или создания размытий.
Что, если нам нужно вставить съемочного человека внутрь отрендеренного участка тумана или дыма, или объединить между собою разные атмосферные эффекты, дополнять их, смешивать между собой?
При этом, уже стандартных методов с использованием альфаканала и простого наложения становиться недостаточно. Ведь чаще всего эти элементы просчитываются отдельными изображениями, иногда даже в разных программах. И для того, чтобы всё потом чётко совпало, нужна хорошо отлаженная техника рендера. И что хуже всего, при изменении какого-либо одного элемента – пересчитывать нужно будет все остальные, зависящие от него.
Почему бы просто не отсчитать каждый обьект или эффект отдельно, а потом попросту всё смешать в композере при помощи информации о том, где и что должно находиться? Ведь по сути всё просто. Нам нужно знать порядок. Что за чем. Всё, что ближе будет попросту перекрывать то, что находиться дальше от камеры.
И казалось бы даже решение уже почти найдено – пас глубины – рендер элемент, который указывает на расстояние к каждому пикселю изображения. Дальше рендерим объект – к нему прилагается карта глубины и теперь расставляем все объекты, а если быть точнее, все пиксели согласно расстояния.
Но есть парочка нюансов, которые данное решение отложили на долгое время.
Первое – это особенность самого слоя глубины, который может учитывать расстояние только к 1 обьекту. А если быть точным и занудным – то иметь только одно значение на каждый пиксель, что очевидно, недостаточно.
Почему? Первая проблема очевидна – это anti-aliasing, либо сглаживание. Технология, которая используется для устранения «зубчатости» по краям объекта. Ведь пиксели у нас квадратные и чтобы все округлые, да и в принципе идеально ровные объекты смотрелись реалистично – по краям они размываються. Пиксели крайние становятся в разной степени прозрачными и визуально сглаживают край поверхности.
Отсюда и первая проблема – прозрачность. Ведь если у нас в одном изображении есть несколько объектов, и один находиться за другим – то в этом самом крайнем пикселе будет находиться информация, а если быть точным, то цвет – каждого из них. Как первого так и второго. Поэтому из-за прозрачности, информация о расстоянии также в нём заложена по обоим объектам одновременно. Как это получилось.
Канал глубины использует элементарные значения от нуля до единицы (ну или больше, в зависимости от настроек). Как правило чем меньше значение, тем дальше пиксель.
Вот простая схема определения расстояния. Берём некий крайний пиксель. Его прозрачность 0,15, то есть на 15% его цвет состоит из цвета сферы, на 85% из цвета стены за ней. Допустим, расстояние к крайнему участку сферы будет 0,5. К дальней стенке за сферой расстояние 0,2. Это означает, что на 15% расстояние будет 0,5, а на 85% – 0,2. В итоге получаем значение 0,245. Это некое фантомное расстояние, ни применимое ни к чему, ни к первому объекту, ни ко второму.
Поправим ситуацию – выключим фильтрацию и сглаживание для слоя глубины.
Получаем ситуацию немногим лучшую – теперь мы точно знаем расстояние о всем пикселям сферы, но теперь напрочь отсутствует информация о расстоянии к стенке по краю сферы. И в итоге, если мы помещаем туда некий объект – просто отсекается часть изображения. В итоге у нас отсутствует сглаживание и артефакты по цвету.
Каким же видится выход из данной ситуации? Нужно создать некий массив данных для каждого пикселя в изображении на основе информации о том, какое расстояние имеет каждый объект, цвет которого входит в данный пиксель. Казалось бы, что может быть проще, давайте разобьём по каналам и будем это расстояние показывать в разных каналах, у нас их целых 3.
Но таких расстояний может быть много. Взять то же дерево – каждый листочек практически состоит из полупрозрачных пикселей. А там их сотни. А если деревьев много. Какой формат может в себя вместить десятки значений для каждого пикселя.
Далее, еще один момент – это глубина пикселя. Вот возьмём ту же сферу и какой-нибудь крайний пиксель. Если смотреть спереди, то это обычный, плоский квадратный пиксель. Но если взглянуть сверху, то мы увидим, что представляет собою некую часть сферы, небольшой объем. Так как же определять расстояние – к началу поверхности, которую он представляет, или к концу.
По-этому второй задачей является создать некую точку входа и выхода, или по другому начало и конец этого расстояния для каждого объекта. А если учесть, что к этому нужно привязать значение цвета в 3 каналах для каждого из объектов и его прозрачность – то получается совсем не малый объем информации. Ведь если мы между сферой и стеной что-то поставим – нам нужно знать какого цвета и какой прозрачности будет пиксель сферы, чтобы вычесть оттуда цвет стены – он нам уже не нужен.
Это огромный массив данных. И это только для 1 пикселя. Кажется много да, но геометрия с её сглаживанием нервно курит в стороне по сравнению с волюметриками. Вот тут начинается самое интересное. Даже без пересечений и сглаживаний, любой атмосферный эффект это просто огромный массив прозрачностей.
Ведь тот же дым или туман будет разной плотности и цвета не только на разных участках, но и на разной глубине. И если вы захотите поставить какой-нибудь объект внутрь этого дыма, то вам нужно знать какая плотность и цвет должна быть в итоге. И так на протяжении всего объёма. Или по крайней мере пока плотность пикселя не станет 100%. То есть если он будет 100% непрозрачным еще посредине дыма, то уже дальнейшие расстояния просчитывать нету смысла.
И тут постал вопрос касательно того, можно ли в принципе как-то просчитать и главное – куда-нить впихнуть подобную информацию.
Эта история, как и многие другие, началась еще в Пиксарах, где Ерик Вич и Томас Локович (см. фото ниже) создали функциональную модель хранения прозрачности глубины в карте Deep Shadow Map, которая использовалась для решения проблем при рендере волос а также для запекания освещения, что позволяло рендерить такие вещи как дым или волосы более реалистично.
Эта карта представляла собой некий массив пикселей, в каждом из которых записывалась его степень прозрачности. Работала система довольно просто – прозрачность определялась лучом света, исходящим от источника, который проходил через пиксель. На заданной глубине определялась мощность луча, и разница от начальной мощности. Что и указывало на степень прозрачности.
Этот же принцип был взят за основу, за исключением того, что теперь луч выходил не из источника света а из камеры.
К слову сказать, ребята за это получили Оскар через 14 лет, как они покинули эту индустрию. Наверно был лёгкий сюрприз. Они даже не догадывались о том, что их технология, за это время, притерпев некоторых изменений, достигнет таких результатов.
Несмотря на то, что это произошло довольно таки давно, развитие глубины, именно в композе, произошло сравнительно недавно. Во первых, для манипуляции такими большими данными нужны были мощные компьютеры да и сама технология не давала явных преимуществ в пайплайне на той стадии, где она была.
Мощный прорыв в этом направлении произошел в компании Weta Digital. Работа шла над Avatar. Большое количество растительности, разных существ и атмосферных эффектов позволило по новому взглянуть на глубокий композ. Возможность рендерить персонажей по отдельности без перепросчета окружения, редактирование объёмных лучей в вольюметриках на посту и т.д. Всё это стало реальностью только благодаря глубоким данным.
К тому времени, правда, Nuke этого еще не умел делать. Умел только Shake. Именно в нём и использовалась информация по глубине, которую на то время умел выдавать только Renderman. Но к массиву простых прозрачностей прибавился еще и цвет. До этого, глубина использовалась лишь для того, чтобы создавать маски – попросту вырезая из объекта всё то, что должно перекрываться другими элементами в сцене.
Идея добавления цвета пас глубины заинтересовала Foundry и они создали так называемый дип риколор. Первоначально формат, в котором хранилась информация был ODZ, но уже тогда были планы по переходу на OpenExr2.
Также были определённые сложности с интерполяцией и сжатием данных. Ведь если брать геометрические объекты, то там проще – их конечное число, как мы обсуждали вначале, а вот с вольюметриками было всё сложнее. Без сжатия данных, или каких-то функций, определяющих количество семплов в пикселе – размеры файлов были огромными. Выходом из ситуации были лимитирование до 10 семплов на пиксель в сценах, где не было вольюметриков. Или выборочный рендер. То есть в глубине рендерились только те вольюметрики, с которыми по плану должна была пересекаться геометрия. Остальные же считались либо обычными форматами, либо с лимитированным количеством семплов.
В сам нюк, глубокий композ официально пришел с версии 6,3. Но доработан до полного функционала в версии 7 в далёком 2012 году. По началу Weta пыталась что-то сделать в Shake. Даже после того, как Apple его прикрыл, и получив доступ к исходному коду, Weta пыталась туда его интегрировать. В конце концов, в виду тесного сотрудничества с Foundry по Mary и не только – переключилась на Nuke. Благодаря этому – вначале в виде надстройки, а потом уже в видео интегрированного инструмента, дип композ пришел в Nuke.
В итоге, прежде чем уже коснуться нюка, давайте посмотрим, чем же отличается обычный пиксель от глубокого. Вот один из пикселей листьев дерева. Имеет 6 семплов. Каждый из семплов имеет во-первых, толщину, или глубину. Он может быть или плоским или объёмным. Если плоский – совпадает начало и конец. Дальше – каждый семпл имеет цвет в RGB. Ну и прозрачность. Используя эту информацию, мы можем ставить между ними объекты и при этом программа на основе прозрачности и цвета семплов впереди объекта будет выдавать нужные параметры пикселя. Обо всё этом мы можем узнать из ноды семплинга (DeepSample), которая может нам показать абсолютно всю информацию по выбранному пикселю.
Теперь на примерах посмотрим как работает глубокий композ в Нюке и какими возможностями он обладает.
Для этого Нюк оборудован целым рядом инструментов, напишу лишь основные. Но главное – это понять методы работы и смысл в этом. Стоит ли разрушать стандартные принципы и методы композа ради этого.
Поскольку глубокое изображение – это принципиально новый тип информации, то и работа с подобной информацией также немного отличается. Во-первых, к такому типу изображения мы можем применять только определённые инструменты. Ни один инструмент для работы с обычными 2-х мерными изображениями нам не поможет. Мы его даже подключить не сможем.
Итак, начнём с загрузки глубокого изображения. За это отвечает нода Read, только в отличии от обычной Read– эта называется DeepRead, и загружает всего 2 типа файлов – DTEX (получаемых с Renderman) и Scanline OpenEXR 2.2. Если для чтения первого нам нужен Renderman, то для считывания ЕХР нам кроме Нюка больше ничего не понадобится. Если в нём присутствует глубокая информация, то всё ок. В противном случае получим ошибку.
Визуально, сама картинка ничем не отличается от обычного изображения, и даже можем посмотреть на слои, из которых она состоит – всё как прежде. Но если посмотреть на неё с другой стороны, или даже с разных сторон, то увидим, что это набор семплов, или набор пикселей в 3Д пространстве (при помощи ноды DeepToPoints). И каждый из этих пикселей имеет своё положение, цвет, прозрачность, глубину и т.д. И это, конечно, не единственное отличие. Первое- время рендера, как вы можете увидеть – гораздо больше. 32 минуты против 18 с теми же настройками и разрешением. Кроме того вес файла также больше – 126 мегабайт против 6-ти. И, пожалуй, это единственный, хоть и существенный недостаток. Ну а судить о преимуществах и решить, чего всё-таки больше, мы уже будем в конце.
Знакомыми также кажутся и названия нод для роботы с глубиной – тот же transform, reformat, crop, color correct, merge и т.д. Только единственное и самое важное отличие – работают только с глубокими изображениями и существует ряд ограничений.
Первое ограничение – это трансформация. В ввиду того, что это некий массив объёмных данных, которые визуально можно представить в виде неких кубиков или плоских квадратов, размещённых в пространстве – то и трансформировать их нужно немного по другому. С обычными изображениями мы можем делать практически всё, что угодно – растягивать их перемещать, поворачивать, изменять масштаб, всё что хотим.
Но если глянуть на дип трансформ, то можно увидеть, что количество параметров очень скудное. Всего-то translate и scale. Но и это еще не всё. Translate (перемещение) работает только в импульсном режиме. То есть мы обычным “трансформом” обычное изображение можем переместить на любое значение, хоть на пол пикселя, хоть на десятую часть. При этом применяются фильтра, которые распределяют цвет пикселя на соседние. Но в случаи с глубоким изображением такая процедура невозможна, поэтому картинка перемещается с шагом в один пиксель. По этой же причине мы не можем и масштабировать или поворачивать изображение. Параметр скейл лишь подвигает изображение ближе по расстоянию к камере. Но при этом, само изображение не масштабируется, сохраняя размер. В этом особенности глубоких изображений – казалось бы, не совсем удобно ими манипулировать. Но есть инструменты, которые наоборот – при работе с глубиной имею больше функций. Так нода цветокорекции ColorCorrect может теперь корректировать не только по диапазону яркости, выбирая тени, хайлайты и средние тона, но и по расстоянию. Всё, что нам нужно – это выбрать диапазон дальности, на которую будут воздействовать изменения в цвете. При этом, регулируя 4 параметра, мы можем края этого диапазона смягчать, дабы не было резких переходов по цвету.
Тоже самое нода Crop – может теперь обрезать изображение не только по выбранному формату или размеру, а и по глубине. Всё остальное будет попросту вырезаться.
Но, пожалуй, перейдём к главному – какие же новые возможности даёт нам глубина при композе. В чём преимущество и есть ли оно вообще.
Ну, говоря о глубине, первое что приходит на ум – это вставка каких-то дополнительных объектов в изображение на расстоянии, чтобы программа автоматически вырезала их из элементов, стоящих по первому плану.
Вот к примеру корабль, на палубу которого нужно поместить человека.
Сделать это можно несколькими способами. Ну, понятно, маской вырезать проще всего, или получить маску ограждения палубы при рендере с 3D. Да, в такой простой ситуации можно обойтись и этим, но если человек не 1, а много и перекрывать их будут разные объекты на разном расcтоянии – тут никаких масок не напасёшься, а ротоскопить на каждого человека – будет слишком затратно по времени.
В Нюке также часто практикуется возможность использовать сам 3D объект, как маску, загружая его модель в Нюк и комбинируя элементы внутри 3D пространства. Ставим плоскость внутри 3Д геометрии корабля, проецируем на неё изображение человека – а дальше, как говорится, дело техники. В роди всё просто, да и такими людьми мы можем хоть усыпать весь корабль. Но вот, снова этот пресловутый anti-aliasing. Ведь при создании сглаживания используются разнообразные фильтры и режимы, поэтому сглаживание края одного и того же элемента в разных программах будет разным. И если мы рендерим в Нюке 3Д объект – то сглаживание будет совсем другим. Особенно в мелких деталях. Это во первых, а во-вторых, не всегда можно загрузить всю хай-поли геометрию в Нюк для комфортной работы. Как правило используется лоу поли. Всё таки не 3D пакет.
Поэтому вариант с глубиной будет не плохим. Ведь всё, что нам нужно – это импортировать камеру и само глубокое изображение. Мы с легкость вычисляем при помощи семплера расстояние к краю объекта по переднему плану, или расстояние к объекту на заднем плане и размещаем картинку между ними при помощи всё той же плоскости в 3Д режиме. Как видите, в результате этого, никаких проблем со сглаживанием нет.
Все глубокие изображения объединяет хорошо известная всем нода Merge. Ну только, естественно она называется DeepMerge и также имеет свои особенности. Прежде всего, отсутствие любой манипуляции со слоями, каналами или режимами объединения. Всё, что она делает – объединяет между собой глубокие изображения и на основе информации о расстоянии – размещает относительно друг друга все пиксели подключенного изображения.
И преимуществом этого является возможность визуализации/рендера элементов по отдельности не используя масок, затеняющих объектов (matte objects) или с использованием альфы -1. Вот к примеру тот же взрыв, изображение которого вы видели выше. И время рендера больше и места занимает кучу. Но мы часто сталкиваемся с ситуацией, когда сама симуляция состоит из нескольких частей. Основной взрыв, взрывная волна, пыль, дым от осколков и т.д. И часто, все эти элементы одной и той же симуляции делаются в разных контейнерах. Но рендеряться вместе. В итоге, если нам нужно будет заменить какой-то один элемент (допустим замедлить/ускорить взрывную волну, или поменялась траектория осколков – нужно менять дым от них), то “перерендеривать” нужно будет весь взрыв целиком. А если у нас взрыв не один, или же есть еще какие-то атмосферные эффекты в сцене? Правки приведут к долгим перепросчетам. Используя же глубокие элементы, мы просто делаем заново рендер только изменённого фрагмента и программа сама правильно “интегрирует” его со всеми остальными. (яркий пример – наш вебинар по FumeFX 4 https://www.youtube.com/watch?v=khVM85m7mIw Техника композа взрыва с использованием deep data).
Исходя из этого, не сложно представить себе схему работы глубокого композа. На входе мы имеем множество глубоких элементов, каждый из которых просто объединяется в мердже с другими объектами и в итоге получаем финальное изображение. Возникает вполне логичный вопрос. А где же собственно композ? То есть расстановка объектов это хорошо, но ведь композ предусматривает еще много разных действий, начиная со сборки пасов, заканчивая цветокором, дефокусом, моушн блюром и прочими вещами. Но как мы уже знаем, обычные инструменты Нюка, которые бы нам в этом помогли не подключаются к глубоким изображениям.
Выход вполне логичен – конвертировать глубокое изображение в обычное и дальше работать по накатаной схеме.
Да, есть такая возможность при помощи ноды DeepToImage – создать привычную нам среду для работы. Но снова проблема – если я хочу покрутить и подкорректировать каждый объект по отдельности. Это логично. Но если мы их конвертируем в самом начале, то не сможем потом объединить при помощи DeepMerge, ведь мы уже манипулируем обычными изображениями.
Поэтому тут можно использовать 2 простые схемы. Первая – использовать DeepMerge как маску, или HoldOut. Допустим, я хочу вставить в экстерьер автомобиль. Я перевожу глубокие изображения в обычные, что даёт мне возможность проводить сборку пасов и цветокор в привычной манере. Тоже самое и с экстерьером. Но при объединении обычных изображений в DeepMerge нам нужно указать маску для автомобиля, чтобы он разместился за столбом. И вот для этого мы используем глубину – мы объединяем глубокие изображения, но теперь я указываю режим HoldOut и программа создаёт мне маску для автомобиля, которую я и подключаю в итоге к ноде Merge.
И вторая схема при помощи ноды DeepToImage мы конвертируем глубокое изображение в обычное, далее делаем сборку и цветокорекцию и потом, все изменения, которые мы провели в слое RGB мы переносим обратно в глубину при помощи ноды DeepRecolor. В итоге имеем и глубокое изображение и коррекцию привычными нам методами. И таким методом мы можем “обрабатывать” каждый элемент сцены, после чего обьеденять воедино.
Также есть еще одна схема (не являюсь её фанатом, но некоторые люди в забугорных уроках любят её показывать). Каждое глубокое изображение вырезается, используя Holdout ноды DeepMerge по альфаканалу. В итоге мы получаем обычное изображение, но с вычетом всех элементов, которые его должны затенять и с минусом самого канала depp, так как он нам дальше не нужен. То есть, по сути, мы получаем тот же рендер, который получали раньше с 3Д пакета – с масками и затеняющими элементами.
Все преимущества глубины пропадают ровно на третей ноде сверху)) Поэтому, вариант довольно простой, но не во всех случаях подойдёт. Для fullCG шота скорее всего не плох, но если вдруг нам позже, на этапе дальнейшего композ, а если понадобиться снова глубина – нужно будет её “выковыривать из первых рядов”. Хотя….кому, как – на вкус и цвет – сами знаете.
Более детальное изучение работы с глубоким композом доступно в онайн-тренинге по программе Nuke на сайте cg-school.org.
Что хотелось бы написать в итоге.
Основываясь на, хоть и небольшом пока, опыте работы с глубокими изображениями, хочется отметить, что данный тип композа является довольно перспективным в использовании не только в студиях, но и в “частных” проектах. Прежде всего это проявляется при работе с визуальными эффектами.
Больший объем данных и более длительное время просчета перекрывает возможность боле быстрой коррекции, замены, изменений или добавления любого элемента в сцену без перепросчета остальных. В некоторых случаях даже даёт преимущество во времени рендера.
Иногда, при рендере массивных стимуляций, созданных в нескольких контейнерах – время просчета каждого элемента в сумме гораздо меньше времени просчета всех симуляций в целом (в примере с вебинара – рендер всего взрыва занимает около 2-х часов на кадр, тогда как сумма времени рендера каждого элемента меньше часа).