Войти
ПрограммированиеСтатьиГрафика

OpenGL pixel and vertex shaders. (2 стр)

Автор:

Инструкции и их применение

Общий вид инструкции:

  opcode  dst, [-]s0 [, [-]s1 [,[-]s2]];   #comment

opcode — имя инструкции.
dst — регистр-приемник.
s0, s1, s2  — регистр-источник.

Пример:

  MOV  R0, R1;

Состояние регистров:

До

После

R0

R1

R0

R1

X
Y
Z
W

0.0
0.0
0.0
0.0

7.0
6.0
2.0
1.0

7.0
6.0
2.0
1.0

7.0
6.0
2.0
1.0

Перед регистром можно поставить знак "минуc" и перемешать x,y,z,w компоненты в нужном вам порядке (swizzling).

Пример:

  MOV  R0, -R2.yzzx;


[td COLSPAN=2 width=120]

До  [td COLSPAN=2 width=120]

После

X
Y
Z
W

R0

R2

R0

R2

0.0
0.0
0.0
0.0

7.0
3.0
6.0
2.0

-3.0
-6.0
-6.0
-7.0

7.0
3.0
6.0
2.0

Или можно написать так:

  MOV  R0, R1.z;

[td COLSPAN=2 width=120]

До  [td COLSPAN=2 width=120]

После

X
Y
Z
W

R0

R1

R0

R1

0.0
0.0
0.0
0.0

7.0
3.0
6.0
2.0

2.0
2.0
2.0
2.0

7.0
3.0
6.0
2.0

Можно указывать, какие из компонент регистра-приемника модифицировать:

  MOV  R0.xw, -R1;

[td COLSPAN=2 width=120]

До  [td COLSPAN=2 width=120]

После

X
Y
Z
W

R0

R1

R0

R1

0.0
0.0
0.0
0.0

7.0
3.0
6.0
2.0

-7.0
0.0
0.0
-2.0

7.0
3.0
6.0
2.0

В NV_vertex_program используются 17 различных инструкций:
ARL, MOV, MUL, ADD, MAD, RCP, RSQ, DP3, DP4, DST, MIN, MAX, SLT, SGE, EXP, LOG, LIT

Вернемся к нашей первой программе:

!!VP1.0
  DP4  o[HPOS].x, c[0], v[OPOS];
  DP4  o[HPOS].y, c[1], v[OPOS];
  DP4  o[HPOS].z, c[2], v[OPOS];
  DP4  o[HPOS].w, c[3], v[OPOS];
  MOV  o[COL0], v[COL0];"
MOV  o[TEX0], v[TEX0];
END;

Вторая строка - это четырехкомпонентное скалярное произведение векторов c[0] и v[OPOS]. Результат записывается в компоненту X регистра o[HPOS]. с[0], как я уже говорил, - константа. Что же такое v[OPOS] и o[HPOS]? v[OPOS] - это вертексный атрибут, хранящий позицию вертекса. Всего существует 16 вертексных атрибутов. На картах следующего поколения (после NV30) возможно будет больше. o[HPOS] - это регистр, в который записывается результат (в данном случае преобразованная позиция вертекса). В NV_vertex_program таких регистров 15.

Вертексные атрибуты:


Регистр  v[0]  v[1]  v[2]  v[3]  v[4]  v[5]  v[6]  v[7]  v[8]  v[9]  v[10]  v[11]  v[12]  v[13]  v[14]  v[15] 
Имя  Типичное применение
v[OPOS]  Позиция вертекса
v[WGHT]  Вес вертекса
v[NRML]  Нормаль
v[COL0]  Primary color
v[COL1]  Secondary color
v[FOGC]  Fog coordinate
-
-
v[TEX0]  Текстурные координаты 0
v[TEX1]  Текстурные координаты 1
v[TEX2]  Текстурные координаты 2
v[TEX3]  Текстурные координаты 3
v[TEX4]  Текстурные координаты 4
v[TEX5]  Текстурные координаты 5
v[TEX6]  Текстурные координаты 6
v[TEX7]  Текстурные координаты 7

Выходные регистры:


