netlib.narod.ru< Назад | Оглавление | Далее >

Вскрытие шейдера

Теперь, когда у вас появилось общее представление об интерфейсе RenderMonkey, пришло время для более глубокого исследования — давайте возьмем простой шейдер и проведем его вскрытие. Вооружившись полученными в результате знаниями вы будете готовы к созданию собственного простого шейдера, чем мы займемся в главе 4 «Начинаем: ваши первые шейдеры».

В оставшейся части главы я предполагаю, что RenderMonkey у вас уже установлен и готов к работе. Инструкцию по установке вы найдете в руководстве пользователя, находящемся в приложении B.

Первый шаг — запуск приложения RenderMonkey. В меню Start (Пуск) Windows выберите Start | Programs | ATI Technologies | ATI RenderMonkey | RenderMonkey. На рис. 3.7 показано, как найти программу RenderMonkey на вашем компьютере.


Рис. 3.7. Как запустить RenderMonkey из меню Start

Рис. 3.7. Как запустить RenderMonkey из меню Start


После того, как RenderMonkey запущен, надо открыть файл шейдера, с которым мы будем работать. Для этой главы мы выберем один из примеров шейдеров, поставляемых вместе с утилитой. Чтобы открыть рабочее пространство, выберите команду Open из меню File или щелкните по первому значку на панели инструментов. Затем вам необходимо выбрать файл шейдера bubble.rfx. Открытие файла шейдера показано на рис. 3.8.


Рис. 3.8. Как открыть пример шейдера в RenderMonkey

Рис. 3.8. Как открыть пример шейдера в RenderMonkey


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

Теперь давайте взглянем на скелет шейдера. Рабочее пространство для данного шейдера показано на рис. 3.9.


Рис. 3.9. Рабочее пространство примера шейдера

Рис. 3.9. Рабочее пространство примера шейдера


Открыв рабочее пространство можно исследовать его содержимое элемент за элементом. Первый узел, находящийся под корнем рабочего пространства называется Header и является чисто информационным узлом, содержащим произвольные общие комментарии к проекту. Следующий узел с именем view_proj_matrix — первый из тех, которые вызывают настоящий интерес. Как указано в руководстве пользователя, это переменная, которая хранит матрицу преобразования, используемую для проекции вершин объекта из трехмерного пространства на двухмерную поверхность экрана. Вам не надо инициализировать эту переменную, поскольку она заполняется RenderMonkey автоматически.

Следующий элемент рабочего пространства называется PNTT Stream Mapping. Этот узел определяет, как информация о геометрии будет передаваться в вершинный шейдер. По сути этот узел описывает как данные геометрии будут отображаться на входные регистры и переменные внутри вашего шейдера. Если дважды щелкнуть по этому узлу, будет выведено диалоговое окно, показанное на рис. 3.10.


Рис. 3.10. Окно отображения потоковых данных для рассматриваемого примера

Рис. 3.10. Окно отображения потоковых данных для рассматриваемого примера


Как видите, данный поток состоит из четырех элементов: местоположения, нормали, координат текстуры и касательной. Отображение определяет, какие данные нужны вершинному шейдеру, в каких регистрах они передаются и в какой форме должны быть представлены. Закройте диалоговое окно и взгляните на следующий узел. Это группа эффектов, содержащая эффект с именем ASM Bubble Shader. Каждая группа эффектов по сути представляет различные индивидуальные шейдеры, определенные в вашем рабочем пространстве. Поскольку в одном рабочем пространстве RenderMonkey можно определить несколько шейдеров, это удобный способ для организации ваших эффектов.

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

После букета переменных идут два узла с именами basemap и cubemap. Это текстуры, используемые пиксельным шейдером при визуализации эффекта. Первая используется для окрашивания пузыря, а вторая представляет собой карту окружения для реализации отражений. Если дважды щелкнуть по любому узлу текстуры, на экран будет выведено диалоговое окно выбора файла, в котором вы можете выбрать любой файл .DDS (или другой стандартный формат файлов изобоажений), который будет использоваться в качестве текстуры.

Пора взглянуть на следующий узел с именем Torus. Он определяет используемую шейдером геометрию. На данный момент RenderMonkey поддерживает только файлы форматов .3DS и .X. Для редактирования файлов .3DS необходима программа 3DStudio MAX, а файлы .X — это разработанный Microsoft формат, который также может редактироваться с помощью 3DSMax. Не надо беспокоиться, вместе с RenderMonkey поставляется большое количество примеров моделей, которые вы можете использовать. Если дважды щелкнуть по узлу геометрии, на экран будет выведено диалоговое окно, которое позволит вам выбрать файл модели, находящийся на вашем компьютере.

