Расширение NV_texture_shader в его использование в OpenGL
Впервые появившееся на графических ускорителях GeForce 3 расширение NV_texture_shader позволяет
изменить механизм применения текстур в OpenGL. Вместо традиционной модели OpenGL вводится понятие
шагов текстурирования (texture stage), каждому такому шагу соответствует текстурный блок и
на каждом из этих шагов работает одна из 21 предопределенных программ (шейдеров, shaders),
опредеяющая выходной цвет для данного текстурного блока.
Каждая из этих программ в качестве входных данных берет интерполированные текстурные координаты
(s,t,r,q) для соответствующего текстурного блока и выдает два значения - RGBA-значение, которое
выступает как значение с данного текстурного блока (например, при работе с register combiner's) и
результат данного шага, который может быть использован на следующих шагах.
Отдельные программы могут приводить к различным побочным эффектам - отбрасыванию данного
фрагмента или изменению значения глубины для данного фрагмента в буфере глубины.
Рис 1. Реализация текстурирования с использованием расширения NV_texture_shader
Для проверки поддержки расширения NV_texture_shader следует использовать
isExtensionSupported ( "GL_NV_texture_shader" )
Данное расширение не вводит ни одной новой функции, но зато вводит много различных констант
для задания программ на разлитчных шагах и их параметров.
Используемые программы (собственно и называемые шейдерами - texture shaders) можно разбить на
четыре группы:
-
Обычные операции текстурирования
-
Специальные режимы текстурирования
-
Режимы, зависящие от результатов другого шага
-
Режимы, зависящие от результатов другого шага и использующие скалярное произведение
Для включение этих шейдеров служит команда
glEnable ( GL_TEXTURE_SHADER_NV );
Обратите внимание на то, что когда включено использование текстурных шейдеров, то включены все
четыре шага, поэтому если какие-либо шаги не нужны, то для них следует установить шейдер GL_NONE.
Также обратите внимание на то, что некоторые шейдеры возвращают в качестве выходного RGBA значения
нулевой вектор (0,0,0,0) независимо от текстуры, выбранной в данном блоке текстурирования.
Обычные операции текстурирования
1. Одномерные текстуры (Texture 1D)
Данная операция возвращает значение одномерной текстуры по параметру (s/q).
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | (s,t,r,q) | Texture 1D | (s/q) | Любая | tex(s/q) |
Установить данный режим можно командой
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_1D );
2. Двухмерные текстуры (Texture 2D)
Данная операция возвращает значение двухмерной текстуры по параметру (s/q,t/q).
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | (s,t,r,q) | Texture 2D | (s/q,t/q) | Любая | tex(s/q,t/q) |
Установить данный режим можно командой
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
2. Прямоугольные текстуры (texture rectange)
Это новый тип текстуры (NV_texture_rectangle) позволяющий размерам текстуры width и
height не являться степенью двух, а быть произвольными целыми числами.
Текстурные координаты s и t для таких текстур принимают значения в области
[0,width]x[0,height] вместо единичного квадрата.
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | (s,t,r,q) | Texture rectangle | (s/q,t/q) | Любая прямоугольная | tex(s/q,t/q) |
Установить данный режим можно командой
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_RECTANGLE_NV );
2. Кубические текстуры (Texture Cube Map)
Этот шейдер соответствует обычной кубичесмкой карте.
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | (s,t,r) | Texture cube map | (q,t,r) | Любая кубическая | cubeMap(s,t,r) |
Установить данный режим можно командой
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB );
Специальные режимы текстурирования
1. None
Данный шейдер вообще не обращается к текстуре, игнорирует переданные текстурные координаты и всегда
возвращает нулевой вектор (0,0,0,0).
Установить данный режим можно командой
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE );
2. Pass through
Данный шейдер также не обращается к текстуре и просто возвращает в качестве выходного RGBA
значения текстурыне координаты, усеченные по отрезку [0,1].
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | (s,t,r,q) | r=clamp(s) g=clamp(t) b=clamp(q) a=clamp(q) | нет | Любая | (r,g,b,a) |
Установить данный режим можно командой
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_PASS_THROUGH_NV );
3. Отсечение фрагмента (cull fragment)
Данный шейдер позволяет отбросить фрагмент в зависимости от значения его текстурных координат.
Для каждой текстурной координаты ставится свое условие прохождения. Это условие может быть либо
GL_GEQUAL (значение соответствующей координаты больше или равно нулю), либо GL_LESS (значение
соответствующей координаты отритцательно).
Если для хотя бы одной из четырех текстурных координат условие прохождения не выполняется,
то фрагмент отбрасывается. В противном случае фрагмент проходит и в качестве выходного RGBA
значения выступает нулевой вектор (0,0,0,0).
Пример.
int cullModes [4] = { GL_LESS, GL_LESS, GL_GEQUAL, GL_LESS };
glActiveTextureARB ( GL_TEXTURE0_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_CULL_FRAGMENT_NV );
glTexEnviv ( GL_TEXTURE_SHADER_NV, GL_CULL_MODES_NV, cullModes );
Режимы, зависящие от результатов другого шага
Все шейдеры из этой группы позволяют взять значение из одной текстуры и использовать его для
адресации другой текстуры.
Поэтому данный шаг всегда использует RGBA результат другого шага, причем эти шаги не обязаны
следовать друг за другом. Для простоты мы будем нумеровать шаги, начиная с нуля.
1. Dependent alpha-red texturing
Данный шейдер берет красную (R) и альфа (А) компоненты с одного из шагов текстурирования (не
обязательно предыдущего) и использует их в качестве текстурных координат для доступа к другой
двухмерной текстуре.
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | зависят от приложения | зависит от текстуры | зависит от текстуры | Любая 2D RGBA текстура | RGBA |
1 | игнорируются | нет | (a,r) | Любая 2D RGBA текстура | tex1(r,a) |
Пример.
// setup stage 0
glActiveTextureARB ( GL_TEXTURE0_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
// setup stage 1
glActiveTextureARB ( GL_TEXTURE1_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DEPENDENT_AR_TEXTURE_2D_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
2. Dependent green-blue texturing
Данный шейдер полностью аналогичен предыдущему и отличается от него только тем, что в качестве
текстурных координат для доступа к другой текстуре используются зеленая (G) и синяя (B) компоненты.
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | зависят от приложения | зависит от текстуры | зависит от текстуры | Любая 2D RGBA текстура | RGBA |
1 | игнорируются | нет | (g,b) | Любая 2D RGBA текстура | tex1(g,b) |
Пример.
// setup stage 0
glActiveTextureARB ( GL_TEXTURE0_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
// setup stage 1
glActiveTextureARB ( GL_TEXTURE1_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DEPENDENT_GB_TEXTURE_2D_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
3. Offset texture 2D
Этот шейдер позволяет использовать значения из одной текстуры для изменения текстурных координат
для доступа к другой текстуре.
При этом полученные из текстуры два значения умножаются на матрицу 2х2 из вещественных чисел и
полученные значения добавляются к обычным текстурным координатам.
Этот шейдер использует новые форматы текстур - GL_DSDT_NV (два знаковых канала, по 8 бит на канал),
GL_DSDT_MAG_NV (три 8-битовых канала, последний из них беззнаковый) и GL_DSDT_MAG_INTENSITY_NV (четыре канала,
последние два беззнаковых) канала).
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | (s0,t0,r0q0) | Texture 2D | (s0/q0,t0/q0) | 2D DSDT | (0,0,0,0) ds,dt |
1 | (s1,t1) | Texture 2D | s'1=s1+k0*ds+k2*dt t'1=t1+k1*ds+k3*dt | Любая 2D RGBA текстура | tex1(s'1,t'1) |
Пример.
// setup stage 0
glActiveTextureARB ( GL_TEXTURE0_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
// setup stage 1
float k [4] = { 0.3, 0.5, 0.7, 0.5 };
glActiveTextureARB ( GL_TEXTURE1_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
glTexEnvfv ( GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, k );
4. Offset texture 2D scale
Данный шейдер аналогичен предыдущему, но здесь RGB компоненты выходного цвета подвергаются масштабированию при
помощи коэффициента MAG, вычисляемого при помощи задаваемых пользователем значений kscale и kbias.
Обратите внимание, что альфа канал масштабированию не подвергается.
В случае, если текстура, задающая смещение, имеет формат GL_DSDT_MAG_INTENSITY, то на соответствующем текстурном
блоке возвращается яркость во всех каналах ((i,i,i,i)).
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | (s0,t0,r0q0) | Texture 2D | (s0/q0,t0/q0) | 2D DSDT_MAG | (0,0,0,0) ds,dt,mag |
1 | (s1,t1) | s'1=s1+k0*ds+k2*dt t'1=t1+k1*ds+k3*dt M=kscale*mag+kbias | tex1(s'1,t'1)tex(s'1,t'1) | Любая 2D RGBA текстура | (R*M,G*M,B*M,A) |
Пример.
// setup stage 0
glActiveTextureARB ( GL_TEXTURE0_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
// setup stage 1
float k [4] = { 0.3, 0.5, 0.7, 0.5 };
glActiveTextureARB ( GL_TEXTURE1_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_SCALE_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
glTexEnvfv ( GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, k );
glTexEnvf ( GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_SCALE_NV, 0.7 );
glTexEnvf ( GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_BIAS_NV, 0.2 );
Шейдеры, использующие скалярное произведение
Эта группа шейдеров берет результат из одной текстуры, вычисляет два или скалярных произведения значения из
текстуры и текстурных координат и использует полученный результат для доступа к другой текстуре.
1. Dot Product
Этот шейдер просто вычисляет скалярное произведение RGB значения предыдущего шага (они могут быть знаковыми или
беззнаковыми, в последнем случае они могут преобразованы в отрезок [-1,1]) (GL_SIGNED_RGB_NV или GL_SIGNED_RGBA_NV),
а также 16-битовые текстуры (GL_SIGNED_HILO_NV, GL_UNSIGNED_HILO_NV).
При использовании безнаковых RGB(A) текстур можно задать преобразование их в отрезок [-1,1] или же использовать
их как они есть.
Это осуществляется следующей командой
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV, param );
В случае, когда параметр param принимает значение GL_EXPAND_NORMAL_NV происходит преобразование
компонент в отрезок [-1,1] аналогично тому, как это делается в расширении register combiners. В случае,
когда значение параметра равно GL_UNSIGNED_IDENTITY_NV компоненты используются в скалярном произведении как
они есть, без каких-либо преобразований.
Шейдер GL_DOT_PRODUCT_NV предназначен только для использования на промежуточных шагах, при его использовании не
происходит обращения ни к одной текстуре.
Пример.
// setup stage 0
glActiveTextureARB ( GL_TEXTURE0_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
// setup stage 1
glActiveTextureARB ( GL_TEXTURE1_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
Этот шейдер обычно используется в качестве промежуточного шага для рассматриваемых далее шейдеров.
2. Dot Product Texture 2D
Данный шейдер вычисляет два скалярных произведения и использует их для обращения к текстуре. Предыдущим шагом
должно быть скалярное произведение (GL_DOT_PRODUCT_NV).
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | Зависит от приложения | Зависит от текстуры | Зависит от текстуре | Любая RGB(A) | (r0,g0,b0) |
1 | (s1,t1,r1) | ux=((r0,g0,b0),(s1,t1,r1)) | Нет | Нет | (0,0,0,0) |
2 | (s2,t2,r2) | uy=((r0,g0,b0),(s2,t2,r2)) | tex(ux,uy) | 2D RGBA | tex2D(ux,uy) |
Пример.
// setup stage 0
glActiveTextureARB ( GL_TEXTURE0_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
// setup stage 1
glActiveTextureARB ( GL_TEXTURE1_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
// setup stage 2
glActiveTextureARB ( GL_TEXTURE2_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_TEXTURE_2D_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
3. Dot Product Rectange
Полностью анаологичен предыдущему шейдеру, но на последнем шаге используется текстура типа NV_texture_rectange.
4. Dot Product Texture Cube Map
Данный шейдер аналогичен dot product texure 2D, но здесь используется два промежуточных скалярных произведения,
еще одно вычисляется на этом шаге и три полученных значения используются для доступа к кубической карте.
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | Зависит от приложения | Зависит от текстуры | Зависит от текстуре | Любая RGB(A) | (r0,g0,b0) |
1 | (s1,t1,r1) | ux=((r0,g0,b0),(s1,t1,r1)) | Нет | Нет | (0,0,0,0) |
2 | (s2,t2,r2) | uy=((r0,g0,b0),(s2,t2,r2)) | Нет | Нет | (0,0,0,0) |
3 | (s3,t3,r3) | uz=((r0,g0,b0),(s3,t3,r3)) | u=(ux,uy,uz) | Cube Map RGBA | cubeMap(ux,uy,uz) |
Часто в качестве текстурных координат на очередном шаге служат очередные компоненты базиса касательного пространства
(t,b,n) - сперва (tx,bx,nx), потом (ty,by,ny) и
наконец (tz,bz,nz).
Пример.
// setup stage 0
glActiveTextureARB ( GL_TEXTURE0_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
// setup stage 1
glActiveTextureARB ( GL_TEXTURE1_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
// setup stage 2
glActiveTextureARB ( GL_TEXTURE2_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
// setup stage 3
glActiveTextureARB ( GL_TEXTURE3_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
5. Dot Product Constant Eye Reflect Cube Map
Данный шейдер, как и предыдущий, использует три скалярных произведения для получения трехмерного вектора, но для
доступа к кубической карте использется не сам полученный вектор u, а отраженный вектор r, вычисляемый
по следующей формуле:
r=2*u*(u,e)/(u,u)-e
Здесь e - это положение наблюдателя, которое считается постоянным и задается отдельной командой.
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | Зависит от приложения | Зависит от текстуры | Зависит от текстуре | Любая RGB(A) | (r0,g0,b0) |
1 | (s1,t1,r1) | ux=((r0,g0,b0),(s1,t1,r1)) | Нет | Нет | (0,0,0,0) |
2 | (s2,t2,r2) | uy=((r0,g0,b0),(s2,t2,r2)) | Нет | Нет | (0,0,0,0) |
3 | (s3,t3,r3) | uz=((r0,g0,b0),(s3,t3,r3)) u=(ux,uy,uz) r=2u(u,e)/(u,u)-e | (rx,ry,rz) | Cube Map RGBA | cubeMap(rx,ry,rz) |
Пример.
// setup stage 0
glActiveTextureARB ( GL_TEXTURE0_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
// setup stage 1
glActiveTextureARB ( GL_TEXTURE1_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
// setup stage 2
glActiveTextureARB ( GL_TEXTURE2_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
// setup stage 3
float eye [3] = { -5, 0, 0 };
glActiveTextureARB ( GL_TEXTURE3_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
glTexEnvfv ( GL_TEXTURE_SHADER_NV, GL_CONSTANT_EYE_NV, eye );
6. Dot Product Reflect Cube Map
Этот шейдер аналогичен предыдущему, но здесь координаты наблюдателя передаются в текстурной координате q.
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | Зависит от приложения | Зависит от текстуры | Зависит от текстуре | Любая RGB(A) | (r0,g0,b0) |
1 | (s1,t1,r1,q1) | ux=((r0,g0,b0),(s1,t1,r1)) | Нет | Нет | (0,0,0,0) |
2 | (s2,t2,r2,q2) | uy=((r0,g0,b0),(s2,t2,r2)) | Нет | Нет | (0,0,0,0) |
3 | (s3,t3,r3,q3) | uz=((r0,g0,b0),(s3,t3,r3)) u=(ux,uy,uz) e=(q1,q2,q3) r=2u(u,e)/(u,u)-e | (rx,ry,rz) | Cube Map RGBA | cubeMap(rx,ry,rz) |
Пример.
// setup stage 0
glActiveTextureARB ( GL_TEXTURE0_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
// setup stage 1
glActiveTextureARB ( GL_TEXTURE1_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
// setup stage 2
glActiveTextureARB ( GL_TEXTURE2_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
// setup stage 3
glActiveTextureARB ( GL_TEXTURE3_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
7. Dot Product Diffuse Cube Map
Предыдущие расширение для получения отраженного вектора r вычисляет вектор u, который фактически
является преобразованным в касательное пространство вектором нормали (возможно не единичным).
Данный шейдер позволяет использовать этот промежуточный вектор для обращения к еще одной текстурной карте, таким
образом на последнем шаге происходит обращение к кубической карте по отраженному вектору r, а на предпоследнем
- обращение к другой кубической карте по вектору u.
Если на предыдущем шаге разместить нормирующую кубическую карту, то на выходе этого шага мы получим значение
единичного вектора нормали, преобразованное в касательное пространство.
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | Зависит от приложения | Зависит от текстуры | Зависит от текстуре | Любая RGB(A) | (r0,g0,b0) |
1 | (s1,t1,r1,q1) | ux=((r0,g0,b0),(s1,t1,r1)) | Нет | Нет | (0,0,0,0) |
2 | (s2,t2,r2,q2) | uy=((r0,g0,b0),(s2,t2,r2)) uz=((r0,g0,b0),(s3,t3,r3)) | (ux,uy,uz) | Cube Map RGBA | cubeMap(ux,uy,uz) |
3 | (s3,t3,r3,q3) | u=(ux,uy,uz) e=(q1,q2,q3) r=2u(u,e)/(u,u)-e | (rx,ry,rz) | Cube Map RGBA | cubeMap(rx,ry,rz) |
Пример.
// setup stage 0
glActiveTextureARB ( GL_TEXTURE0_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
// setup stage 1
glActiveTextureARB ( GL_TEXTURE1_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
// setup stage 2
glActiveTextureARB ( GL_TEXTURE2_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
// setup stage 3
glActiveTextureARB ( GL_TEXTURE3_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
8.Dot Product Depth Replace
Этот шейдер позволяет выводить грань, параллельную экрану, с заданной картой глубин (depth sprite).
Для получения наибольшой точности лучше всего использовать беззнаковую текстуру HILO.
По текстуре на данном шаге вычисляется два скалярных произведения, отношение которых и дает значение глубины.
Если это значение лежит в пределах [znear,zfar], то он записывается в буфер глубины.
В противном случае фрагмент отбрасывается.
Предыдущим шагом должно быть скалярное произведение.
Рис. 2 Работа шейдера dot product depth replace (рисунок взят из презентации компании NVDIA)
Шаг | Текстурные координаты | Шейдер | Обращение к текстуре | Формат текстуры | Выходное значение |
0 | (s0,t0,r0,q0) | Texture 2D | (s0/q0,t0/q0) | Беззнаковая HILO | (0,0,0,0) |
1 | (zscale,zscale/216,zbias) | Z=(zscale,zscale/216,zbias),(H,L,1)) | Нет | Нет | (0,0,0,0) |
2 | (wscale,wscale/216,wbias) | W=(wscale,wscale/216,wbias),(H,L,1)) zw=Z/W | Нет | Нет | (0,0,0,0) |
Пример.
// setup stage 0
glActiveTextureARB ( GL_TEXTURE0_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
// setup stage 1
glActiveTextureARB ( GL_TEXTURE1_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
// setup stage 2
glActiveTextureARB ( GL_TEXTURE2_ARB );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_DEPTH_REPLACE_NV );
glTexEnvi ( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );
Обратите внимание, что в ряду случаев при неправильном задании данных, шаг текстурирование может находится в
ошибочном (inconsistent) состоянии. В этом случае данный шаг работает, как если бы в нем была установлена
операция GL_NONE.
Узнать состояние шага можно при помощи следующего фрагмента кода
GLint consistent;
glActiveTextureARB ( stage_to_check );
glGetTexEnviv ( GL_TEXTURE_SHADER_NV, GL_SHADER_CONSISTENT_NV, &consistent );
При подготовке статьи использовались материалы компании NVIDIA.
Дополнительную информацию по данному расширению можно найти на
OpenGL Extension Registry, а также
на сайте компании NVIDIA.
|