HLSL

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

HLSL(англ.High Level Shader Language) —C-подобный язык высокого уровня для программированияшейдеров.

Был создан корпорациейMicrosoftи включён в пакетDirectX9.0, выпущенный в 2002 году.

Типы данных

[править|править код]

HLSL поддерживает скалярные типы, векторные типы, матрицы и структуры.

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

[править|править код]
Название Характеристики типа
bool булевый тип
int 32-битовое знаковое целое
half 16-битовое число с плавающей точкой
float 32-битовое число с плавающей точкой
double 64-битовое число с плавающей точкой

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

[править|править код]

Примеры:

vector<float,4>color;
float4newcolor;
floatoldcolor[4];
newcolor=float4(oldcolor[0],oldcolor[1],oldcolor[2],oldcolor[3]);

Примеры:

matrix<float,4>view_matrix;
float4x4view_matrix;

Примеры:

structvs_input
{
float4pos:POSITION;
float3nor:NORMAL;
float2uv:TEXCOORD0;
};
structps_input
{
float4pos:POSITION;
float3nor:NORMAL;
float2uv:TEXCOORD0;
floatCustomVar;
texture2DCustomTexture;
//и так далее…:POSITION:NORMAL и т. д. это сентиматики, о них ниже.
};
Операции Операторы
Арифметические -, +, *, /, %
Инкремент, декремент ++, --
Логические \|,?:
Унарные !, -, +
Сравнения <, >, <=, >=, ==,!=
Назначение =, -=, +=, *=, /=
Приведение типов (тип)
Запятая ,
Член структуры .
Член массива [индекс]

if(выражение) <оператор> [else<оператор>]

В HLSL различают 3 вида циклов:

  • do<оператор>while(<выражение>);
  • while(<выражение>) <оператор>;
  • for(<выражение1>; <выражение2>; <выражение3>) <оператор>

математические функции

[править|править код]
abs(x) возвращает абсолютную величину каждого компонента x
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
clamp(x, a, b) Если x < a, то возвращает а, если x > b, то возвращает b, иначе возвращает x.
ddx(x) возвращает частную производную x относительно screen-space x-координаты
ddy(x) возвращает частную производную x относительно screen-space y-координаты
degrees(x) Конвертирование x с радианы в градусы
distance(a, b) возвращает расстояние между двумя точками a и b
dot(a, b) возвращает скалярное произведение двух векторов a и b
exp(x) возвращает экспоненту с основанием e, или ex
floor(x) возвращает самое большое целое число, которое является меньше чем или равным x (округление вниз)
frac(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
modf(x, out ip) возвращает на дробную и целую части x, каждая часть имеет тот же знак, что и x
mul(a, b) делает матричное умножение между a и b
normalize(v) возвращает нормированный вектор v
pow(x, y) возвращает xy
radians(x) конвертирует x из градусов в радианы
reflect(i, n) возвращает вектор отражения
refract(i, n, eta) возвращает вектор преломления.
round(x) возвращает ближайшее целое.
rsqrt(x) возвращает 1 / sqrt(x)
saturate(x) Аналогично clamp(x,0,1)
sin(x) возвращает синус x.
sincos(x, out s, out c) возвращает синус и косинус x
sinh(x) возвращает гиперболический синус x
sqrt(x) возвращает квадратный корень каждого компонента
step(a, x) возвращает 1 если x >= a, иначе возвращает 0
tan(x) возвращает тангенс x
tanh(x) возвращает гиперболический тангенс x

Функции для работы с текстурами

[править|править код]
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 — 3D текстурные координаты.
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) Чтение из кубической текстуры.
sampler, t — 4D вектор.
Мип-уровень смещается на t.w до того, как производится поиск.

Входящие и исходящие данные для вершинного и пиксельного шейдеров

[править|править код]

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

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

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

float4value;

float4main():COLOR
{
returnvalue;
}

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

float4main(uniformfloat4value):COLOR
{
returnvalue;
}

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

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

Основные входящие семантические типы:

BINORMAL Бинормаль
BLENDWEIGHT Весовой коэффициент
BLENDINDICES Индекс весовой матрицы
COLOR Цвет
NORMAL Нормаль
POSITION Позиция
PSIZE Размер точки
TANGENT Тангент
TESSFACTOR Фактортесселяции
TEXCOORD Текстурные координаты

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

COLOR Цвет
TEXCOORD Текстурные координаты

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

POSITION Позиция
PSIZE Размер точки
FOG Коэффициент «туманности» для вершины
COLOR Цвет
TEXCOORD Текстурные координаты

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

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

Программы для создания шейдеров

[править|править код]

Для облегчения написания шейдеров существует ряд программ, позволяющих составлять шейдеры и тут же просматривать результат

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

  • MilkdropотNullsoft— Этот плагин позволяет создавать шейдеры, зависящие от музыки.

Простейший шейдер «Texture mapping»

[править|править код]

Код в этом листинге работает в ATI Rendermonkey и Nvidia FX composer. Для использования в кастомном движке нужно указать SamplerState и technique.

/* ========== ВЕРШИННЫЙ ШЕЙДЕР ========== */
/* world_matrix, view_matrix, proj_matrix необходимо получить из приложения, установив константы шейдера.
Константы шейдера загружаются в регистры. */
float4x4world_matrix;// мировая матрица
float4x4view_matrix;// матрица вида
float4x4proj_matrix;// матрица проекции

structVS_OUTPUT// экземпляр этой структуры будет возвращать вершинный шейдер
{
float4Pos:POSITION0;/* POSITION0 и TEXCOORD0 - семантики, обозначающие слоты, из которых пиксельный
шейдер будет в дальнейшем получать данные. Семантики, указанные здесь должны совпадать с семантиками во
входных данных пиксельного шейдера. Имена переменных и их порядок может различаться.*/
float2TexCoord:TEXCOORD0;
};

