Книга: Написание скриптов для Blender 2.49

Свежий бриз - текстуры с нормалями

Свежий бриз - текстуры с нормалями

Текстура может иметь больше, чем просто геометрический вход. Если Вам нужна текстура, изменяющая свое поведение в зависимости от другой текстуры, этого не получится достигнуть простой настройкой нодов, которую Вы можете обеспечить дополнительными входными сокетами. Мы разработаем Pynode, генерирующий карту нормалей, которая имитирует небольшие пятна всплесков (wavelets) в пруду во время почти безветренного дня.

Места, где эти пятна появляются, определяются дополнительным входным сокетом, который может быть связан с почти любой текстурой шума. Мы дадим этому входному сокету имя amplitude (амплитуда), поскольку мы используем его, чтобы перемножать с нашими рассчитанными нормалями. Таким образом, наши всплески будут исчезать везде, где наша шумовая текстура будет нулевой.

Длина волн ряби управляется еще одним входом с названием wavelength, и наш нод Ripples (Пульсации) будет также иметь входной сокет для координат.

Четвертый и последний вход, называемый direction - вектор, который контролирует ориентацию наших элементарных волн. Может быть установлено вручную пользователем, но при желании, может быть соединён с нодом normal, который предоставляет простой способ манипулировать направлением с помощью мыши.

Окончательная настройка нодов, которая объединяет все это, показана на скриншоте редактора нодов:


Скрипт для нода прост; после нескольких необходимых операций импорта мы определим многочисленные входные сокеты и наш единственный выходной сокет.

from Blender import Node
from math import cos
from Blender.Mathutils import Vector as vec
class Ripples(Node.Scripted):
   def __init__(self, sockets):
      sockets.input = [
         Node.Socket('amplitude' , val= 1.0, 
                      min = 0.001, max = 1.0),
         Node.Socket('wavelength', val= 1.0, 
                      min = 0.01, max = 1000.0),
         Node.Socket('direction' , val= [1.0,0.0,0.0]),
         Node.Socket('Coords'    , val= 3*[1.0])]
      sockets.output = [Node.Socket('Normal',
                        val = [0.0,0.0,1.0])]
   def __call__(self):
      norm = vec(0.0,0.0,1.0)
      p = vec(self.input.Coords)
      d = vec(self.input.direction)
      x = p.dot(d)*self.input.wavelength
      norm.x=-self.input.amplitude*cos(x)
      n = norm.normalize()
      self.output.Normal = n*.01
__node__ = Ripples

Снова, вся реальная работа выполняется в функции __call__() (выделено в предыдущем куске коде). Мы сначала определяем сокращения p и d для векторов координат и направления соответственно. Наши элементарные волны - функции синуса и позиция на этой синусоиде определяется проекцией позиции на вектора направления. Эта проекция вычисляется скалярным произведением - операция предоставлена методом dot() объекта Vector.


Затем, проекция умножается на длину волны. Если бы мы вычислили синус, у нас была бы высота нашей волны. Но нас, тем не менее, интересует не высота, а нормаль. Нормаль всегда направлена вверх и перемещается вместе с нашей сунусоидальной волной (смотри следующую диаграмму). Можно показать, что эта нормаль - вектор с z-компонентой 1.0 и x-компонентой, равной отрицательной производной функции синуса, то есть, минус косинус. Скрипт (ripples.py) и пример настройки нодов доступны как файл ripples.blend.


В нодовой сети, которую мы показывали раньше, Вы могли обратить внимание, что вместо связи нода геометрии непосредственно с нашим нодом ripples, мы добавили второй нод текстуры, и скомбинировали этот нод с вводом геометрии сложив с масштабированным выходом normal текстурного нода. Мы могли бы смешать с некоторым шумом в ноде ripples непосредственно, но этим способом мы даем значительно больше управления пользователю над типом и количеством шума, который он хочет добавить (если хочет). Это - обычная модель: ноды должны разрабатываться по возможности простыми, чтобы облегчить их использование многократно с различными настройками.

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


Оглавление книги


Генерация: 2.079. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз