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

Программирование шейдеров на HLSL. (2 стр)

Обзор HLSL

Tired of writing shaders in assembly language?
Try the high–level shader language!
SDK help (с)

Один из наиболее серьёзных компонентов в DirectX, предоставляющий программирование шейдеров, является язык высокого уровня HLSL (High Level Shading Language), разработанный Microsoft.

Зачем нужен HLSL? Область применения языка программирования графики высокого уровня весьма широка. Такой язык облегчает разработку графических эффектов и создание впечатляющих графических приложений. Кроме того, использование HLSL повышает читаемость кода шейдера и снижает время разработки тяжелого алгоритма. Приведем пример фрагментного шейдера на asm–языке:

ps_2_0
def c0, 1, 1, 0.5, 0.5
mov r0, c0
mov oC0, r0

и тоже самое на HLSL:

float4 main(): COLOR0
{
   return float4(1.0,1.0,0.5,0.5);
}

Можно сделать вывод, что HLSL очень удобен и понятен.

Описание языка HLSL

Типы данных

HLSL поддерживает разнообразные типы данных: от простых скаляров до комплексных типов — векторов и матриц.

Скалярные типы:

ТипЗначение
bool  true или false
int  32-bit signed integer
half  16-bit floating point value
float  32-bit floating point value
double  64-bit floating point value

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

Векторные типы:

vector <type, size>
— означает вектор размерностью size, и скалярным типом type.

Можно объявлять еще так:

typeN
– означает N компонентный вектор с данным типом type. Например:
float4  Vector;

или тоже самое можно объявить так:

float  Vector[4];

или

vector <float, 4> Vector;

Матрицы:

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

typeMxN
— матрица с типом type и размерностью M на N.
matrix<type, M,N>
— матрица с типом type и размерностью M на N.

Можно контролировать ориентацию:

#pragma pack_matrix (row_major);

Доступ к элементам и строкам матрицы:

mat._m00, mat._11, mat [0][0]

mat._m00_m01_m02_m03, mat [0]

Переменные:

Переменная может быть объявлена как static или extern. Любая нестатическая переменная (записывается с приставкой extern или без приставки), которая объявлена за шейдером, может быть изменена через API. Статическая переменная используется только шейдером и не управляется API. 

Например:

extern float a;
const  float b;
static float c;
float d;

Переменные a и d должны выставляться через API-функцию Set*ShaderConstant*() и их может изменять шейдер. Переменная b тоже задается через Set*ShaderConstant*(), но шейдер не может изменить ее значение. И переменная c не задается через API, но может быть изменена в шейдере.

Инициализация переменных выполняется также как и на языке C.

Например:

float2x2 mat = {1.0f, 0.0f, // ряд 1
                1.0f, 2.0f}; // ряд 2
float4 pos = {1.0f, 0.5f, 12.0f, 1.0f};
float f = 0.01f;

Структуры:

HLSL поддерживает структуры. Например:

struct VS_OUTPUT
{
  float4 Pos;
  float3 View;
};

Структуры могут быть приведены к/из скалярных величин, векторов, матриц и других структур.

Операторы

Существуют операторы для следующих операций:

ОперацииОператоры
Арифметические  -, +, *, /, %
Инкремент, декремент  ++, --
Логические  &&, ||, ?:
Унарные  !, -, +
Сравнения  <, >, <=, >=, ==, !=
Назначение  =, -=, +=, *=, /=
Привидение типов  (тип)
Комма  ,
Член структуры  .
Член массива  [индекс]

Оператор извлечения остатка деления (%) работает как с целыми числами, так и с числами с плавающей точкой.

Сравнение векторов производится покомпонентно.

Ветвление

if (expr) then statement [else statement]

Циклы

do statement while (expr);
while (expr) statement;
for (expr1;expr2;expr3) statement

Функции

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

Некоторые математические инструкции, которые можно применять в HLSL:

abs(x)абсолютная величина (per-component).
acos(x)возвращает арккосинус каждого компонента x. Каждый компонент должен быть в диапазоне [-1, 1].
asin(x)возвращает арксинус каждого компонента x. Каждый компонент должен быть в диапазоне [-pi/2, pi/2].
atan(x)возвращает арктангенс каждого компонента x. Каждый компонент должен быть в диапазоне [-pi/2, pi/2].
ceil(x)Возвращает наименьшее целое число, которое больше чем или равно x.
cos(x)Возвращает косинус x.
cosh(x)Возвращает гиперболический косинус x.
ddx(x)Возвращает частную производную x относительно screen-space x-координаты.
ddy(x)Возвращает частную производную x относительно screen-space y-координаты.
degrees(x)Конвертирование x с радианы в градусы.
distance(a, b)Возвращает расстояние между двумя точками a и b.
dot(a, b)Возвращает dot product двух векторов a и b.
floor(x)Возвращает самое большое целое число, которое является меньше чем или равным x.
fwidth(x)Возвращает abs(ddx(x))+abs(ddy(x)).
len(v)Векторная длина.
length(v)Возвращает длину вектора v.
lerp(a, b, s)Возвращает a + s (b - a).
log(x)Возвращает логарифм x.
log10(x)Возвращает десятичный логарифм x.
mul(a, b)Делает матричное умножение между a и b.
normalize(v)Возвращает нормализированный вектор v.
pow(x, y)Возвращает xy.
radians(x)Конвертирует x из градусов в радианы.
reflect(i, n)Возвращает вектор отражения.
refract(i, n, eta)Возвращает вектор преломления.
rsqrt(x)Возвращает 1 / sqrt(x).
sin(x)Возвращает синус x.
sincos(x, out s, out c)Возвращает синус и косинус x.
sinh(x)Возвращает гиперболический синус x
sqrt(x)Возвращает квадратный корень(per-component).
step(a, x)Возвращает (x = a) ? 1 : 0.
tan(x)Возвращает тангенс x
tanh(x)Возвращает гиперболический тангенс x