VS_OUTPUTVS_Main(float4InPos:POSITION0,float2InTexCoord:TEXCOORD0)/* Вершинный шейдер выполняется
для каждой вершины выводимого объекта. InPos и InTexCoord получены из данных stream-mapping'a */
{
VS_OUTPUTOut;

float4x4worldViewProj_matrix=mul(world_matrix,view_matrix);
worldViewProj_matrix=mul(worldViewProj_matrix,proj_matrix);

Out.Pos=mul(InPos,worldViewProj_matrix);// трансформируем вершину в clip-space
Out.TexCoord=InTexCoord;// текстурные координаты мы получаем извне, ничего модифицировать не нужно

returnOut;
}

/* ========== ПИКСЕЛЬНЫЙ ШЕЙДЕР ========== */

sampler2DbaseMap;// sampler2D - специальный слот "текстурный слот" в который можно загрузить текстуру.

float4PS_Main(float2texCoord:TEXCOORD0):COLOR0/* пиксельный шейдер всегда возвращает цвет выводимого
пикселя с семантикой COLOR0 в формате float4. Пиксельный шейдер выполняется для каждого пикселя выводимого
на экран изображения (а не для каждого текселя текстуры) */
{
returntex2D(baseMap,texCoord);/* tex2d(sampler2D, float2) читает из текстурного сэмплера
(из текстуры) цвет её текселя с заданными текстурными координатами. Это и будет цвет выводимого пикселя. */
}

Простой шейдер «Головокружение»

[править|править код]
float4x4view_proj_matrix:register(c0);

structVS_OUTPUT
{
float4Pos:POSITION;
float2texCoord:TEXCOORD0;
};

VS_OUTPUTVS_Dizzy(float4Pos:POSITION)
{
VS_OUTPUTOut;

Pos.xy=sign(Pos.xy);

Out.Pos=float4(Pos.xy,0,1);
Out.texCoord=Pos.xy;

returnOut;
}

floattime_0_X:register(c0);
floatrings:register(c1);
floatspeed:register(c2);
floatexponent:register(c3);

float4PS_Dizzy(float2texCoord:TEXCOORD0):COLOR
{
floatang=atan2(texCoord.x,texCoord.y);
floatrad=pow(dot(texCoord,texCoord),exponent);

return0.5*(1+sin(ang+rings*rad+speed*time_0_X));
}

Шейдер, имитирующий электрический разряд

[править|править код]
structVS_OUTPUT
{
float4Pos:POSITION;
float2texCoord:TEXCOORD;
};

VS_OUTPUTVS_Electricity(float4Pos:POSITION)
{
VS_OUTPUTOut;

// Clean up inaccuracies
Pos.xy=sign(Pos.xy);

Out.Pos=float4(Pos.xy,0,1);
Out.texCoord=Pos.xy;

returnOut;
}

float4color:register(c1);
floatglowStrength:register(c2);
floatheight:register(c3);
floatglowFallOff:register(c4);
floatspeed:register(c5);
floatsampleDist:register(c6);
floatambientGlow:register(c7);
floatambientGlowHeightScale:register(c8);
floatvertNoise:register(c9);
floattime_0_X:register(c0);
samplerNoise:register(s0);

float4PS_Electricity(float2texCoord:TEXCOORD):COLOR
{
float2t=float2(speed*time_0_X*0.5871-vertNoise*abs(texCoord.y),speed*time_0_X);

// Sample at three positions for some horizontal blur
// The shader should blur fine by itself in vertical direction
floatxs0=texCoord.x-sampleDist;
floatxs1=texCoord.x;
floatxs2=texCoord.x+sampleDist;

// Noise for the three samples
floatnoise0=tex3D(Noise,float3(xs0,t));
floatnoise1=tex3D(Noise,float3(xs1,t));
floatnoise2=tex3D(Noise,float3(xs2,t));

// The position of the flash
floatmid0=height*(noise0*2-1)*(1-xs0*xs0);
floatmid1=height*(noise1*2-1)*(1-xs1*xs1);
floatmid2=height*(noise2*2-1)*(1-xs2*xs2);

// Distance to flash
floatdist0=abs(texCoord.y-mid0);
floatdist1=abs(texCoord.y-mid1);
floatdist2=abs(texCoord.y-mid2);

// Glow according to distance to flash
floatglow=1.0-pow(0.25*(dist0+2*dist1+dist2),glowFallOff);

// Add some ambient glow to get some power in the air feeling
floatambGlow=ambientGlow*(1-xs1*xs1)*(1-abs(ambientGlowHeightScale*texCoord.y));

return(glowStrength*glow*glow+ambGlow)*color;
}

Пластилиновая модель

[править|править код]
float4x4view_proj_matrix:register(c0);

float4view_position:register(c4);

structVS_OUTPUT
{
float4Pos:POSITION;
float3normal:TEXCOORD0;
float3viewVec:TEXCOORD1;
};

VS_OUTPUTVS_Plastic(float4Pos:POSITION,float3normal:NORMAL)
{
VS_OUTPUTOut;

Out.Pos=mul(view_proj_matrix,Pos);

Out.normal=normal;
Out.viewVec=view_position-Pos;

returnOut;
}

float4color:register(c0);

float4PS_Plastic(float3normal:TEXCOORD0,float3viewVec:TEXCOORD1):COLOR
{
floatv=0.5*(1+dot(normalize(viewVec),normal));

returnv*color;
}