ShadingTechniques

Перемещение текстурных координат


Вы можете сдвинуть рисунок текстуры, просто сдвинув текстурные координаты. Концепция этого метода очень похожа на использование функции mod для создания повторяющихся чисел. Заметим, что текстура трансформируется в сторону, противоположную направлению изменения текстурных координат. Например, если вы двигаете текстурные координаты влево, текстура будет двигаться вправо; если вы уменьшите масштаб текстурных координат, видимый размер текстуры увеличится.




Наслоение шейдеров


В Renderman вы не можете откомпилировать отдельные шейдеры и сложить эти слои вместе на поверхности, как, например, это делается в Maya. Наслоение должно быть сделано в одном шейдере, который назначен данной поверхности. При этом используется такой же механизм наслоения, как и в композинге: чтобы наложить верхний шейдер на нижний, используя maskinfo (маску), необходимо вычислить:


output = (1 – maskinfo) * bottomshader + maskinfo * topshader

где maskinfo лежит в пределах от 0 до 1.







«Бомбёжка»



Предположим, у вас есть текстура, существующая в st от 0 до 1; известна также высота текстуры h и ее ширина w.



Поделим зону текстурирования на квадратные ячейки. Вы можете легко это сделать с помощью функции mod. Например, предположим, что неделимые s и t расширены до рамок от 0 до 1. Тогда вы можете использовать ss = mod(3*s,1) и tt = mod(3*t,1) для деления их на сетку 3 на 3 ячейки.



Используем поделенную область (ss и tt заменяя на s и t) для создания текстуры.



Сдвинем центр каждой ячейки на случайное число, не превышающее (1-w)/2 по ss, и (1-h)/2 по tt.



Случайным образом удалим некоторые звезды. Это можно сделать, сдвигая их за пределы ячейки.


Ниже показан пример использования этой техники. Вы можете пропустить код функции звезды, он приведён в разделе Surface Shaders.




Проецирование текстур в третьем измерении


Например есть такая текстурная проблема: вам нужно сделать ночные дома, и точка зрения пассажира ведущего машину вдоль домов. И при этом вы должны
видеть неравномерно освещенные 3D комнаты внутри домов, таким образом вы не можете просто наложить плоскую текстуру на поверхность окон. Другими словами, вам нужно сделать так, чтобы текстура была внутри поверхности.




Как показано на рисунке, задача в том, чтобы найти позицию Ipt, и затем перевести ее в текстурные координаты. Если внимательно посмотрите на левый рисунок, то заметите что


by similar triangles, Iin / (hinterv*ceilheight-ycomp(Et)) = It / (ycomp(Pt)-ycomp(Et))

или
Iin = It * (hinterv*ceilheight-ycomp(Et)) / (ycomp(Pt)-ycomp(Et))

где hinterv = ceil( ycomp(Pt)/ceilheight )

и тогда
Ipt = Et + Iin

После того, как мы узнали Ipt, мы можем извлечь компоненты x и y для создания сетчатой текстуры. Можно также сделать эмуляцию света в окнах используя функцию cellnoise.



Передача сообщений


Иногда бывает необходимо передать какую-то информацию от одного шейдера к другому, применённому в той же точке шейдинга. Скажем, у вас есть такой шейдер дисплейсмента




и вы хотите загрязнить цвет, чтобы показать изгибы. Самый простой метод – передать из дисплейсмент шейдера переменную bmp – содержащую углубления и пики – шейдеру поверхности, который сможет её использовать для создания необходимого эффекта.





Объявляя переменную как “output varying”, вы открываете её для чтения другим шейдерам. Второй вариант обьявления переменной – “output uniform” – подходит для переменных, которые содержат одинаковые значения во всех точках поверхности. Вы можете использовать эти функции чтения параметров в шейдерах в таком порядке


displacement ··> lights ··> surface ··> atmosphere.


atmosphere( "[param]", [variable] )
displacement( "[param]", [variable] )
lightsource( "[param]", [variable] ) – присутствует только в цикле illuminance
surface( "[param]", [variable] )

В loopycolor функция displacement(«throwval»,receival) отвечает за поиск параметра throwval, исходящего от шейдера дисплейсмента, и если параметр найден, его значение присваивается переменной receival.


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




Rdir это I отраженное вокруг N;
hitpt это точка, где Rdir пересекает плоскость текстуры;
hitvec это вектор от источника света (или центра плоскости текстуры) к hitpt;
и lightright, lightup и lightnorm – вектора единичной длины, которые направлены, соответственно вдоль осей x, y и z (в координатной системе источника света).


Если у нас есть вектор V, который направлен из точки P, и плоскость, находящаяся в точке Q и «смотрящая» в направлении W, то траектория V достигнет плоскости в


P + V * ((Q – P). W) / (V. W)

В таком случае,


hitpt = P + Rdir * (L . lightnorm) / (Rdir . lightnorm)

и


hitvec = hitpt – P – L

К тому же, зная, что проекция вектора А на вектор B будет иметь длину A.B/length(B), и что lightright и lightup – вектора единичной длины, мы можем ычислить ss и tt:


ss = hitvec . lightright / hilightsize + 0.5

и


tt = hitvec . lightup / hilightsize + 0.5


где hilightsize – ширина квадратной плоскости текстуры.


Итак, у нас есть все необходимые формулы и практически все переменные – P и L стандартные глобальные переменные; hilightsize параметр шейдера; а Rdir может лекго расчитан как reflect(I,N). Единственная проблема состоит в том, чтобы получить lightright, lightup и lightnorm. Но, если подумать, эти три вектора – просто vector “shader” (1, 0, 0), vector “shader” (0, 1, 0) и vector “shader” (0, 0, 1) в шейдере света, и мы может запросто передать их шейдеру поверхности, используя механизм передачи сообщений. Таким образом,




Shading exercise – watermelon


Alexei Puzikov: с этого места начинается статья, уже переведённая и опубликованная на нашем сайте JHP – про шейдинг арбузов..