Новости
Карта сайта
Авторы
Поиск
Рассылки
Статьи и информация
VB хитрости
Популярные ошибки
Книги
Конференция
Программы
Контролы
Примеры
Разное
Ссылки

Статьи

Pixel Shader

Количество просмотров: 13204 Автор: ktchv@mail.ru

Что такое Pixel Shader


Начиная с DirectX 8.0 Microsoft добавляет новую функцию - Pixel Shader. Это позволило получить новые возможности по преобразованию цвета, наложенных тектур, света, для каждой точки примитива. Pixel shaders - короткие программы, запускаемые во время прорисовки КАЖДОГО пикселя примитива(треугольника), т.е. при вызове DrawPrimitive эта программа будет выполнена столько раз, сколько точек будет в итоге нарисовано.
Эти программы состоят из инструкций(instructions) в формате ASCII текста. Все инструкции можно разделить на арифметические(по пробразованию цвета(diffuse/specular)) и текстурные(преобразование содержимого наложенных текстур). Для получения и записи цветовой информации используют регистры(registers), например, t0-цветовое содержимое текстуры из SetTexture(0, ...) в данной точке, или v0-цвет пикселя из буфера вершин, установленного с помощью SetStreamSource(0, ...). Их значения будут менятся в зависимости от того, какой пиксель примитива в данный момент прорисовывается устройством.
Текст pixel shader'ов похож на ассемблер и компилируется с помощью объекта D3DX из фаила или текстовой строки. Скомпилированный shader передаЈтся Direct3DDevice, и может быть использован во время прорисовки вызовом SetPixelShader. После этого, каждый пиксель будет рисоваться с учЈтом программы shader'а.

Создание Pixel Shader'a


Для создания PS необходимо выполнить следующие шаги:
  Проверить устройство на наличие поддержки данной технологии.
  Создать буфер вершин.
  Написать сам pixel shader.
  Скомпилировать и передать Direct3DDevice.
  Нарисовать содержимое буфера вершин.
 

1. Проверяем версию PS


Существует несколько версий pixel shader'ов (друг от друга они отличаются добавлением новых инструкций). И прежде чем начинать экспириментировать, проверьте какая версия у вас. Сделать это можно так:
Получите информацию о вашем Direct3DDevice.
Dim caps As D3DCAPS8
D3DDevice.GetDeviceCaps caps

Вставте в текст программы слкдующий код (это аналог функции из DirectX 9 для С++). Аргументы major и minor - это первая и вторая цифры версии, которую вы хотите получить(например, 1 и 1 для версии 1.1, или 1 и 4 для версии 1.4).
Function D3DPS_VERSION(ByVal major As Byte, ByVal minor As Byte) As Long
Dim B As D3DXBuffer
Set B = D3DX.CreateBuffer(4)
D3DX.BufferSetData B, 0, 1, 1, minor
D3DX.BufferSetData B, 1, 1, 1, major
D3DX.BufferSetData B, 2, 1, 1, &HFF
D3DX.BufferSetData B, 3, 1, 1, &HFF
D3DX.BufferGetData B, 0, 4, 1, D3DPS_VERSION
Set B = Nothing
End Function

И перед созданием shader'ов выполните следующее, например, для проверки наличия версии 1.1(будем работать именно с ней):
If caps.PixelShaderVersion < D3DPS_VERSION(1, 1) Then
MsgBox "Версия вашего pixel shader'a меньше необходимой"
'Выход из процедуры здесь
End If

