Главная -
Статьи -
Проекты -
Ссылки -
Скачать -
Из гельминтов -
Юмор, приколы -
Почитать -
Обо мне -
Мысли -
Гостевая -

Расширение NV_register_combiners в OpenGL

Начиная с видеокарт серии GeForce компания NVIDIA предложила новую схему обработки данных (pipeline), кроме стандартной схемы, используемой в OpenGL.

Новая схема, основанная на так называемых register combiner'ах, поддерживает гораздо более сложную модель обработки данных и хорошо подходит для целого ряда попиксельных операция включая расчет попиксельного диффузного и бликового (specular) освещения.

В новой модели все входные данные помещаются в набор регистров, далее значения в регистрах проходят через один или несколько блоков обработки, называемых general combiner'ами, после чего они попадают в блок, называемый final combiner, который по ним регистрам определяет выходное значение цвета и альфа канала.

Общая схема работы register combiners

Рис 1. Общая схема работы register combiners

Используемые регистры представлены в следующей таблице.

Таблица 1. Регистры

НазваниеЗначениеКонстанта в OpenGL
primary colorЦвет фрагментаGL_PRIMARY_COLOR_NV
secondary colorДополнительный (вторичный) цветGL_SECONDARY_COLOR_NV
texture0,
texture1
...
Значение с соответствующего текстурного блокаGL_TEXTURE0_ARB
GL_TEXTURE1_ARB
...
spare0
spare1
Временные регистры, их начальные значения не определеныGL_SPARE0
GL_SPARE1
fogСтепень затуманиванияGL_FOG
constant color 0
constant color 1
Задаваемые пользователем дополнительные цветаGL_CONSTANT_COLOR0_NV
GL_CONSTANT_COLOR1_NV
zeroНулевой цвет (0,0,0,0)
Доступен только для чтения
GL_ZERO

Каждый из этих регистров состоит из цветовой (RGB) части и альфа-части, которые могут обрабатываться совершенно независимо.

Каждый блок General Combiner работает следующим образом - на основе входных регистров из таблицы 1 с использованием простых преобразований строятся четыре внутренних переменных - A, B, C и D.

При этом для каждой из этих переменных (отдельно для RGB- и альфа-частей) задается из какого входного регистра следует взять соответствующее значение и какому преобразованию следует подвергнуть это значение перед записью в соответствующую переменную (см рис. 2).

Схема работы general combiners для RGB части

Рис 2. Работа general combiner'а для RGB части

На основе переменных A, B, C и D вычисляется три RGBA значения, которые (после преобразований масштабирования и сдвига) отсекаются по отрезку [-1,1] и записываются в выходные регистры.

При этом соответствия между переменными, значения которых будут записываться, и выходными регистрами, в которые будет происходить запись, может задаваться отдельно как для цветовой (RGB) части, так и для альфа-части.

На следующих двух рисунках приводятся схемы, показывающие как по входным переменным A, B, C и D вычисляются три выходных значения (RGB и альфа).

Схема вычисления выходных значений для RGB части general combiner-a

Рис 3. Вычисление выходных значений для RGB части

Схема вычисления выходных значений для альфа части general combiner-a

Рис 4. Вычисление выходных значений для альфа части

Операция mux вводится следующи образом: a mux b возвращает значение a, если spare0.a > 0.5. В противном случае возвращается b.

Обратите внимание, что по умолчанию альфа-часть регистра spare0 инициализируется альфа-значением из нулевого текстурного блока texture0.

Для получения значений внутренних переменных A, B, C и D по значениям соответствующих регистров могут использоваться следующие операции (mappings):

Таблица 2. Допустимые операции

НазваниеФормулаКонстанта в OpenGL
unsigned indenitymax ( 0, x )GL_UNSIGNED_IDENTITY_NV
unsigned invert1-min(max(0,x))GL_UNSIGNED_INVERT_NV
expand normal2*max(0,x)-1GL_EXPAND_NORMAL_NV
expand negate1-2*max(0,x)GL_EXPAND_NEGATE_NV
half-bias normalmax(0,x)-0.5GL_HALF_BIAS_NORMAL_NV
half-bias negate0.5 - max ( 0,x )GL_HALF_BIAS_NEGATE_NV
signed identityxGL_SIGNED_IDENTITY_NV
signed negate-xGL_SIGNED_NEGATE_NV

