Наше комьюнити:   OpenGL Shader Lab  •  Half-Life FX  •  Форум  
OpenGL Shader Lab

Просмотр комментариев

Показаны комментарии 1-0 из 0

Руководство по библиотеке AFSParse 31-05-2009 16:56

Написание фрагментных шейдеров с использованием расширения ATI_fragment_shader представляет собой довольно трудоемкий процесс, требуется знать довольно большое число символических констант и следить за аппаратными лимитами. Кроме того, команды задаются путем вызовов функций расширения, в результате чего для внесения изменений в шейдер требуется перекомпиляция проекта. Для решения этих проблем была разработана статическая библиотека AFSparse.

Содержание статьи:

  1. Введение
  2. Подключение библиотеки AFSparse
  3. Структура AFS-программы
  4. Команды


  5. Выходные регистры и модификаторы
  6. Входные регистры и модификаторы
  7. Ошибки в программах и отладка


  8. Примеры шейдеров на AFS



1. Введение

Библиотека содержит основную функцию ассемблирования фрагментного шейдера из текста AFS-программы, а также несколько вспомогательных функций контроля за ошибками.
Вы можете свободно использовать библиотеку AFSparse и программы, написанные на языке AFS, в своих коммерческих и некоммерческих проектах, при условии указания имени разработчика библиотеки (Chain Studios) в информации о вашем проекте.

2. Подключение библиотеки AFSparse

Для использования AFSparse вам необходимы следующие файлы:

  • afsparse.h – содержит прототипы функций библиотеки.
  • afsparse.lib – собственно библиотека, вам нужно подключить ее к проекту.




Для успешной сборки проекта вы должны подключить к нему opengl32.lib (как правило, он уже подключен к проекту, использующему функции OpenGL), а также объявить несколько функций, соответствующих расширению ATI_fragment_shader:


C++ Source Code:
PFNGLBINDFRAGMENTSHADERATIPROC glBindFragmentShaderATI;
PFNGLBEGINFRAGMENTSHADERATIPROC glBeginFragmentShaderATI;
PFNGLENDFRAGMENTSHADERATIPROC glEndFragmentShaderATI;
PFNGLPASSTEXCOORDATIPROC glPassTexCoordATI;
PFNGLSAMPLEMAPATIPROC glSampleMapATI;
PFNGLCOLORFRAGMENTOP1ATIPROC glColorFragmentOp1ATI;
PFNGLCOLORFRAGMENTOP2ATIPROC glColorFragmentOp2ATI;
PFNGLCOLORFRAGMENTOP3ATIPROC glColorFragmentOp3ATI;
PFNGLALPHAFRAGMENTOP1ATIPROC glAlphaFragmentOp1ATI;
PFNGLALPHAFRAGMENTOP2ATIPROC glAlphaFragmentOp2ATI;
PFNGLALPHAFRAGMENTOP3ATIPROC glAlphaFragmentOp3ATI;
PFNGLSETFRAGMENTSHADERCONSTANTATIPROC glSetFragmentShaderConstantATI;


Учтите, что вы должны сами проверить поддержку расширения ATI_fragment_shader и получить указатели на эти функции до вызова функций AFSparse.
Для сборки шейдера вам нужно получить свободный идентификатор, привязать его к текущему шейдеру и вызвать функцию afsparse, в качестве аргумента которой выступает текст AFS-программы.


C++ Source Code:
void afsparse(const char * const text);


Пример:


C++ Source Code:
glBindFragmentShaderATI( uiShaderIdentifier );
afsparse( szProgramBuffer );
glBindFragmentShaderATI(0);


Далее вы можете использовать этот шейдер при рисовании:


C++ Source Code:
glBindFragmentShaderATI(uiShaderIdentifier );
glEnable(GL_FRAGMENT_SHADER_ATI);
// Код рисования
glDisable(GL_FRAGMENT_SHADER_ATI);