Имя  o[HPOS]  o[COL0]  o[COL1]  o[BFC0]  o[BFC1]  o[FOGC]  o[PSIZ]  o[TEX0]  o[TEX1]  o[TEX2]  o[TEX3]  o[TEX4]  o[TEX5]  o[TEX6]  o[TEX7] 
Описание  Интерпретация компонент
Homogeneous clip space position  (x,y,z,w)
Primary color  (r,g,b,a)
Secondary color  (r,g,b,a)
Back-facing primary color  (r,g,b,a)
Back-facing secondary color  (r,g,b,a)
Fog coordinate  (f,*,*,*)
Point size  (p,*,*,*)
Texture coordinate set 0  (s,t,r,q)
Texture coordinate set 1  (s,t,r,q)
Texture coordinate set 2  (s,t,r,q)
Texture coordinate set 3  (s,t,r,q)
Texture coordinate set 4  (s,t,r,q)
Texture coordinate set 5  (s,t,r,q)
Texture coordinate set 6  (s,t,r,q)
Texture coordinate set 7  (s,t,r,q)

Как я уже сказал, в нашей программе первые 4 строки - скалярные произведения DP4. Из курса математики известно, что это умножение матрицы на вектор. Т.е. выполняется следующее действие: ProjectionModelview_Matrix * vertex_position. Последние 2 строки (не считая инструкцию END) - копирование данных из регистров вертексных атрибутов в выходные регистры.

Важно знать, что из v[...] регистров и констант с[...] во время выполнения вертексной программы можно только считывать данные, а в o[...] регистры можно только записывать. Временные регистры R0-R11 предназначены для промежуточных вычислений, и в них можно как записывать какие-то значения, так и считывать.

Рассмотрим еще несколько инструкций. Описывать все 17 инструкций я не буду, о них вы сами можете подробно прочитать в спецификации.

MAD: Multiply and Add

Описание:

Сложение третьего регистра-источника с произведением первого и второго регистра-источника.

Синтаксис:

  MAD  dest, src0, src1, src2;

Пример:

  MAD  R1.xyz, R2, R3, R4;

[td COLSPAN=4 width=200]

До  [td COLSPAN=4 width=200]

После

X
Y
Z
W

R1

R2

R3

R4

R1

R2

R3

R4

0.0
0.0
0.0
0.0

7.0
3.0
6.0
2.0

2.0
2.1
5.0
7.0

1.0
3.0
2.0
1.0