Допустимые преобразования для general combiner-a

Рис 5. Допустимые преобразования для general combiner'ов

Выходные значения (перед записью в регистры) подвергаются масштабированию(scale) и сдвигу(bias).

Таблица 3. Допустимые значения для масштабирования.

Константа в OpenGLМножитель
GL_NONE1
GL_SCALE_BY_TWO_NV2
GL_SCALE_BY_FOUR_NV4
GL_SCALE_BY_ONE_HALF_NV0.5

Таблица 4. Допустимые значения для сдвига.

Константа в OpenGLВеличина сдвига
GL_NONE0
GL_BY_NEGATIVE_ONE_HALF_NV-0.5

В результате на выходе получаются три RGB значения и три альфа значения. RGB значения могут быть записаны в RGB части регистров (доступных для записи), альфа значения могут быть записаны как в альфа части регистров, так и в RGB часть (в этом случае получается цвет, все три компоненты кторого равны между собой). Записанные в регистры значения являеются входными для следующего combiner'а.

Любое из трех выходных значений может быть просто отброшено (т.е. никуда не записано).

Внутри каждого из general combiner'ов все операции выполняются в диапазоне [-1,1].

Конфигурация и обработка RGB и альфа частей происходят полностью независимо.

Обычно general combiner'ы образуют цепочку - выход одного является входом для следующего, хотя это не обязательно.

Заключительным шагом обработки является final combiner.

Схема вычисления выходных значений для final combiner-a

Рис 6. Работа final combiner

Final combiner вычисляет RGBA значение, которое и будет выходным цветом. Он вычисляет беззнаковые выходные значения по беззнаковым входным значениям. Все отритцательные значения на входе в final combiner преобразуются в 0.

Для вычисления выходного RGB значения final combiner содержит шесть внутренних переменных - A, B, C, D, E и F. Каждая из них является RGB- величиной и может быть построена на основе любого из входных регистров, причем как из RGB-части, так и из альфа-части. Значение любой из входных частей может быть инвертировано.

Допустимые преобразования для final combiner-а

Рис 7. Допустимые преобразования для final combiner

Также имеются два псевдорегистра - EF и spare0+secondary color.

Псевдорегистр EF равен произведению переменных E и F, он может быть использован в качестве исходного значения для любой из переменных A, B, C и D.

Псевдорегистр spare0+secondary color может выступать в качестве входного значения для переменных B, C и D.

Для получения RGB части выхода final combiner вычисляет значение AB+(1-A)C+D.

Значение седьмой переменной G определяет альфа-канал выходного RGBA значения. Эта переменная состоит только из альфа части и может получить свое значение из альфа-части любого из регистров за исключением двух псевдорегистров. Также значение G может быть инвертировано.

При этом величина spare0+secondary color может либо отсекаться по отрезку [0,1], либо принимать значения из отрезка [0,2].

Рассмотрим теперь как осуществляется программирование register combiner'ов.

Первым шагом является их включение:

    glEnable ( GL_REGISTER_COMBINERS_NV );

Далее слежует указать количество general comber'ов, которое будет использоваться:

    glCombinerParamteriNV ( GL_NUM_GENERAL_COMBINERS_NV, num );

Узнать максимальное количество general combiner'ов, поддерживаемое графической картой и драйвером можно узнать при помощи следующего фрагмента кода:

    int maxCombiners;

    glGetIntegerv ( GL_MAX_GENERAL_COMBINERS_NV, &maxCombiners    );

Далее, для каждого из используемых general combiner'ов следует задать входные и выходные величины.

Задание входных величин осуществляется при помощи функции:

    glCombinerInputNV ( GLenum stage, GLenum portion, GLenum var,
                        GLenum input, GLenum mapping, GLenum usage );

Параметр stage задает номер используемого combiner'а и принимает одно из следующих значений от GL_COMBINER0_NV до GL_COMBINER7_NV.

Параметр portion определяет какая часть переменной (RGB или альфа) будет задаваться и принимает одно из двух значений: GLRGB или GL_ALPHA.

Параметр var определяет используемую внутреннюю переменную и принимает одно из значений: GL_VARIABLE_A_NV, GL_VARIABLE_B_NV, GL_VARIABLE_C_NV и GL_VARIABLE_D_NV.

Параметр input определяет из какого входного регистра следует взять значение для соответствующей переменной. Допустимые значения для этого параметра приведены в таблице 1.

