Управляющие структуры в OSL

23 ноября 2013 1 комментарий Артем Слаква Скриптинг на Python

Данная статья является продолжением перевода книги об OSL в Blender, которая вышла примерно месяц назад. Если Вы не читали первую статью, то обязательно сделайте это, иначе много моментов могут быть не понятными.


Принятие решений и генерация различных выходных значений на основе некоторого условия присутствует почти в каждом шейдере. В примере ниже мы будем генерировать выходное значение, равное 1 в случае, если входные значения будут находиться в заданных диапазонах. Такой шейдер можно использовать для получения острых граней из гладкой/шумной поверхности.
shader-osl1

1
2
3
4
5
6
7
8
9
10
11
shader range(
  float Value = 0,
  float Low = 0,
  float High = 0,
 
  output float Fac = 0
){
  if( Value >= Low && Value <= High ){
    Fac = 1;
  }
}

Шейдер имеет 3 входных параметра: значение, которое мы хотим проверить, и два значения, указывающих на диапазон, в результате чего будет возвращаться 1 или 0 для выходного параметра Fac.

Тело шейдера состоит всего из одной строки (строка 8). В ней мы проверяем больше, либо равно значение Value, относительно параметра Low, а также меньше, либо равно, относительно High. Оператор && (логическое И) означает, что оба условия должны быть истинными.

Теперь немного доработаем шейдер, и тем самым добавим новый функционал в него.
shader-osl2
Добавились три дополнительных входных параметра цвета, которые мы можем изменять. Единственный выходной параметр — выбранный цвет.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
shader range(
  float Value = 0,
  float Low = 0,
  float High = 0,
  color LowColor = 0,
  color MidColor = 0.5,
  color HighColor = 1,
 
  output color Color = 0
){
  Color = LowColor;
  if( Value >= Low && Value <= High ){     
    Color = MidColor;   
    } else     
   if( Value > High ){
    Color = HighColor;
  }
}

Одиннадцатая строка присваивает значение LowColor выходному параметру по умолчанию. Затем снова проверяется, находится ли входное значение Value в заданном диапазоне значений Low и High. Если да, то выходному параметру присваивается значение MidColor. Если нет, то выполняется строка 14. Данное условие проверяет, выше ли значение Value параметра High. Если да, то присваивает выходному параметру значение HighColor.


Принятие решений является фундаментальной чертой языка программирования, а также возможность повторять определенные действия указанное количество раз. Таким образом, с помощью следующего шейдера, мы можем генерировать нужное нам количество полос.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
shader stripes(
  point Pos = P,
  int Numder = 4,
 
  output float Fac = 0
){
  float x = mod(Pos[0],1);
 
  int i;
  for(i=1; i <= Numder; i++){
    if( x < (float)i/Numder ){
    Fac = i % 2;
    break;
    }
  }
}

Два входных параметра нода указывают на позицию, с которой нужно начинать создавать полосы, и их количество. Выходной параметр Fac принимает значения либо 0, либо 1.
shader-osl3
В теле шейдера мы указываем, что значение параметра X может принимать значения 0 или 1. Далее мы объявляем переменную i. В строке 10 находится цикл, который выполняется заданное количество раз. После каждого выполнения цикла происходит проверка параметра X. В момент первого выполнения цикла условие выглядит — х < 1/4, во время второго — х < 2/4 и т.д. Обратите внимание, что переменная i переведена с целого числа, на число с плавающей запятой, чтобы мы при делении целых чисел не получали в результате 0.

Если значение истинно, то мы присваиваем выходному значению Fac значение переменной i по модулю 2. Таким образом, значение Fac будет чередоваться между 0 и 1, в зависимости от того, что параметр i является четным или нечетным. В случае истинности выражения, мы не только присваиваем значение для выходного параметра, но также останавливаем выполнение (строка 13). Это делается для того, чтобы при продолжении выполнения итераций цикла мы вновь не получали значение true (ведь если 1/4 меньше x, то и 2/4 и 3/4 также будут меньше).


Не всегда бывает нужным произвести какое-то определенное количество полос. Бывают случаи, когда необходимо выполнять какое-то условие до тех пор, пока условие является истинным.

В следующем примере мы будем создавать все меньшие полосы до тех пор, пока ширина полосы не будет считаться совсем малой. Основной идеей данного примера является проверка условия x < xlimit, а если нет, то увеличить данное значение на значение dx и проверить еще раз. На каждой последующей итерации значение dx уменьшается на четверть, пока не станет меньше, чем входной параметр Limit.
shader-osl4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
shader smallerstripes(
  point Pos = P,
  float Limit = 0.01,
 
  output float Fac = 0
){
  float x = mod(Pos[0],1)*2;
  float dx = 0.5;
  float xlimit = dx;
 
  float ActualLimit = 
    Limit>0.001 ? Limit : 0.01;
  while( dx <= ActualLimit ){
    if( x < xlimit ){
      break;
    }
    Fac = abs(Fac-1);
    dx *= 0.75;
    xlimit += dx;
  }
}

Для предотвращения бесконечного цикла мы проверяем, больше ли значение Limit некоторого малого значения, и если да, то назначаем его переменной ActualLimit. Если нет, то берем 0,010 в качестве безопасного минимума. Мы ввели дополнительную переменную ActualLimit, потому как входной параметр Limit доступен лишь для чтения, и мы не можем его изменять. В строке 12 странное, на первый взгляд, выражение. На самом деле это позаимствованная из языка С идиома a ? b :c (если условие a истинно, то присваивается значение b, иначе с).

В теле цикла происходит проверка: координата x меньше, либо равна текущему пределу. Если это так, то цикл прекращается. Если координата x не ниже текущего предела, то мы должны не только расширить предел, но и перевернуть значение Fac. Fac является значением с плавающей запятой, а выражение abs(Fac-1) один из способов для преобразования значения с 0 на 1, и наоборот. Последние две строки тела сокращают ширину dx на 25% и добавляют эту ширину в переменную xlimit.

О сайте

На данном сайте Вы сможете найти множество уроков и материалов по графическому
редактору Blender.

Контакты

Для связи с администрацией сайта Вы можете воспользоваться следующими контактами:

Email:
info@blender3d.com.ua

Следите за нами

Подписывайтесь на наши страницы в социальных сетях.

На сайте Blender3D собрано огромное количество уроков по программе трехмерного моделирования Blender. Обучающие материалы представлены как в формате видеоуроков, так и в текстовом виде. Здесь затронуты все аспекты, связанные с Blender, начиная от моделирования и заканчивая созданием игр с применением языка программирования Python.

Помимо уроков по Blender, Вы сможете найти готовые 3D-модели, материалы и архивы высококачественных текстур. Сайт регулярно пополняется новым контентом и следит за развитием Blender.