[color=#ff0000]15.0
9.3
32.0[/color]
0.0

7.0
3.0
6.0
2.0

2.0
2.1
5.0
7.0

1.0
3.0
2.0
1.0


RSQ: Reciprocal Square Root

Описание:

Вычисляет 1.0 / sqrt(|x|) и помещает результат во всех 4 компонентах приемника.

Синтаксис:

  RSQ  dest, src0.C;
где 'С' - x, y, z или w.

Пример:

  RSQ  R1, R5.x;

[td COLSPAN=2 width=120]

До  [td COLSPAN=2 width=120]

После

X
Y
Z
W

R0

R1

R0

R1

0.0
0.0
0.0
0.0

-4.0
3.0
7.0
9.0

0.5
0.5
0.5
0.5

-4.0
3.0
7.0
9.0

DP3: Three-Component Dot Product

Описание:

Вычисляет трехмерное (x,y,z) скалярное произведение исходных векторов и помещает результат во всех 4-х компонентах приемника.

Синтаксис:

  DP3  dest, src0, src1;

Пример:

  DP3  R1.x, R6, R6;


[td COLSPAN=2 width=120]

До  [td COLSPAN=2 width=120]

После

X
Y
Z
W

R1

R6

R1

R6

0.0
0.0
0.0
0.0

3.0
2.0
1.0
1.0

14.0
0.0
0.0
0.0

3.0
2.0
1.0
1.0

ARL: Address Register Load

Описание:

Загружает целую часть какого-то числа в регистр адреса (address register).

96 параметров вертексной программы доступны через константы "c". Номер константы можно указывать непосредственно:

c[0], c[7], c[4]

или через регистр адреса: 
c[A0.x + offset]

Синтаксис:

  ARL  A0.x, src0.C;

где 'С' - x, y, z или w.

Пример:

  ARL  A0.x, R8.y;

  MOV  R9, c[A0.x+2];


[td COLSPAN=4 width=200]

До  [td COLSPAN=4 width=200]

После

X
Y
Z
W

A0

R8

R9

c[6]

A0

R8

R9

c[6]

0
0
0
0

2.0
5.9
4.2
7.0

0.0
0.0
0.0
0.0

17.0
22.0
3.0
3.0

4
0
0
0

2.0
5.9
4.2
7.0

0.0
0.0
0.0
0.0

17.0
22.0
3.0
3.0


Нормализация, векторное произведение.

Очень часто надо вычислить векторное произведение или выполнить нормализацию вектора. Как это просто и эффективно сделать на вертексном шейдере?

Нормализация

#
# R1 = (nx, ny, nz)
# 
# R0.xyz  = normalize(R1)
# R0.w  = 1/sqrt(nx*nx + ny*ny + nz*nz)
#
DP3  R0.w, R1, R1;
RSQ  R0.w, R0.w;
MUL  R0.xyz, R1, R0.w;

Векторное произведение

#
# Cross product |  i      j      k    |
#               | R0.x   R0.y   R0.z  |
#               | R1.x   R1.y   R1.z  |
#
MUL  R2, R0.zxyw, R1.yzxw;
MAD  R2, R0.yzxw, R1.zxyw, -R2;


Пример вертексной программы.

Теперь вы имеете небольшое представление о вертексных программах. Пора взглянуть на реальный пример шейдера. Следующей шейдер рассчитывает diffuse и specular освещение.

!!VP1.0
#
# c[0-3]  = modelview projection (composite) matrix
# c[4-7]  = modelview inverse transpose
# c[32]   = normalized eye-space light direction (infinite light)
# c[33]   = normalized constant eye-space half-angle vector (infinite viewer)
# c[35].x = pre-multiplied monochromatic diffuse light color & diffuse material
# c[35].y = pre-multiplied monochromatic ambient light color & diffuse material
# c[36]   = specular color
# c[38].x = specular power
#
# outputs homogenous position and color
#
DP4   o[HPOS].x, c[0], v[OPOS];
DP4   o[HPOS].y, c[1], v[OPOS];
DP4   o[HPOS].z, c[2], v[OPOS];
DP4   o[HPOS].w, c[3], v[OPOS];
DP3   R0.x, c[4], v[NRML];
DP3   R0.y, c[5], v[NRML]; 
DP3   R0.z, c[6], v[NRML];           # R0 = n' = transformed normal
DP3   R1.x, c[32], R0;               # R1.x = Lpos DOT n'
DP3   R1.y, c[33], R0;               # R1.y = hHat DOT n'
MOV   R1.w, c[38].x;                 # R1.w = specular power
LIT   R2, R1;                        # Compute lighting values
MAD   R3, c[35].x, R2.y, c[35].y;    # diffuse + emissive
MAD   o[COL0].xyz, c[36], R2.z, R3;  # + specular
END

Заключение

В этой части статьи я рассказал только о вертексных программах, разработанных компанией NVidia. Но не так уж давно появилось ARB расширение - ARB_vertex_program. Его поддерживает и GeForce, и Radeon. К тому же писать программы на arb_vp намного удобнее. Взгляните на кусок шейдера, написанного на arb_vp:


  DP4  oPos.x, mvp[0], pos;
  DP4  oPos.y, mvp[1], pos;
  DP4  oPos.z, mvp[2], pos;
  DP4  oPos.w, mvp[3], pos;

Думаю, всем понятно, что использовать переменные с какими-то именами намного проще, чем регистры. Как только вы немного разберетесь с NV_vp, я рекомендую переходить на arb-шное расширение. Ну а если у вас Radeon, то arb_vp - это единственный правильный выбор. Не надо связываться с родным ext_vertex_shader.

Напоследок дам несколько полезных ссылок. Это описания расширений:
http://oss.sgi.com/projects/ogl-sample/registry/NV/vertex_program.txt
http://oss.sgi.com/projects/ogl-sample/registry/NV/vertex_program1_1.txt
http://oss.sgi.com/projects/ogl-sample/registry/ARB/vertex_program.txt
http://oss.sgi.com/projects/ogl-sample/registry/EXT/vertex_shader.txt

А это неплохой PDF, содержащий короткое и понятное описание инстуркиций:
http://developer.nvidia.com/docs/IO/1314/ATT/VertexProgrammingCheatSheet.pdf

Страницы: 1 2 3 Следующая »

#OpenGL, #шейдеры

20 февраля 2002 (Обновление: 4 фев. 2011)

Комментарии [1]