Привет, Хабр! На связи Глеб, ML-разработчик Friflex. В этой серии статей я делюсь своим опытом работы с Blender (мы используем Blender для работы над нашими проектами по оцифровке спорта). В предыдущих статьях мы говорили о работе с объектами и с камерами: научились наводить объектив на объекты, менять фокусное расстояние и многое другое. В этой статье мы поговорим о том, как сделать сцену более реалистичной: настроим освещение, добавим тени, создадим текстуру для объекта, свойства которой будем менять через API.
Содержание:
Собираем генератор данных на Blender. Часть 3: Материалы и освещение
Материалы
Мы не будем вдаваться в создание сложных текстур – это целое искусство, которому можно посвятить отдельный цикл статей. Наоборот, мы создадим простой материал и сделаем акцент на том, как работать с ним через API.
Материалы в Blender позволяют влиять на внешний вид объектов. Например, мы можем поменять цвет, прозрачность, шероховатость и т.д. В этой статье мы рассмотрим, как работать с этими свойствами через API.
Только что мы перешли в раздел редактирования материалов – «shading». Теперь создадим простой материал с названием «custom material» и установим его на наш куб.
Попробуем изменить цвет нового материала.
Отлично! Наш куб приобрёл фиолетовый цвет. Но теперь давайте разберемся в том, как получить доступ к материалу через API.
material = bpy.data.materials['custom material']
Перед тем как двинуться дальше, давайте посмотрим на то, что представляет из себя материал.
Материал состоит из узлов, которые влияют на внешний вид. Это создает небольшую сложность: нам нужно получать доступ не к самому материалу, а к конкретному узлу, свойство которого мы хотим изменить. Но есть подход позволяющий избежать этой путаницы. Для этого нам нужно рассмотреть «пользовательские свойства» (aka. custom properties) и «драйверы».
Пользовательские свойства
В первой части мы работали с базовыми свойствами объекта: location, scale, и т.д.
cube = bpy.data.objects[‘Cube’]
cube.scale.x = 2
К счастью для нас, Blender предоставляет возможность создавать собственные свойства, доступ к которым можно получить схожим образом.
Только что мы создали свойство, которое будет отвечать за изменение цвета объекта. Давайте попробуем получить к нему доступ.
cube = bpy.data.objects[‘Cube’]
list(cube[‘color’]) # Получим [0, 0, 0]
Однако, если сейчас мы попробуем изменить color, то ничего не произойдет. Мы не объяснили blender-у, что он должен делать, когда мы меняем свойство.
Драйверы
В Blender драйверы позволяют создавать связи между двумя и более свойствами. Сейчас мы можем привязать color (свойство материала) к пользовательскому свойству куба, которое мы создали в предыдущем блоке. Первым делом нам нужно получить путь свойства, к которому будет происходить привязка.
Теперь перейдем к свойству, которое будем привязывать, создадим для него драйвер и откроем редактор драйверов.
В редакторе мы проведем простую привязку одного свойства к другому. Для лучшего понимания драйверов, советую прочитать эту статью.
Теперь, когда мы будем менять пользовательское свойство куба, вместе с ним автоматически будет меняться привязанное свойство материала. Только заметим, что свойство color состоит из трех значений: red, green, blue. На данный момент мы привязали только r-канал. g и b каналы можно привязать аналогичным образом.
cube = bpy.data.objects[‘Cube’]
cube[‘color’] = 0.5
Важно, что если попробовать применить код из примера выше в консоли Blender, то внешне ничего не произойдет. Изменения будут видны на изображении после рендеринга.
Освещение
Перейдем к не менее интересной теме – источники света. В Blender есть четыре вида излучателей: «Spot», «Point», «Area», «Sun». Чтобы создать представление о том, как каждый из них работает, предлагаю посмотреть это видео. Мы же перейдем к их рассмотрению с точки зрения API. И первым делом, получим доступ к источнику света.
light = bpy.data.lights['Light']
Color
По умолчанию любой источник света использует белый свет. С помощью свойства color мы можем это менять. Для примера, сделаем цвет свечения лампы более фиолетовым.
light = bpy.data.lights['Light']
light.color = (0.33, 0.01, 1.0)
Energy
Это свойство отвечает за мощность излучателя. Единицей измерения является ватт.
light = bpy.data.lights['Light']
light.energy = 100
Процедурная генерация излучателей
Blender предоставляет возможность создавать новые объекты через API. Попробуем создать новый конический источник света.
spot = bpy.data.objects.new(
'SpotLight',
bpy.data.lights.new('SpotLight', 'SPOT')
)
В примере выше мы создали объект типа bpy.types.Object с названием SpotLight и поместили в него (в свойство data) источник света со схожим именем и с типом bpy.types.SpotLight
Однако, если сейчас посмотреть на список объектов, расположенных на сцене, окажется, что нашего объекта нет. В Blender нельзя просто так взять и создать объект, его ещё нужно поместить в какую-нибудь коллекцию, чтобы он был добавлен на сцену.
collection = bpy.context.scene.collection
collection.objects.link(spot)
Таким образом, мы добавили нашу лампу в основную коллекцию сцены и теперь можем с ней взаимодействовать.
Rotation
Чтобы изменить направление свечения, достаточно повернуть излучатель на сцене. Для этого мы будем использовать стандартное свойство объектов – «rotation_euler».
spot = bpy.data.objects['SpotLight']
spot.rotation_euler = (1, 1, 1)
Наведение на объект
Предположим, что мы хотим навести лампу, созданную на предыдущем этапе, на наш куб. Для этого мы можем использовать функцию, которую рассмотрели в статье о работе с камерами.
def point_ligth_at(
ligth: bpy.types.Object,
target: mathutils.Vector,
track_axis: str = 'Z',
up_axis: str = 'Y'
):
vector = ligth.location - target
ligth.rotation_euler = vector.to_track_quat(
track_axis,
up_axis
).to_euler()
light = bpy.data.objects['Light']
cube = bpy.data.objects['Cube']
point_ligth_at(light, cube.location)
The end
Если вы работали с blender и хотите обсудить прочитанное или поделиться своим опытом и знаниями, жду вас в комментариях! Сделаем статью более полной и полезной для новичков.