15 окт. 2010 г.

motion vector pass для blobby surface

Как известно, motion vector pass - очень полезный пасс, но просчить его можно только для объектов с регулярной топологией. Иными словами, точка поверхности объекта должна быть однозначно определена на протяжении интересующего нас отрезка анимации.
Blobby Surface же не является регулярной, её топология генерируется в каждом фрэйме независимо. Motion vector pass привычным путем посчитать для нее не получится, поэтому вооружимся спецификацией стандарта, например от RE:Vision и вспомним курс векторной геометрии.

В изображение пасса записываются скорости конкретных точек поверхности, в пространстве камеры. Горизонтальной скорости соответствует красный канал, вертикальной - зеленый. Нам предлагают использовать на выбор два варианта, 16-битное целочисленное хранение цвета пикселов, либо 32-битное с плавающей запятой. Тут нужно оговориться, что в 32-битное изображение отрицательные числа (например, если объект двигается в сторону противоположную оси) записываются как есть, а в 16-битном используется следующая хитрость: нулевые значения записываются, как 0.5, а положительные и отрицательные - соответственно прибавляются или отнимаются от него. Именно поэтому неподвижные объекты на Motion Vector Pass изображении имеют такой "горчичный" цвет (0.5, 0.5, 0.0).

Итак начнем. Назначим нашей Blooby поверхности обычный Surface материал, чтобы избежать лишних просчетов. На его Out Color подключаем ноду Particle Sampler, она и будет окрашивать её цветом партиклов.

Теперь перейдем к камере из которой мы собираемся визуализировать изображение. Создадим ноду pointMatrixMult,
createNode pointMatrixMult;
и соединим её с нашей камерой (как на изображении ниже). Этот узел вычисляет положение точки в мировых координатах. И сразу же делаем два дубликата этого узла, с включенной опцией Duplicate input connections, добавляем к именам суффиксы X и Y и вводим в их аттрибуты In Point значения (1, 0, 0) и (0, 1, 0) соответственно. Так мы получим мировые координаты двух точек - направлений единичных векторов x и y в пространстве камеры.

Возьмемся за частички. Напишем для них выражение, которое будет вычислять центральную проекцию вектора скорости на плоскость изображения, а это ничто иное, как скалярное произведение проецируемого вектора на единичный вектор плоскости проекции (изображения или камеры), деленого на расстояние от цента проекции.
Уфф, еле выговорил.
vector $cam = `getAttr pointMatrixMult.output`;
// позиция камеры
vector $camx = `getAttr pointMatrixMultX.output`;
// позиция точки смещенной от камеры на 1 по x
vector $camy = `getAttr pointMatrixMultY.output`;
// позиция точки смещенной от камеры на 1 по y

vector $x = $camx-$cam;
vector $y = $camy-$cam;
// единичные вектора плоскости изображения
// камеры в мировом пространстве координат

float $dist = mag($cam-particleShape1.position);
// расстояние от конкретной частички до цента проекции - камеры

float $xp=(dot($x, particleShape1.velocity))/$dist;
// проекция по оси x
float $yp=(dot($y, particleShape1.velocity))/$dist;
// проекция по оси y

particleShape1.rgbPP=<<$xp,$yp,0>>;
// искомый цвет партикла для изображения с плавающей запятой

Некоторые участки выглядят черными, но в действительности в них записаны отрицательные значения.

Либо же для 16-битного изображения, заменим последнюю часть выражения этой:
float $k = 0.5;
particleShape1.rgbPP=(<<0.5,0.5,0>> + <<$xp*$k,$yp*$k,0>>);
Где $k будет являться коэффицентом, подбираемым опытным путем с расчетом, чтобы значения цвета не выходили за границы от 0 до 1 (иначе они отсекутся), а с другой стороны, чтобы максимально эффективно использовать данный диапазон.

Для верности выбираем текущим рендерером MentalRay, выставляем в настройках Framebuffer нужный тип данных RGBA(Float)32 bit либо RGBA(Short)16 bit и считаем изображения в формат поддерживающий его, например OpenExr.

Данный пример не претендует на звание единственно-верного и был выполнен как упражнение на понимание основ векторной геометрии.

11 комментариев:

  1. познавательно.. :) композом не занимаюсь но на всякий случай буду иметь ввиду

    ОтветитьУдалить
  2. Очень интересно, молодец! Меня тоже МЕЛ заинтересовал. Можно вопрос не по теме? Посмотрел твое резюме, там написано "Тихоокеанский Гос Университет". Это который в Хабаровске? Я сам из Хабаровска.

    ОтветитьУдалить
  3. да, верно, Хабаровский политен

    ОтветитьУдалить
  4. ЗдОрово вот так земляка повстречать, который тоже увлекается 3Д графикой.

    ОтветитьУдалить
  5. привет.. у мну как раз появилась задача сделать моблюр на частицах.. их ОЧ много... я так понял что если делать по твоей схеме, то получается надо 2 раза визуализировать? ну сначала изображение а потом вектор пасс? так? или я ошибаюсь?

    ОтветитьУдалить
  6. Добрый день. на самом деле у меня задача довольно специфическая рассмотрена, если ты используешь тип частиц именно blobby, и хочешь блюрить именно на посте.

    для всех остальных должен сработать и стандартный вывод векторов.

    а так же ничто не мешает посчитать честный моушенблёр.

    ОтветитьУдалить
  7. привет ещё раз. не работает зараза стандартный вывод... а честный моблюр - ренедер уходит в бесконечность....

    ОтветитьУдалить
  8. а какой тип частиц у тебя и какой рендерер?

    ОтветитьУдалить
  9. нпартиклс из них вылетают простые частицы.
    а тип cloud (s/w)

    ОтветитьУдалить
  10. совета два:
    1. посчитать все это добро рендерманом, его честный моушен блёр фактически "бесплатный".

    2. с клаудами в любом случае будут некоторые проблемы, т.к. у них есть прозрачность. попробуй бьюти посчитать с клаудами(но только отдельно от всего остального), а велосити со сферками
    идентичного радиуса, но в настройках ментала все равно нужно включить фул моушен блёр, а его шатер клоуз поставить в 0,001. результат может сработать а может и нет.

    ОтветитьУдалить

счетчик посещений