Следующие два узла — это проходы визуализации с именами Front Faces и Back Faces — ядро эффекта! Шейдер может состоять из нескольких проходов, каждый из которых визуализирует свою версию геометрии. Это простой способ разделить сложный шейдер на несколько меньших частей. Чтобы сэкономить место и не повторяться, здесь мы рассмотрим только проход Front Faces. Откройте проход визуализации, и вы увидите семь новых узлов.

Первый узел в проходе визуализации это просто ссылка на узел геометрии, указывающая на загруженную в рабочее пространство модель. Второй узел — это состояния визуализации; если дважды щелкнуть по нему, то будет открыто новое диалоговое окно со списком состояний визуализации и значений, которые должны быть для них установлены (рис. 3.11). Например, вы видите, что состоянию ALPHABLENDENABLE присваивается значение TRUE, что говорит аппаратуре о необходимости смешивать полученный в результате прохода пиксель с тем пикселем, который уже находится во вторичном буфере.


Рис. 3.11. Окно состояний визуализации для рассматриваемого примера

Рис. 3.11. Окно состояний визуализации для рассматриваемого примера


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

vs.1.1

dcl_position v0
dcl_normal   v1
dcl_texcoord v2
dcl_tangent  v3

// c0   - { 0.0, 0.5, 1.0, 2.0}
// c1   - { 4.0, .5pi, pi, 2pi}
// c2   - {1, -1/3!, 1/5!, -1/7!}    для синуса
// c3   - {1/2!, -1/4!, 1/6!, -1/8!} для косинуса
// c4-7 - составная матрица мир-вид-проекция
// c8   - местоположение камеры в пространстве модели
// c10  - {1.02, 0.04, 0, 0} фиксированные коэффициенты для
//                           погрешностей рядов Тейлора 
// c11  - {0.5, 0.5, 0.25, 0.25}
//         waveHeight0, waveHeight1, waveHeight2, waveHeight3
// c12  - {0.0, 0.0, 0.0, 0.0}
//         waveOffset0, waveOffset1, waveOffset2, waveOffset3
// c13  - {0.6, 0.7, 1.2, 1.4}
//         waveSpeed0, waveSpeed1, waveSpeed2, waveSpeed3
// c14  - {0.0, 2.0, 0.0, 4.0}
//         waveDirX0, waveDirX1, waveDirX2, waveDirX3
// c15  - {2.0, 0.0, 4.0, 0.0}
//         waveDirY0, waveDirY1, waveDirY2, waveDirY3
// c16  - { время }
// c17  - {-0.00015, 1.0, 0.0, 0.0} искажение координат базовой текстуры
//                                  x0, y0, x1, y1
// c18  - мировая матрица

mul  r0, c14, v2.x      // используем координаты текстуры в качествеuse
mad  r0, c15, v2.y, r0  // входных данных для синусоидальной деформации

mov  r1, c16.x          // время...
mad  r0, r1, c13, r0    // прибавляем масштабированное время для
                       // перемещения изгибов в соответствии с частотой 
add  r0, r0, c12
frc  r0.xy, r0          // получаем frac от всех 4 компонент
frc  r1.xy, r0.zwzw
mov  r0.zw, r1.xyxy

mul  r0, r0, c10.x      // умножаем на фиксированный коэффициент
sub  r0, r0, c0.y       // вычитаем .5
mul  r0, r0, c1.w       // умножаем координаты текстур на 2pi,
                        // диапазон коордитат: от -pi до pi

mul  r5, r0, r0         // (wave vec)^2
mul  r1, r5, r0         // (wave vec)^3
mul  r6, r1, r0         // (wave vec)^4
mul  r2, r6, r0         // (wave vec)^5
mul  r7, r2, r0         // (wave vec)^6
mul  r3, r7, r0         // (wave vec)^7
mul  r8, r3, r0         // (wave vec)^8

mad  r4, r1, c2.y, r0   // (wave vec) - ((wave vec)^3)/3!
mad  r4, r2, c2.z, r4   // + ((wave vec)^5)/5!
mad  r4, r3, c2.w, r4   // - ((wave vec)^7)/7!

mov  r0, c0.z           // 1
mad  r5, r5, c3.x ,r0   // -(wave vec)^2/2!
mad  r5, r6, c3.y, r5   // +(wave vec)^4/4!
mad  r5, r7, c3.z, r5   // -(wave vec)^6/6!
mad  r5, r8, c3.w, r5   // +(wave vec)^8/8!

