Меню
Главная
Случайная статья
Настройки
|
HLSL (англ. High Level Shader Language) — C-подобный язык высокого уровня для программирования шейдеров.
Был создан корпорацией Microsoft и включён в пакет DirectX 9.0, выпущенный в 2002 году.
Содержание
Типы данных
HLSL поддерживает скалярные типы, векторные типы, матрицы и структуры.
Скалярные типы
Название
|
Характеристики типа
|
bool
|
булевый тип
|
int
|
32-битовое знаковое целое
|
half
|
16-битовое число с плавающей точкой
|
float
|
32-битовое число с плавающей точкой
|
double
|
64-битовое число с плавающей точкой
|
Векторные типы
Примеры:
vector <float, 4> color;
float4 newcolor;
float oldcolor[4];
newcolor = float4(oldcolor[0], oldcolor[1], oldcolor[2], oldcolor[3]);
Матрицы
Примеры:
matrix <float, 4> view_matrix;
float 4x4 view_matrix;
Структуры
Примеры:
struct vs_input
{
float4 pos:POSITION;
float3 nor:NORMAL;
float2 uv:TEXCOORD0;
};
struct ps_input
{
float4 pos:POSITION;
float3 nor:NORMAL;
float2 uv:TEXCOORD0;
float CustomVar;
texture2D CustomTexture;
//и так далее… :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 переменную. Например:
float4 value;
float4 main () : COLOR
{
return value;
}
2)Объявить данные через определитель uniform. Например:
float4 main (uniform float4 value) : COLOR
{
return value;
}
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 необходимо получить из приложения, установив константы шейдера.
Константы шейдера загружаются в регистры. */
float4x4 world_matrix; // мировая матрица
float4x4 view_matrix; // матрица вида
float4x4 proj_matrix; // матрица проекции
struct VS_OUTPUT // экземпляр этой структуры будет возвращать вершинный шейдер
{
float4 Pos: POSITION0; /* POSITION0 и TEXCOORD0 - семантики, обозначающие слоты, из которых пиксельный
шейдер будет в дальнейшем получать данные. Семантики, указанные здесь должны совпадать с семантиками во
входных данных пиксельного шейдера. Имена переменных и их порядок может различаться.*/
float2 TexCoord: TEXCOORD0;
};
VS_OUTPUT VS_Main(float4 InPos: POSITION0, float2 InTexCoord : TEXCOORD0) /* Вершинный шейдер выполняется
для каждой вершины выводимого объекта. InPos и InTexCoord получены из данных stream-mapping'a */
{
VS_OUTPUT Out;
float4x4 worldViewProj_matrix = mul(world_matrix, view_matrix);
worldViewProj_matrix = mul(worldViewProj_matrix, proj_matrix);
Out.Pos = mul(InPos, worldViewProj_matrix); // трансформируем вершину в clip-space
Out.TexCoord = InTexCoord; // текстурные координаты мы получаем извне, ничего модифицировать не нужно
return Out;
}
/* ========== ПИКСЕЛЬНЫЙ ШЕЙДЕР ========== */
sampler2D baseMap; // sampler2D - специальный слот "текстурный слот" в который можно загрузить текстуру.
float4 PS_Main(float2 texCoord: TEXCOORD0) : COLOR0 /* пиксельный шейдер всегда возвращает цвет выводимого
пикселя с семантикой COLOR0 в формате float4. Пиксельный шейдер выполняется для каждого пикселя выводимого
на экран изображения (а не для каждого текселя текстуры) */
{
return tex2D( baseMap, texCoord ); /* tex2d(sampler2D, float2) читает из текстурного сэмплера
(из текстуры) цвет её текселя с заданными текстурными координатами. Это и будет цвет выводимого пикселя. */
}
Простой шейдер «Головокружение»float4x4 view_proj_matrix: register(c0);
struct VS_OUTPUT
{
float4 Pos: POSITION;
float2 texCoord: TEXCOORD0;
};
VS_OUTPUT VS_Dizzy(float4 Pos: POSITION)
{
VS_OUTPUT Out;
Pos.xy = sign(Pos.xy);
Out.Pos = float4(Pos.xy, 0, 1);
Out.texCoord = Pos.xy;
return Out;
}
float time_0_X: register(c0);
float rings: register(c1);
float speed: register(c2);
float exponent: register(c3);
float4 PS_Dizzy(float2 texCoord: TEXCOORD0) : COLOR
{
float ang = atan2(texCoord.x, texCoord.y);
float rad = pow(dot(texCoord, texCoord), exponent);
return 0.5 * (1 + sin(ang + rings * rad + speed * time_0_X));
}
Шейдер, имитирующий электрический разрядstruct VS_OUTPUT
{
float4 Pos: POSITION;
float2 texCoord: TEXCOORD;
};
VS_OUTPUT VS_Electricity(float4 Pos: POSITION)
{
VS_OUTPUT Out;
// Clean up inaccuracies
Pos.xy = sign(Pos.xy);
Out.Pos = float4(Pos.xy, 0, 1);
Out.texCoord = Pos.xy;
return Out;
}
float4 color: register(c1);
float glowStrength: register(c2);
float height: register(c3);
float glowFallOff: register(c4);
float speed: register(c5);
float sampleDist: register(c6);
float ambientGlow: register(c7);
float ambientGlowHeightScale: register(c8);
float vertNoise: register(c9);
float time_0_X: register(c0);
sampler Noise: register(s0);
float4 PS_Electricity(float2 texCoord: TEXCOORD) : COLOR
{
float2 t = 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
float xs0 = texCoord.x - sampleDist;
float xs1 = texCoord.x;
float xs2 = texCoord.x + sampleDist;
// Noise for the three samples
float noise0 = tex3D(Noise, float3(xs0, t));
float noise1 = tex3D(Noise, float3(xs1, t));
float noise2 = tex3D(Noise, float3(xs2, t));
// The position of the flash
float mid0 = height * (noise0 * 2 - 1) * (1 - xs0 * xs0);
float mid1 = height * (noise1 * 2 - 1) * (1 - xs1 * xs1);
float mid2 = height * (noise2 * 2 - 1) * (1 - xs2 * xs2);
// Distance to flash
float dist0 = abs(texCoord.y - mid0);
float dist1 = abs(texCoord.y - mid1);
float dist2 = abs(texCoord.y - mid2);
// Glow according to distance to flash
float glow = 1.0 - pow(0.25 * (dist0 + 2 * dist1 + dist2), glowFallOff);
// Add some ambient glow to get some power in the air feeling
float ambGlow = ambientGlow * (1 - xs1 * xs1) * (1 - abs(ambientGlowHeightScale * texCoord.y));
return (glowStrength * glow * glow + ambGlow) * color;
}
Пластилиновая модельfloat4x4 view_proj_matrix: register(c0);
float4 view_position: register(c4);
struct VS_OUTPUT
{
float4 Pos: POSITION;
float3 normal: TEXCOORD0;
float3 viewVec: TEXCOORD1;
};
VS_OUTPUT VS_Plastic(float4 Pos: POSITION, float3 normal: NORMAL)
{
VS_OUTPUT Out;
Out.Pos = mul(view_proj_matrix, Pos);
Out.normal = normal;
Out.viewVec = view_position - Pos;
return Out;
}
float4 color: register(c0);
float4 PS_Plastic(float3 normal: TEXCOORD0, float3 viewVec: TEXCOORD1) : COLOR
{
float v = 0.5 * (1 + dot(normalize(viewVec), normal));
return v * color;
}
Ссылки
|
|