Сразу после сборки шейдера вы можете узнать, сколько он содержит инструкций (в обоих проходах), вызвав функцию afsparse_get_instruction_count:


C++ Source Code:
int numCmds = afsparse_get_instruction_count();


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

3. Структура AFS-программы

Рассмотрим базовую структуру AFS-программ.


Code:
!!AFS1.0
// Объявления констант
{
    // Первый проход шейдера
    
    //Текстурные инструкции
    //Общие инструкции
}
{
    // Второй проход шейдера (необязателен)
    
    //Текстурные инструкции
    //Общие инструкции
}


Каждая AFS-программа должна начинаться со строки «!!AFS1.0».
Далее могут идти объявления констант, используемых в шейдере. Для этого используется следующий синтаксис:


Code:
CONSTi value1, value2, value3, value4;


Где i варьирует от 0 до GL_NUM_FRAGMENT_CONSTANTS_ATI-1.
Разделение параметров с помощью запятой и постановка точки запятой в конце необязательно, но рекомендуется для повышения читабельности программы.
Вы можете оставлять комментарии в любой строке, кроме первой. Символы // и \\ говорят о том, что вся строка – комментарий. Вы также можете использовать комментарии в стиле С (/* … */).
Открывающая фигурная скобка «{» объявляет начало нового прохода. Всего может быть один (простой шейдер) или два прохода (сложный шейдер с доступом к текстуре по вычисленным текстурным координатам). Каждый проход должен завершаться закрывающей фигурной скобкой «}».
Инструкции прохода делятся на текстурные и общие (вычислительные). Текстурные инструкции должны предшествовать общим, т.к. они инициализируют используемые в дальнейшем регистры.
Количество доступных регистров, констант и текстурных блоков ограничено. Библиотека проверяет их максимально допустимое количество и генерирует ошибку, если в программе фигурирует неподдерживаемый параметр.

4. Команды

Команды программы напоминают ассемблерные:


Code:
cmdName dest src0 [, src1 [, src2]];


Первым операндом служит выходной регистр. Второй и последующие операнды – исходные регистры. У команд может быть 2, 3 или 4 операнда.
В вашем распоряжении 4 текстурных и 12 общих команд.
Общие команды формируют пары – первая команда в паре относится к RGB-части, а вторая – к альфа-части. Они выполняются параллельно, и результаты одной из них не могут влиять на результаты другой.
В каждом проходе можно задать не более 8 таких пар (всего не более 16 команд).
Если вам нужно использовать подряд 2 команды, работающие с RGB-частью, используйте в качестве второй команды пары команду NOP (аналогично – для двух подряд альфа-команд, тогда потребуется еще и NOP перед первой альфа-командой).

К общим командам могут применяться модификаторы (см. табл.)

4.1. Список текстурных команд AFS

 
КомандаСинтаксисДействие
TEXTEX map, coords, coords_mod;Получение данных из текстуры по указанным координатам. В качестве текстуры берется карта с индексом регистра map (например, для reg1 берется текущая текстура первого блока). Координаты в первом проходе должны быть texX, где X – номер блока. Во втором проходе допускается чтение из произвольного регистра. Coords_mod задает, какие координаты использовать для сэмплирования и принимает два значения:
STR (s,t,r)
STQ (s,t,q)
TXPTXP map, coords, coords_mod;То же, что и TEX, но осуществляется проективное преобразование координат:
STR (s/r,t/r,1/r)
STQ (s/q,t/q,1/q)
PTCPTC reg, coords, coords_mod;Сохранение в регистр текстурных координат (в первом проходе) или значения, вычисленного на первом проходе (во втором проходе). Coords_mod аналогичен значениям в команде TEX:
STR (s,t,r)
STQ (s,t,q)
PTPPTP reg, coords, coords_mod;Проективное преобразование координат. В остальном аналогичен PTC.
STR (s/r,t/r,1/r)
STQ (s/q,t/q,1/q)
 
4.2. Список общих команд AFS
 