dp4  r0, r4, c11        // умножаем высоту волны на волну

mul  r0, r0, v1         // Выполняем деформацию в направлении нормали

add  r0.xyz, r0, v0     // прибавляем к местоположению
mov  r0.w, c0.z         // однородную компоненту

m4x4 oPos, r0, c4       // OutPos = WorldSpacePos * Composite View-Proj Matrix
mov  oT0, v2            // Проход вдоль координат текстуры

; С этого места код шейдера отличается от шейдера Ocean.

; Сперва вычисляем бинормаль
mov  r3, v1
mul  r4, v3.yzxw, r3.zxyw
mad  r4, v3.zxyw, -r3.yzxw, r4  // векторное произведение для получения бинормали

;Затем нормаль искажается на основании базовых векторов касательного пространства
;(тангенс и бинормаль).
mul  r1, r5, c11       // cos * waveheight
dp4  r9.x, -r1, c14    // величина искажения нормали в направлении бинормали
dp4  r9.y, -r1, c15    // величина искажения нормали в направлении тангенса
mul  r1, r4, r9.x      // искажение нормали в направлении бинормали
mad  r1, v3, r9.y, r1  // искажение нормали в направлении тангенса
mad  r5, r1, c10.y, v1 // перемещение искаженной нормали nx, ny

;Теперь нормали ренормализуются
mov  r10, r5
m3x3 r5, r10, c18      // преобразование нормали
dp3  r10.x, r5, r5
rsq  r10.y, r10.x
mul  r5, r5, r10.y     // нормализация искаженной нормали

; Затем вычисляем вектор вида
mov  r10, r0
m4x4 r0, r10, c18     // преобразование позиции вершины
sub  r2, c8, r0       // вектор вида
dp3  r10.x, r2, r2
rsq  r10.y, r10.x
mul  r2, r2, r10.y    // нормализованный вектор вида

; Вычисляем векторное произведение вектора вида и искаженной нормали
dp3  r7, r5, r2      // N.V
mov  oT2, r7         // Проход вдоль N.V

; Результат используется для вычисления вектора отражения
add  r6, r7, r7      // 2N.V
mad  r6, r6, r5, -r2 // 2N(N.V)-V
mov  oT1, r6         // вектор отражения

А вот код пиксельного шейдера для нашего примера:

// c0 - (0.0, 0.5, 1.0, -0.75)
// c1 - (0.6, 0.1, 0.0, 0.0)   Альфа Масштаб и смещение
ps.1.4

texld  r0, t0
texld  r1, t1
texcrd r2.rgb, t2

cmp         r2.r, r2.r, r2.r, -r2.r // abs(V.N)
+mad_x4_sat r1.a, r1.a, r1.a, c0.a  // 4 * (a^2 - .75), ограниченное

mul_x2_sat r2.rgb, r0, r1     // base * env (позднее коэффициент масштабирования
                              //             может меняться)
+mad r2.a, 1-r2.r, c1.x, c1.y // alphascale * abs(V.N) + alphabias

lrp r0.rgb, r1.a, r1, r2      // Lerp между Env и Base*Env
+add r0.a, r2.a, r1.a         // Add glow map to Fresnel term for alpha

Следом за кодом шейдеров идут два узла текстур с именами basemap и cubemap. Они привязывают ранее установленные текстуры к аппаратным блокам выборки текстур, что делает эти текстуры доступными для использования внутри шейдера. Если дважды щелкнуть по узлу, на экран будет выведено диалоговое окно, изображенное на рис. 3.12.


Рис. 3.12. Окно текстуры для рассматриваемого примера

Рис. 3.12. Окно текстуры для рассматриваемого примера


В данном окне отображается уменьшенное изображение каждой используемой в проходе текстуры и набор режимов выборки, сообщающий аппаратуре, как именно должна осуществляться выборка данных конкретной текстуры. Режимы задают такие вещи, как способ повторения текстуры, обработка уровней детализации и т.д. Многие состояния в диалоговом окне относятся к фиксированному конвейеру и могут игнорироваться.

Последний рассматриваемый узел — это ссылка на отображение данных потока с именем PNTT Stream Mapping. Он позволяет указать ссылку на ранее определенную в рабочем пространстве схему отображения данных потока, которая сообщает RenderMonkey, как данные геометрии должны передаваться в вершинный шейдер в данном проходе. Если вы хотите отредактировать схему отображения данных потока, необходимо вносить изменения в узел оригинала, поскольку ссылку изменять нельзя.


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz