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

Мировое пространство против пространства камеры

Мировое пространство против пространства камеры

Нормаль поверхности, которую мы имеем в распоряжении, определена в пространстве камеры. Это означает, что, например, когда нормаль поверхности указывает прямо в камеру, она определена как (0, 0,-1). В данный момент мы хотим определить нашу нормаль поверхности в мировом пространстве. Нормаль, которая указывает прямо вверх, например, должна иметь величину (0,0,1) независимо от позиции или наклона камеры (в конце концов, растительность на горном склоне обычно не изменяется с изменением угла камеры). К счастью, мы можем провести преобразование из  пространства камеры в  мировое пространство, взяв матрицу камеры мирового пространства и умножив нормаль поверхности на вращающую часть этой матрицы. Результирующий код выглядит похожим на это:

class Slope(Node.Scripted):
   def __init__(self, sockets):
      sockets.output = [Node.Socket('SlopeX', val = 1.0),
                        Node.Socket('SlopeY', val = 1.0),
                        Node.Socket('SlopeZ', val = 1.0),]
      self.offset =  vec([1,1,1])
      self.scale =  0.5

Заметьте, что код инициализации не определяет входных сокетов. Мы получим нормаль поверхности в позиции пикселя, который мы затеняем, из входа shader (выделено в следующей части кода). Мы определяем три отдельных выходных сокета для x, y, и z компонент наклона для удобства использования в нодовой сети.  Так как мы, по большей части, используем именно z-компоненту наклона, то если мы будем иметь её доступной в отдельном сокете, нам не придётся использовать для её извлечения из вектора дополнительный нод обработки вектора.

   def __call__(self):
      scn=Scene.GetCurrent()
      cam=scn.objects.camera
      rot=cam.getMatrix('worldspace').rotationPart(
                             ).resize4x4();
      N = vec(self.shi.surfaceNormal).normalize(
                             ).resize4D() * rot
      N = (N + self.offset ) * self.scale
      self.output.SlopeX=N[0]
      self.output.SlopeY=N[1]
      self.output.SlopeZ=N[2]
__node__ = Slope

Преобразование из пространства камеры в мировое пространство делается в строке, которая ссылается на нормаль поверхности  (выделено). Ориентация зависит только от вращения, следовательно, мы извлекаем вращающую часть матрицы преобразования камеры до того, как мы умножим нормаль поверхности на неё. Так как нормализованный результат может указывать вниз, мы заставляем z-компоненту находиться в дипазоне [0, 1], прибавляя 1 и умножая на 0.5. Полный код доступен как slope.py в файле slope.blend.

Есть одна важная вещь, о которой нужно отдавать себе отчет: нормаль поверхности, которую мы здесь используем, не интерполируется, и, следовательно, она одинаковая везде вдоль поверхности единственной грани, даже если был установлен атрибут грани  smooth. Это не должно быть проблемой в тонко подразделенном ландшафте, где вход наклона не используется непосредственно, тем не менее, это отличается от того, что Вы могли ожидать. В текущей реализации Pynodes это ограничение трудно, если не совсем невозможно, преодолеть.

Следующая иллюстрация показывает возможный пример.


Эффекты, показанные выше, были реализованы объединением различных материалов в нодовой сети, показанной на следующем скриншоте. Эта настройка также доступна в slope.blend. Два нижних материала смешивались с использованием нашего наклоно-зависимого нода, и результирующий материал смешивается с верхним материалом, основанным на Pynode, который вычисляет высоту.


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


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