Использование текстур во фрагментном шейдере.

Если вы хотите использовать текстуры во фрагментном шейдере, то необходимо объявить extern переменную типа sampler. Фактически sampler определяет текстуру, с которой можно читать текущие значение цвета во фрагментном шейдере. Ниже описаны функции, которые возвращают цвет текстуры, исходя из заданных параметров:

tex1D(s, t)Чтение из одномерной текстуры. s - sampler. t - скаляр.
tex1D(s, t, ddx, ddy)Чтение из одномерной текстуры, с производными. s - sampler.
t, ddx, и ddy - скаляры.
tex1Dproj(s, t)Чтение из одномерной проективной текстуры. s - sampler. t - 4D вектор.
t делиться на t.w перед выполнением функции.
tex1Dbias(s, t)Чтение из одномерной текстуры со смещением, s - sampler, t - 4-х мерный вектор,
Мип-уровень смещается на t.w до того, как производится поиск.
tex2D(s, t)Чтение из двухмерной текстуры. s - sampler. t – 2D вектор.
tex2D(s, t, ddx, ddy)Чтение из двухмерной текстуры, с производными. s - sampler.
t – 2D текстурные координаты. ddx, ddy- 2D вектора.
tex2Dproj(s, t)Чтение из двумерной проективной текстуры. s - sampler. t - 4D вектор.
t делиться на t.w перед выполнением функции.
tex2Dbias(s, t)Чтение из двумерной текстуры со смещением, s - sampler, t - 4-х мерный вектор,
Мип-уровень смещается на t.w до того, как производится поиск.
tex3D(s, t)Чтение из трехмерной текстуры. s - sampler. t – 3D вектор.
tex3D(s, t, ddx, ddy)Чтение из трехмерной текстуры, с производными. s - sampler.
t – 2D текстурные координаты. ddx, ddy - 3D вектора.
tex3Dproj(s, t)Чтение из трехмерной проективной текстуры. s - sampler. t - 4D вектор.
t делиться на t.w перед выполнением функции.
tex3Dbias(s, t)Чтение из трехмерной текстуры со смещением, s - sampler,
t - 4-х мерный вектор, Мип-уровень смещается на t.w до того, как производится поиск.
texCUBE(s, t)Чтение из кубической текстуры. s – sampler,
t – 2D текстурные координаты.
texCUBE(s, t, ddx, ddy)Чтение из кубической текстуры. s - sampler.
t – 3D текстурные координаты. ddx, ddy - 3D вектора.
texCUBEproj(s, t)Чтение из кубической проективной текстуры. s – sampler, t - 4D вектор.
t делиться на t.w перед выполнением функции.
texCUBEbias(s, t)Чтение из кубической текстуры. s – sampler, t - 4D вектор.
Мип-уровень смещается на t.w до того, как производится поиск.

t – текстурные координаты. ddx, ddy – производные.

Есть полезное свойство констант в HLSL это связывание с регистрами констант, например:

sampler tex : register (s0);

Определяет текстуру в 0 stage. А в API это задается так:

RenderDevice->SetTexture(0,texture0);

Входные и исходящие параметры вершинного и фрагментного шейдеров.

Вершинные и фрагментные шейдера имеют два типа входящих данных: varying и uniform.

Uniform — данные, которые постоянны для многократного использования в шейдере. Объявление uniform данных в HLSL можно сделать двумя способами:

1)Объявить данные как extern переменную. Например:

float f;

float4 main () : COLOR
{
  return f;
}

2)Объявить данные через определитель uniform. Например:

float4 main (uniform float4 f) : COLOR
{
  return f;
}

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

Varying — данные, которые являются уникальными для каждого вызова шейдера. Например: позиция, нормаль и т.д. В вершинном шейдере такая семантика описывает varying данные, которые передаются из вершинного буфера, а во фрагментом шейдере — интерполированные данные, полученные из вершинного шейдера. Основные входящие семантические типы:

POSITIONnПозиция.
BLENDWEIGHTnВесовой коэффициент
BLENDINDICESnИндекс весовой матрицы
NORMALnНормаль.
PSIZEnРазмер точки.
COLORnЦвет.
TEXCOORDnТекстурные координаты.
TANGENTnТангент.
BINORMALnБинормаль.
TESSFACTORnФактор тесселяции.

Использование varying данных во фрагментном шейдере определяет состояние одного фрагмента. Основные входящие семантические типы:

COLORnЦвет.
TEXCOORDnТекстурные координаты.

n – определяет номер семантического типа. Например: TEXCOORD1, NORMAL0.

Исходящие данные шейдера определяют способ линковки с входящими данными следующего этапа графического конвейера. Например, исходящая семантика для вершинного шейдера связывает исходящие данные с интерполянтами в растеризаторе, который генерирует входящие данные для фрагментного шейдера.

Исходящие данные для вершинного шейдера:

POSITIONПозиция.
PSIZEРазмер точки.
FOGКоэффициент “туманности” для вершины.
COLORnЦвет.
TEXCOORDnТекстурные координаты.

Исходящие данные для фрагментного шейдера:

COLORnЦвет.
DEPTHЗначение глубины.

Теперь, когда мы обсудили синтаксис языка и связывание с графическим конвейером входящих/исходящих данных шейдеров, напишем простой пример на HLSL.

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

#3D, #Direct3D, #DirectX, #HLSL, #шейдеры

1 июня 2004 (Обновление: 19 июня 2024)

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