КомандаСинтаксисДействие
NOPNOPПропуск соответствующей команде в паре
MOVMOV dst, src;R(dst) = R(src0)
G(dst) = G(src0)
B(dst) = B(src0)
A(dst) = A(src0)
ADDADD dst, src0, src1;R(dst) = R(src0) + R(src1)
G(dst) = G(src0) + G(src1)
B(dst) = B(src0) + B(src1)
A(dst) = A(src0) + A(src1)
SUBSUB dst, src0, src1;R(dst) = R(src0) - R(src1)
G(dst) = G(src0) - G(src1)
B(dst) = B(src0) - B(src1)
A(dst) = A(src0) - A(src1)
MULMUL dst, src0, src1;R(dst) = R(src0) * R(src1)
G(dst) = G(src0) * G(src1)
B(dst) = B(src0) * B(src1)
A(dst) = A(src0) * A(src1)
MADMAD dst, src0, src1, src2;R(dst) = R(src0) * R(src1) + R(src2)
G(dst) = G(src0) * G(src1) + G(src2)
B(dst) = B(src0) * B(src1) + B(src2)
A(dst) = A(src0) * A(src1) + A(src2)
DP2DP2 dst, src0, src1, src2;R(dst) = G(dst) = B(dst) = A(dst) =
R(src0) * R(src1) + G(src0) * G(src1) + B(src2)
DP3DP3 dst, src0, src1;R(dst) = G(dst) = B(dst) = A(dst) =
R(src0) * R(src1) + G(src0) * G(src1) + B(src0) * B(src1)
DP4DP4 dst, src0, src1;R(dst) = G(dst) = B(dst) = A(dst) =
R(src0) * R(src1) + G(src0) * G(src1) + B(src0) * B(src1) + A(src0) * A(src1)
Альфа-часть пары должна также содержать инструкцию DP4 и те же операнды, что и RGB-часть.
CMPCMP dst, src0, src1, src2;R(dst) = (R(src2) > 0.5) ? R(src0) : R(src1)
G(dst) = (G(src2) > 0.5) ? G(src0) : G(src1)
B(dst) = (B(src2) > 0.5) ? B(src0) : B(src1)
A(dst) = (A(src2) > 0.5) ? A(src0) : A(src1)
CMZCMZ dst, src0, src1, src2;R(dst) = (R(src2) >= 0) ? R(src0) : R(src1)
G(dst) = (G(src2) >= 0) ? G(src0) : G(src1)
B(dst) = (B(src2) >= 0) ? B(src0) : B(src1)
A(dst) = (A(src2) >= 0) ? A(src0) : A(src1)
LRPLRP dst, src0, src1, src2;R(dst) = R(src0) * R(src1) + (1 - R(src0)) * R(src2)
G(dst) = G(src0) * G(src1) + (1 - G(src0)) * G(src2)
B(dst) = B(src0) * B(src1) + (1 - B(src0)) * B(src2)
A(dst) = A(src0) * A(src1) + (1 - A(src0)) * A(src2)
Src0 должен лежать в диапазоне [0,1], иначе результаты работы команды не определены.
Для получения значений в альфа-частях регистров нужно поместить такую же команду в альфа-часть пары.

4.3. Модификаторы общих команд

Модификаторы отделяются от названия команды символом подчеркивания и могут идти в любом порядке и количестве.
МодификаторПримерДействие
SATDP3_SATРезультат скалярного произведения отсекается по отрезку [0,1]
2XADD_2XРезультат сложения умножается на 2
4XMUL_4XРезультат умножения умножается на 4
8XMAD_8XРезультат операции умножается на 8
HALFDP3_HALFРезультат скалярного произведения умножается на 0.5
QUATADD_QUATРезультат сложения умножается на 0.25
EIGHMUL_EUGHРезультат умножения умножается на 0.125
 
5. Выходные регистры и модификаторы

