Написание скриптов для Blender 2.49 - Michel Anders
Шрифт:
Интервал:
Закладка:
im.reload()
Window.RedrawAll()
if __name__ == "__main__":
run()
Полный код доступен как strip.py в файле combine.blend.
Рабочий процесс — использование strip.pyСоздать ленту анимационных кадров можно следующим образом:
1. Создать вашу анимацию. (Ага, это, конечно самый простой пункт ;) -прим. пер.)
2. Запустить strip.py из текстового редактора.
3. Комбинированное изображение появится в окне редактора UV/image.
4. Сохранить изображение с именем по вашему выбору.
Рендер билбордов
Слово Billboard дословно переводится как «доска для объявлений» или «рекламный щит», что конечно же мало подходит для нашего случая. В разработке игр billboards часто применяются, и к сожалению, адекватного перевода для этого нигде нет, везде используется эта уродливая транскрипция «билборд». Придётся и мне ей пользоваться - сожаление переводчика.
Реализм в сценах часто обеспечивается массой деталей, особенно на естественных объектах. Тем не менее, такой реализм даётся небесплатно, так как детализированные модели часто содержат много граней, и эти грани поглощают память и увеличивают время рендера. Реалистичная модель дерева может содержать больше полмиллиона граней, так что лес из них будет почти невозможно отрендерить, и, тем более, если этот лес является частью пейзажа в игре, идущей в быстром темпе.
Блендер поставляется со множеством инструментов, позволяющих уменьшить количество необходимой памяти при рендере множества копий объекта; различные Меш-объекты могут ссылаться на одни и те же данные меша, как, например, при DupliVerts. (Объекты-потомки, которые копируются в позицию каждой вершины родительского объекта. Смотри http://www.is.svitonline.com/sailor/doc/man/specmod/dupliverts.htm более подробно.) Дублирование объектов в системах частиц также позволяет нам создавать множество экземпляров того же самого объекта без действительного дублирования всех данных. Эти методы могут предотвратить потери огромного количества памяти, но детализированные объекты все еще могут требовать процессорных мощностей для рендера, поскольку их детали все еще должны быть отрендерены.
Билборды являются методом, используемым для наложения изображения сложного объекта на простой объект, такой, как например, одиночная квадратная грань, и размножения этого простого объекта столько раз, сколько нужно. Изображение должно иметь подходящую прозрачность, в противном случае каждый объект будет закрывать другие не так, как требуется. За исключением этого момента, такая техника очень проста и может значительно уменьшить время рендера, и она даёт довольно реалистичные результаты для объектов, установленных на средних расстояниях или дальше. Системы частиц Блендера могут использовать билборды или как простые квадраты с наложенными изображениями, или накладывать изображение на простой объект и использовать его, как объект дублирования. Последнее также относится и к объектам duplivert.
Хитрость в том, что нужно сгенерировать изображение с подходящим освещением, чтобы использовать его как изображение, которое можно приложить к квадрату. На самом деле мы хотим создать два изображения: одно снятое с передней стороны, одно справа и построить объект, состоящий из двух квадратных граней, перпендикулярных друг другу с наложенными двумя изображениями. Такой объект даст нам несколько больше свободы в последствии при размещении камеры на нашей сцене, так как он не обязательно должен быть виден точно с одной стороны. Это хорошо работает только для объектов с приблизительно цилиндрической симметрией, как например, деревья или многоэтажки, но зато это очень эффективно.
Рабочий процесс для создания таких объектов достаточно сложен, так что его желательно автоматизировать:
1. Спозиционировать две камеры, спереди и справа от детального объекта.
2. Откадрировать обе камеры, чтобы они захватывали весь объект с одинаковым углом.
3. Отрендерить прозрачные изображения с premultiplied (заранее перемноженным) альфа-каналом и без неба.
4. Создать простой объект из двух перпендикулярных квадратов.
5. Наложить каждое отрендеренное изображение на квадрат.
6. Скрыть детальный объект от рендера.
7. Необязательно, скопировать простой объект в систему частиц (пользователю может не понадобиться автоматизировать эту часть, если он захочет расставить простые объекты вручную).
"Premultiplication", упомянутое в третьем шаге, возможно, требует некоторого пояснения. Очевидно, отрендеренные изображения нашего сложного объекта не должны показывать никакого фонового неба, так как их скопированные клоны могут позиционироваться где угодно, и могут показывать различные части неба через свои прозрачные части. Как мы увидим, это достаточно просто сделать, но когда мы просто рендерим прозрачное изображение и перекрываем им позже некоторый фон, изображение может иметь некрасивые бросающиеся в глаза края.
Способ избежать этого - отрегулировать отрендеренные цвета, перемножив их с величиной альфы и контекст рендера имеет необходимые атрибуты, чтобы включить такой режим. Мы не должны забывать отмечать изображения, рендеренные как "premultiplied", при использовании их в качестве текстур, в противном случае они будут выглядеть слишком тёмными. Различие проиллюстрировано на следующем скриншоте, где мы скомпоновали и расширили правильно premultiplied левую половину и отрендеренную с небом правую половину. У ствола дерева справа проявляется светлый край. (Посмотрите отличную книгу Роджера Викса "Foundation Blender Compositing", если нужна дополнительная информация.)
Буковое дерево (использованное на этой и последующих иллюстрациях) - это высокодетальная модель (свыше 30,000 граней), созданная Yorik van Havre с помощью свободного пакета моделирования растений ngPlant. (Смотри его вебсайт для большего количества отличных примеров: http://yorik.uncreated.net/ greenhouse.html). Далее первый набор изображений показывает буковое дерево спереди и результирующий рендер передней грани билборда слева. (немного темнее из-за premultiplication).
Следующий набор скриншотов показывает то же буковое дерево, отрендеренное справа вместе с рендером правой грани билборда слева. Как может быть заметно, исполнение конечно, не идеально с этой точки зрения, но это крупный план, а разумный трехмерный аспект сохраняется.
Чтобы показать, как устроена конструкция билбордов, следующий скриншот показывает две грани с наложенными отрендеренными изображениями. Прозрачность умышленно уменьшена, чтобы было видно отдельные грани.
Нашей первой проблемой будут некоторые ранее используемые функции, которые мы писали для презентации модели с несколькими видами. Эти функции находятся в текстовом буфере с именем combine.py, и мы не сохраняли его во внешний файл. Мы создадим наш скрипт cardboard.py как новый текстовый буфер в том же .blend файле, где и combine.py, и хотим ссылаться на последний так же, как на внешний модуль. Блендер позволяет это делать, так как он ищет модуль в текущих текстовых буферах, если он не может найти внешний файл.
Поскольку внутренние текстовые буферы не имеют информации о том, когда они последний раз изменялись, мы должны убедиться, что загружена самая последняя версия. Об этом позаботится функция reload(). Если мы её не выполним, Блендер не сможет обнаружить возможных изменений в combine.py, что могло бы провести нас к использованию его более старой скомпилированной версии:
import combine
reload(combine)
Мы не будем использовать заново функцию render() из combine.py, поскольку сейчас у нас другие требования для рендеренных изображений, которые мы наложим на билборды. Как уже объяснялось, мы должны убедиться, что мы не получим никаких светлых краёв в местах с частичной прозрачностью, так что мы заранее включаем premultiply в альфа-канале (выделено). Мы восстанавливаем контекст рендера в 'рендер неба' (rendering the sky) обратно до возврата из этой функции, поскольку легко забыть установить его обратно вручную, и Вы можете потратить время на удивление, куда подевалось ваше небо:
def render(camera):
cam = Object.Get(camera)
scn = Scene.GetCurrent()
scn.setCurrentCamera(cam)
context = scn.getRenderingContext()
frame = context.currentFrame()
context.endFrame(frame)
context.startFrame(frame)
context.displayMode=0