PixelShaderVersion возвращает число, содержащее самую последнюю доступную для использования версию, и если оно меньше полученного из функции D3DPS_VERSION, то ничего не получится. :(

2. СоздаЈм буфер вершин.


В примере будем использовать 1 буфер вершин следующего типа:
Private Const D3DFVF_CUSTOMVERTEX = D3DFVF_XYZ Or D3DFVF_DIFFUSE Or D3DFVF_TEX1
Private Type CUSTOMVERTEX
x As Single
y As Single
z As Single
color As Long
tu As Single
tv As Single
End Type

Private VB as Direct3DVertexBuffer8

Зададим вершины и создадим буфер вершин:
Dim V(3) As CUSTOMVERTEX
v(0).x = -1: v(0).y = -1: v(0).z = 0: v(0).color = &HFF0000FF: v(0).tu = 0: v(0).tv = 1
v(0).x = 1: v(0).y = -1: v(0).z = 0: v(0).color = &HFFFF0000: v(0).tu = 1: v(0).tv = 1
v(0).x = 1: v(0).y = 1: v(0).z = 0: v(0).color = &HFFFFFF00: v(0).tu = 1: v(0).tv = 0
v(0).x = -1: v(0).y = 1: v(0).z = 0: v(0).color = &HFFFFFFFF: v(0).tu = 0: v(0).tv = 0

Set vb = D3DDevice.CreateVertexBuffer(D3DX.GetFVFVertexSize(D3DFVF_CUSTOMVERTEX) * 4, _ 
0, D3DFVF_CUSTOMVERTEX, D3DPOOL_MANAGED)
D3DVertexBuffer8SetData vb, 0, D3DX.GetFVFVertexSize(D3DFVF_CUSTOMVERTEX) * 4, 0, v(0) 

3. Пишем Pixel Shader.


В данном примере напишем простенький PS, который будет добавлять diffuse цвет из буфера вершин к цвету пикселя из текстуры. Создайте текстовый фаил pixelshader.txt в папке с вашей программой и поместите в него следующий текст:
ps.1.1
add r0, t0, v0

ps.1.1 - означает, что мы будем использовать Pixel Shader версии 1.1
add r0, t0, v0 - инструкция, записывающая в первый регистр(аргумент) сумму значений второго и третьего аргументов. В данном случае мы записываем в результирующий регистр r0(т.е. регистр, в котором должен содержаться результат всех наших действий) t0+v0, где t0-цвет пикселя текстуры в данной точке, v0-цвет пикселя из буфера вершины в точке. О других инструкциях, модификаторах и регистрах смотрите далее.
 

4. Компилируем Pixel Shader.


Для компиляции нам потребуется D3DX и буфер D3DXBuffer, где будет храниться скомпилированный PS, и строка pError, в которой будет содержаться информация об ошибках компиляции(если они конечно будут).
Dim Buffer As D3DXBuffer
Dim pError As String
Dim PixelShader As Long

Set Buffer = D3DX.AssembleShaderFromFile(App.Path & "\pixelshader.txt", 0, pError, Nothing)

Dim I As Long
Dim f() As Long
I = pData.GetBufferSize / 4 'колличество инструкций в ps в виде Long
ReDim f(I - 1) 
D3DX.BufferGetData pData, 0, 4, I, f(0)'переписываем буфер в массив Long 
Set pData = Nothing 'очищаем буфер 
PixelShader = D3DDevice.CreatePixelShader(f(0)) 

В случае успешного создания PS значение PixelShader будет отличаться от 0 и равно порядковому номеру этого shadera. Это значение будет использовано в процедуре прорисовки.

5. Прорисовка


Воспользуемся заранее загруженной текстурой - Tex1. Этот код идЈт в процессе прорисовки сцены.
D3DDevice.SetRenderState D3DRS_LIGHTING, False
D3DDevice.SetVertexShader D3DFVF_CUSTOMVERTEX
D3DDevice.SetStreamSource 0, vb, D3DX.GetFVFVertexSize(D3DFVF_CUSTOMVERTEX)
D3DDevice.SetTexture 0, Tex1
D3DDevice.SetPixelShader PixelShader
D3DDevice.DrawPrimitive D3DPT_TRIANGLEFAN, 0, 2

После прорисовки всего необходимого вызываем SetPixelShader(0) для того, чтобы PS не распространялся на другие примитивы, к которым он не должен быть применЈн.
Теперь запускаем и смотрим что получиться если рисовать...
...только цвет из буфера вершин
...только текстуру
...наложенную текстуру с diffuse цветом
...наш PixelShader

Не забывайте в конце программы Выполнять Direct3DDevice.DeletePixelShader(pixelshader), для каждого созданного shader'а.
 

Инструкции(Instrctions)


Арифметические инструкции, доступные в Pixel Shader версии 1.1
ps Объявляет начало инструкций(необхдим для любого shader)
ps.X.Y
х,y - версия инсткций.
add Складывает два регистра
add dst, src0, src1
????dst-результат; src0,src1-складываемые регистры
(dst = src0 + src1)
cnd Выбирает src1, если src0.a > 0.5, иначе src2
cnd dst, src0, src1, src2
????dst-результат
(dst = iif(src0.a > 0.5, src1, src2))
lrp Линейная интерполяция между src1 и src2 с пропорцией src0
lrp dst, src0, src1, src2
(dest = src0 * src1 + (1-src0) * src2)
mad Перемножает src0 и src1, и пребавляет src2
mad dst, src0, src1, src2
(dst = (src0 * src1) + src2)
mov Копирует src в dst
mov src, dst
(dst = src)
mul Перемножает src0 и src1
mul dst, src0, src1
(dst = src0 * src1)
nop Не производить никаких операций
sub Вычитает из src0 src1
sub dst, src0, src1
(dst = src0 - src1)
dp3 Считает DotProduct3 src0 и src1
dp3 dst, src0, src1
(dest.w = (src0.x * src1.x) + (src0.y * src1.y) + (src0.z * src1.z) + (src0.w * src1.w))
def Объявляет константу cn
def cn, val1, val2, val3, val4
????Val1, val2, val3, val4 - значения константы(все из них должны присутствовать), тип - single
Константа может быть использована как аргумент к инструкциям в виде цвета rgba или координаты xyzw

Текстурные инструкции


tex Записывает в регистр tn текстуру.
tex tn
texbem Применяет bump environment преобразование.
texbem dest, src
texcoord Интерпритирует координаты UVW1 как цвет RGBA
texcoord dest
texkill Отменяет прорисовку пикселя, если любой из компонентов координаты UVW равен или меньше 0.
texkill src
texreg2ar Переписывает информацию о координате текстуры(u, v) и записывает еЈ в alpha и red каналы
texreg2ar dest, src
texreg2gb Переписывает информацию о координате текстуры(u, v) и записывает еЈ в green и blue каналы
texreg2gb dest, src

Регистры(Registres)


Регистры, доступные для использования. Любой из них может быть передан как аргумент к инструкциям приведЈнным выше.
Имя Описание Max кол-во
cn Константа 8
rn Временный регистр, в r0 - должен быть записан результат пробразований 2
tn Текстура 4
vn Цвет vertex'а v0-diffuse v1-specular 2

Где n - от 0 до Max кол-ва.

Модификаторы(Modifiers)


Типы модификаторов:
  Модификаторы арифметических инструкций.
Применяются для умножения, деления или установления значения результата выполнения инструкции от 0.0 до 1.0.
_x2 или _x4 умножает результат на 2 или 4.
_d2 делит результат на 2.
_sat утонавливает результат выполнения в промежутке от 0 до 1.
Пример:
add_x2 - умножит результат сложения двух регистров на 2.
mul_sat - результат будет в промежутке от 0 до 1.
  Модификаторы регистров.
_bias - вычитает из регистра 0.5. dest = src - 0.5. Например: mov r0, t0_bias
Invert - Выполняет следующую операци dest = 1 - src. Например: mul r0, r0, 1-r1
Negate - меняет знак регистра на противоположный. dest = -src. Например: mul r0, r0, -v1
Signed Scaling - вычитает из регистра 0.5 и умножает на 2. dest = 2 * (src - 0.5). Например: dp3_sat r0, t0_bx2, v0_bx2
 
Готовый пример Вы можете скачать здесь.

Добавлено: 29 апреля 2005

Отзывы читалелей

Janus

Замечательна! Я как раз мечтал об этом.
Большое спасибо - Авторам стати и сайта.

ARTCat

Статьи очень интересные. Для многих начинающих и тех кто уже програмирует на VB просто отличная помощь!!!!!!!!!!!! Молодцы создатели сайта и авторы статей! Так держать!

Георгий

Ух ты !!! Здорово! Огромное спасибо авторам статьи и сайта !!!



Добавить отзыв

Eсли вы уже читали эту статью, не сочтите за труд, напишите пару строк о ваших впечатлениях . Они будут опубликованы здесь для других читателей.

Ваше имя:
Ваш E-mail:
Ваш комментарий:
 


К статьям

Rambler's Top100
Хостинг от Parking.ru
Специализируемся на ремонте ТНВД. ремонт ТНВД недорого и качественно.