В качестве выходных регистров можно использовать любые доступные для записи регистры (reg0..regi, где i < GL_NUM_FRAGMENT_REGISTERS_ATI).
К выходному значению можно применить модификатор и маску записи.
Маска записи опциональна и позволяет защитить части регистра от записи. Маска состоит из комбинации букв r,g,b. Например, выходной регистр reg0.rg означает, что результат операции будет записан в красную и зеленую компоненту регистра 0.
Модификаторы выходного значения указываются в названии команды (см. Модификаторы общих команд).
Результат вычислений шейдера должен быть записан в регистр reg0.

6. Входные регистры и модификаторы

В качестве входных регистров можно использовать любые доступные для чтения регистры (reg0..regi, где i < GL_NUM_FRAGMENT_REGISTERS_ATI, константы con0..coni, где i < GL_NUM_FRAGMENT_CONSTANTS_ATI, текущий цвет col0, вторичный цвет col1, а также значения 1 и 0).
Обращение к текущему цвету можно осуществлять только во втором проходе двухпроходного шейдера.
Вы можете взять только одну компоненту регистра для вычислений, для этого укажите r, g, b, или a. Например, если аргумент равен reg0.r, то в команде будет использована только красная компонента регистра.
К аргументам можно применить дополнительные простые операции. Их синтаксис жестко задан, пробелы не разрешены:

МодификаторДействие
1-reg0reg0 = 1 - reg0
-reg0reg0 = - reg0
2*reg0reg0 = 2 * reg0
-2*reg0reg0 = -2 * reg0
reg0-0.5reg0 = reg0 – 0.5
-reg0-0.5reg0 = - reg0 – 0.5
2*reg0-0.5reg0 = 2 * reg0 – 0.5
-2*reg0-0.5reg0 = -2 * reg0 – 0.5
7. Ошибки в программах и отладка

Библиотека предоставляет несколько фукций для получения информации об ошибках.


C++ Source Code:
const char *afsparse_get_errors( void );


Возвращает строку, содержащую все ошибки, возникшие при сборке программы, или NULL, если ошибок не было. Строки разделены символом переноса строки («\n»)


C++ Source Code:
int afsparse_get_error_count( void );


Возвращает количество ошибок при сборке программы.


C++ Source Code:
void afsparse_set_error_filter( int filter );


Позволяет задать фильтр для ошибок. По умолчанию проверяется как синтаксис программы, так и статус OpenGL при компиляции каждой инструкции. Вы можете опционально отключать эти проверки, указывая маску-фильтр:

  • AFS_NONE – отключить обработку ошибок.
  • AFS_PARSER – выводить информацию об ошибках в программе
  • AFS_DRIVER – выводить информацию об ошибках OpenGL
  • AFS_PARSER | AFS_DRIVER – выводить все ошибки


У каждой ошибки указывается номер строки, где произошел сбой.

7.1. Список ошибок парсера AFS
Shader is empty – длина переданного буфера нулевая.
!!AFS1.0 expected – буфер не является AFS-программой.
Shader stage incomplete – нет закрывающей фигурной скобки.
Too many passes – более чем 2 прохода (открывающих фигурных скобок)
Unexpected symbol – неизвестный символ вне прохода
Bad register index – индекс регистра не указан или превышает лимит
Bad texture index – индекс текстуры не указан или превышает лимит
Bad constant index – индекс константы не указан или превышает лимит
Bad color index – индекс цвета должен быть 0 или 1
Unrecognized source register – неправильное/неподдерживаемое имя входного регистра
Unrecognized destination register – неправильное/неподдерживаемое имя выходного регистра
Unrecognized swizzle (must be STR or STQ) – неправильный модификатор координат
Unrecognized instruction – неизвестная команда
Unrecognized argument replication – неправильная компонента
Bad destination – ошибка обработки выходного параметра функции
Bad source – ошибка обработки входного параметра функции
Not allowed after general instructions – текстурная команда обнаружена после общей
Too many instructions in pass – более 16 инструкций в проходе
error in pass – при чтении прохода произошла ошибка