Параметр mapping задает отображение, применяемое к значению регистра перед записью в переменную. Допустимые значения приведены в таблице 2.

Параметр usage определяет какя часть (RGB или альфа) регистра будет записана (после преобразования) в соответствующую переменную.

Значение для RGB части переменной может буть получено или из RGB части любого из регистров или из альфа части любого из регистров.

Значение для альфа части переменной может быть получено либо из альфа части регистра, либо из синей (blue) цветовой компоненты регистра.

Задание выходных величин осуществляется при помощи функции:

    glCombinerOutputNV ( GLenum stage,    GLenum portion,
                         GLenum abOutput, GLenum cdOutput, GLenum sumOutput,
                         GLenum scale,    GLenum bias,
                         GLboolean abDotProduct, GLboolean cdDotProduct,
                         GLboolean muxSum );

Параметры stage и portion имеют тот же смысл, что и для функции glCombinerInputNV.

Параметры abOutput, cdOutput и sumOutput определяют в какой регистр пойдет каждое из трех выходных значений. Допустимыми значениями являются GL_DISCARD_NV (отбросить соответствующую величину), GL_PRIMARY_COLOR_NV, GL_SECONDARY_COLOR_NV, GL_SPARE0_NV, GL_SPARE1_NV, GL_TEXTURE0_ARB и GL_TEXTURE1_ARB.

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

Параметр bias позволяет задать значение, которое будет вычтено из переменной после операции масштабирования. Допустимые значения указаны в таблице 4.

Параметры abDotProduct и cdDotProduct определяют каким образом происходит вычисление двух выходных значений (AB и CD). Если параметр принимает значение GL_TRUE, то на соответствующем выходе будет величина, все компоненты которой равны соответствующему скалярному произведению ((A,B) или (C,D)).

В противном случае на выходе будет покомпонентное произведение входных величин.

Если хотя бы один из параметров abDotProduct или cdDotProduct не равен нулю, то параметр sumOutput должен принимать значение GL_DISCARD_NV.

Если параметр muxSum равен GL_FALSE, то на выходе ABCD мы получим AB+CD. В противном случае мы получим AB mux CD.

Заключительным шагом является настройка final combiner'а.

Она осуществляется следующей командой:

    glFinalCombinerInputNV ( GLenum var,    GLenum input,
                             GLenum mapping, GLenum usage );

Параметр var задает имя переменной, которая будет задаваться, и принимает одно из значений от GL_VARIABLE_A_NV до GL_VARIABLE_G_NV.

Параметр input может принимать как значения из таблицы 1, так и дополнительные значения, соответствующие псевдорегистрам - GL_E_TIMES_F_NV и GL_SPARE0_PLUS_SECONDARY_COLOR_NV.

Параметр mapping задает преобразование входных значений и может принимать только одно из двух значений - GL_UNSIGNED_IDENTITY_NV и GL_UNSIGNED_INVERT_NV (см. таблицу 2).

Параметр usage определяет какая из частей (RGB или альфа) входного регистра будет использоваться для задания соответствующей переменной и принимает одно из значений - GL_RGB и GL_ALPHA.

Однако, если задается переменная G, то usage должно равняться GL_ALPHA.

Если переменная принимает входное значение либо из псевдорегистра EF, либо из псевдорегистра spare0+secondary color, то usage должно принимать значение GL_RGB.

Значения псевдорегистра spare0+secondary color могут принимать значения из отрезка [0,2], либо обрезаться по отрезку [0,1].

Для установки отсечения по отрезку [0,1] используется следующая команда:

    glCombinerParameteriNV ( GL_COLOR_SUM_CLAMP_NV, GL_TRUE );

Для установки значений регистров constant color можно использовать следующий фрагмент кода.

    glCombinerParamterfvNV ( GL_CONSTANT_COLOR0_NV, c0 );
    glCombinerParamterfvNV ( GL_CONSTANT_COLOR1_NV, c1 );

По умолчанию оба регистра constant color являются нулевыми и режим отсечения по отрезку [0,1] включен.

Исходный код для примера, проверяющего поддержку register combiners и печатающего максимально доступное количество general combiner'ов можно скачать здесь.

При подготовке статьи использовались презентации компании NVIDIA, доступные на ее сайте.


Copyright © 2004 Алексей В. Боресков

Используются технологии uCoz