HLSL
HLSL (англ. High Level Shading Language) — C-подобный язык высокого уровня для программирования шейдеров.
Был создан корпорацией Microsoft и включён в пакет DirectX 9.0
Типы данных
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;
структуры
Операторы
| Операции | Операторы |
|---|---|
| Арифметические | -, +, *, /, % |
| Инкремент, декремент | ++, -- |
| Логические | \|, ?: |
| Унарные | !, -, + |
| Сравнения | <, >, <=, >=, ==, != |
| Назначение | =, -=, +=, *=, /= |
| Приведение типов | (тип) |
| Комма | , |
| Член структуры | . |
| Член массива | [индекс] |
Ветвления
if (выражение) then <оператор> [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 |
| 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 |
| 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) | возвращает квадратный корень каждого компонента |
| 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 — 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) | Чтение из кубической текстуры. 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 | Значение глубины |
Программы для создания шейдеров
Для облегчения написания шейдеров существует ряд программ, позволяющих составлять шейдеры и тут же просматривать результат
- RenderMonkey от ATI (ATI 3D Application Research Group)
- ShaderWorks от Mad Software Inc
- FXComposer от Nvidia
- Shader Config
Также пиксельные шейдеры используются визуализаторами, например,
Примеры
простой шейдер «Головокружение»
<source lang="cpp">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));
} </source>
шейдер, имитирующий электрический разряд
<source lang="cpp"> 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;
} </source>
пластилиновая модель
<source lang="cpp"> 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; } </source>
имитация деревянной поверхности
<source lang="cpp"> float trunk_wobble_frequency;
float4x4 view_matrix; float4x4 view_proj_matrix;
float4x4 texture_matrix0; float4x4 texture_matrix1; float4x4 texture_matrix2;
struct VS_OUTPUT { float4 Pos : POSITION; float3 TCoord0 : TEXCOORD0; float3 TCoord1 : TEXCOORD1; float3 TCoord2 : TEXCOORD2; float3 TCoord3 : TEXCOORD3; float3 TCoord4 : TEXCOORD4; float3 TCoord6 : TEXCOORD6; float3 TCoord7 : TEXCOORD7; };
VS_OUTPUT VS_Wood (float4 vPosition: POSITION, float3 vNormal: NORMAL)
{
VS_OUTPUT Out = (VS_OUTPUT) 0;
float4 TransformedPshade;
// Transform position to clip space Out.Pos = mul (view_proj_matrix, vPosition);
// Transform Pshade (using texture matrices) and output to pixel shader TransformedPshade = mul (texture_matrix0, vPosition); Out.TCoord0 = TransformedPshade; Out.TCoord1 = mul (texture_matrix1, vPosition); Out.TCoord2 = mul (texture_matrix2, vPosition);
// Create two coordinates for sampling noise volume to get wobble Out.TCoord3 = float3(trunk_wobble_frequency * TransformedPshade.z, 0.0f, 0.0f); Out.TCoord4 = float3(trunk_wobble_frequency * TransformedPshade.z + 0.5f, 0.0f, 0.0f);
// Transform position and normal to eye space Out.TCoord6 = mul (view_matrix, vPosition); Out.TCoord7 = mul (view_matrix, vNormal);
return Out; }
float4 light_pos; float4 eye_pos; float4 light_wood_color; float4 dark_wood_color;
float noise_amplitude; float trunk_wobble_amplitude; float ring_freq;
sampler noise_volume; sampler pulse_train; sampler variable_specular;
float4 PS_Wood (float3 Pshade0 : TEXCOORD0, float3 Pshade1 : TEXCOORD1, float3 Pshade2 : TEXCOORD2, float3 zWobble0 : TEXCOORD3, float3 zWobble1 : TEXCOORD4, float3 Peye : TEXCOORD6, float3 Neye : TEXCOORD7) : COLOR { float3 coloredNoise; float3 wobble;
// Construct colored noise from three samples coloredNoise.x = tex3D (noise_volume, Pshade0); coloredNoise.y = tex3D (noise_volume, Pshade1); coloredNoise.z = tex3D (noise_volume, Pshade2);
wobble.x = tex3D (noise_volume, zWobble0); wobble.y = tex3D (noise_volume, zWobble1); wobble.z = 0.5f;
// Make signed coloredNoise = coloredNoise * 2.0f - 1.0f; wobble = wobble * 2.0f - 1.0f;
// Scale noise and add to Pshade float3 noisyWobblyPshade = Pshade0 + coloredNoise * noise_amplitude + wobble * trunk_wobble_amplitude;
float scaledDistFromZAxis = sqrt(dot(noisyWobblyPshade.xy, noisyWobblyPshade.xy)) * ring_freq;
// Lookup blend factor from pulse train float4 blendFactor = tex1D (pulse_train, scaledDistFromZAxis);
// Blend wood colors together float4 albedo = lerp (dark_wood_color, light_wood_color, blendFactor.x);
// Compute normalized vector from vertex to light in eye space (Leye) float3 Leye = (light_pos - Peye) / length(light_pos - Peye);
// Normalize interpolated normal Neye = Neye / length(Neye);
// Compute Veye float3 Veye = -(Peye / length(Peye));
// Compute half-angle float3 Heye = (Leye + Veye) / length(Leye + Veye);
// Compute N.H float NdotH = clamp(dot(Neye, Heye), 0.0f, 1.0f);
// Scale and bias specular exponent from pulse train into decent range float k = blendFactor.z;
// Evaluate (N.H)^k via dependent read float specular = tex2D (variable_s </source>
Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....