8. Примеры шейдеров на AFS
8.1. Искажение отражения в воде с помощью шумовой текстуры
В качестве текстуры нулевого блока выступает текстура отражения с настроенной проективной матрицей. На первом блоке разрешено 3D-текстурирование и привязана шумовая 3D-текстура.


Code:
!!AFS1.0
CONST0 2.0, 2.0, 0.0, 0.0;
{
    //Pass reflection coords in reg0
    PTC reg0, tex0, STR;
    
    //Get 3D noise into reg1
    TEX reg1, tex1, STR;
    
    //Offset reflection coords by noise
    MAD reg2, reg1, con0, reg0;
}
{
    //Do dependent projective texture read
    TXP reg0, reg2, STR;
    
    //RGB channel ignored
    NOP
    
    //Output primary color alpha
    MOV reg0, col0.a;
}



8.2. Имитация преломлений с помощью карты нормалей
В качестве текстуры нулевого блока выступает текстура сцены с настроенной проективной матрицей. На первом блоке разрешено 2D-текстурирование и привязана карта нормалей. Нормаль к поверхности передается как координаты текстуры второго блока.


Code:
!!AFS1.0
{
    //Pass screentexture coords
    PTC reg0, tex0, STR;
    
    //Get normal from normalmap
    TEX reg1, tex1, STQ;
    
    //Pass surface normal
    PTC reg2, tex2, STR;
    
    //Compute expand(reg1) . reg2
    DP3 reg2.rg, 2*reg1-0.5, reg2;
    NOP
    
    //reg0 = reg0 * (N.N')
    MUL reg0.rg, reg0, reg2;
    NOP
}
{
    //Do dependent projective texture read
    TXP reg0, reg0, STR;
    
    //RGB channel ignored
    NOP
    
    //Output primary color alpha
    MOV reg0, 1;
}



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

В качестве текстуры нулевого блока выступает текстура отражения с настроенной проективной матрицей. В качестве текстуры первого блока выступает текстура сцены с настроенной проективной матрицей. На втором блоке разрешено 2D-текстурирование и привязана карта нормалей. На третьем блоке разрешено 3D-текстурирование и привязана шумовая 3D-текстура. Нормаль к поверхности передается как координаты текстуры четвертого блока. И наконец, прозрачность воды передается в альфа-компоненте текущего цвета.
В основе имитации прозрачности лежат следующие сообращения. Полностью прозрачная вода – это текстура сцены. Полностью непрозрачная – текстура отражения. Следовательно, нужно интерполировать эти значения на основе альфа-компонента цвета, для этого есть соответствующая команда – LRP.
Кроме того, шейдер применяет и описанные выше искажения.


Code:
!!AFS1.0
CONST0 2.0, 2.0, 0.0, 0.0;
{
    PTC reg0, tex0, STQ;
    PTC reg1, tex1, STQ;
    TEX reg2, tex2, STQ;
    TEX reg3, tex3, STR;
    PTC reg4, tex4, STR;
    
    DP3 reg2.rg, 2*reg2-0.5, reg4;
    NOP
    
    MUL reg1.rg, reg1, reg2;
    NOP
    
    MAD reg0, reg3, con0, reg0;
}
{
    TXP reg0, reg0, STR;
    TXP reg1, reg1, STR;
    
    LRP reg0, col0.a, reg0, reg1;
    MOV reg0, 1;
}



Скачать библиотеку: Прикрепленный файл

Copyright © Chain Studios, 2006


Автор: XaeroX

Новости форума
Новые статьи
Вход в систему
Имя:
Пароль:
Помнить меня

[ вход ]
[ регистрация ]
[ забыли пароль? ]

Реклама
Текущие активные пользователи: 32
В данный момент на сайте 0 участников и 32 гостей.


Наш форум: В данный момент на форуме 128 посетителей.
Временная зона GMT. Текущее время 20:45.

На основе AcademCMS v1.3
Авторское право © 2001 - 2009, Chain Studios
Техническая площадка: HLFX.Ru