netlib.narod.ru | < Назад | Оглавление | Далее > |
HLSL поддерживает следующие скалярные типы:
bool — Логическое значение «истина» или «ложь». Обратите внимание, что в HLSL есть ключевые слова true и false.
int — 32-разрядное целое со знаком.
half — 16-разрядное число с плавающей точкой.
float — 32-разрядное число с плавающей точкой.
double — 64-разрядное число с плавающей точкой.
HLSL поддерживает следующие встроенные векторные типы:
vector — Четырехмерный вектор, каждая компонента которого имеет тип float.
vector<T, n> — n-мерный вектор, каждая компонента которого относится к скалярному типу T. Размерность n может быть от 1 до 4. Вот пример двухмерного вектора с компонентами типа double:
vector<double, 2> vec2;
Доступ к отдельным компонентам вектора осуществляется с использованием синтаксиса доступа к элементу массива по индексу. Например, чтобы установить значение i-ой компоненты вектора vec, следует написать:
vec[i] = 2.0f;
Кроме того, мы можем обращаться к компонентам вектора vec как к членам структуры, используя предопределенные имена компонентов x, y, z, w, r, g, b и a.
vec.x = vec.r = 1.0f; vec.y = vec.g = 2.0f; vec.z = vec.b = 3.0f; vec.w = vec.a = 4.0f;
Имена r, g, b и a ссылаются на те же самые компоненты, что и имена x, y, z и w, соответственно. Когда вектор используется для представления цвета, нотация RGBA более предпочтительна, поскольку подчеркивает тот факт, что вектор содержит цветовые значения, а не координаты.
Помимо этого, мы можем пользоваться следующими предопределенными типами для представления двухмерных, трехмерных и четырехмерных векторов соответственно:
float2 vec2; float3 vec3; float4 vec4;
Возьмем вектор u = (ux, uy, uz, uw) и предположим, что мы хотим скопировать компоненты вектора u в вектор v, чтобы получить v = (ux, uy, uy, uw). Первое, что приходит на ум, скопировать каждую компоненту u в соответствующую компоненту v. Однако, HLSL предоставляет специальный синтаксис для таких операций копирования с изменением последовательности, называемый перенос по адресам (swizzles):
vector u = {1.0f, 2.0f, 3.0f, 4.0f}; vector v = {0.0f, 0.0f, 5.0f, 6.0f}; v = u.xyyw; // v = {1.0f, 2.0f, 2.0f, 4.0f}
При копировании векторов мы не обязаны копировать все их компоненты. Например, мы можем скопировать только компоненты x и y, как показано в приведенном ниже фрагменте кода:
vector u = {1.0f, 2.0f, 3.0f, 4.0f}; vector v = {0.0f, 0.0f, 5.0f, 6.0f}; v.xy = u; // v = {1.0f, 2.0f, 5.0f, 6.0f}
HLSL предоставляет следующие встроенные матричные типы:
matrix — Матрица 4 × 4 все элементы которой имеют тип float.
matrix<T, m, n> — Матрица размера m × n, каждый элемент которой относится к скалярному типу T. Размеры матрицы m и n могут принимать значения от 1 до 4. Вот пример матрицы целых чисел, размером 2 × 2:
matrix<int, 2, 2> m2x2;
Кроме того, мы можем объявить матрицу m × n, где m и n — числа в диапазоне от 1 до 4, используя следующий синтаксис:
floatmxn matmxn;
Примеры:
float2x2 mat2x2; float3x3 mat3x3; float4x4 mat4x4; float2x4 mat2x4;
int2x2 i2x2; int2x2 i3x3; int2x2 i2x4;
Мы можем обращаться к элементам матрицы, используя синтаксис доступа к элементу массива по двум индексам. Например, для установки значения элемента (i, j) матрицы M, следует писать:
M[i][j] = value;
Кроме того, мы можем обращаться к элементам матрицы M как к членам структуры. Определены следующие имена элементов:
Если нумерация начинается с единицы:
M._11 = M._12 = M._13 = M._14 = 0.0f; M._21 = M._22 = M._23 = M._24 = 0.0f; M._31 = M._32 = M._33 = M._34 = 0.0f; M._41 = M._42 = M._43 = M._44 = 0.0f;
Если нумерация начинается с нуля:
M._m00 = M._m01 = M._m02 = M._m03 = 0.0f; M._m10 = M._m11 = M._m12 = M._m13 = 0.0f; M._m20 = M._m21 = M._m22 = M._m23 = 0.0f; M._m30 = M._m31 = M._m32 = M._m33 = 0.0f;
Иногда нам будет требоваться сослаться на отдельный вектор-строку матрицы. Это делается с использованием синтаксиса доступа к элементу массива по индексу. Например, чтобы получить i-ый вектор-строку матрицы M, следует написать:
vector ithRow = M[i]; // получить i-ый вектор-строку в M
vector u = {0.6f, 0.3f, 1.0f, 1.0f}; vector v = {1.0f, 5.0f, 0.2f, 1.0f};Или эквивалентный стиль конструктора:
vector u = vector(0.6f, 0.3f, 1.0f, 1.0f); vector v = vector(1.0f, 5.0f, 0.2f, 1.0f);Вот еще несколько примеров:
float2x2 f2x2 = float2x2(1.0f, 2.0f, 3.0f, 4.0f); int2x2 m = {1, 2, 3, 4}; int n = int(5); int a = {5}; float3 x = float3(0, 0, 0);
Мы можем объявить массив значений заданного типа используя синтаксис, аналогичный C++. Например:
float M[4][4]; half p[4]; vector v[12];
Структуры объявляются точно так же, как это делается в С++. Однако, членами структур в HLSL не могут быть функции. Вот пример объявления структуры в HLSL:
struct MyStruct { matrix T; vector n; float f; int x; bool b; }; MyStruct s; // создаем экземпляр s.f = 5.0f; // доступ к члену
Ключевое слово typedef делает в HLSL то же самое, что и в С++. Например, приведенный ниже фрагмент кода присваивает имя point типу vector<float, 3>:
typedef vector<float, 3> point;
Теперь вместо
vector<float, 3> myPoint;
мы можем писать
point myPoint;
Вот еще два примера, показывающие как можно использовать ключевое слово typedef с константными типами и массивами:
typedef const float CFLOAT; typedef float point2[2];
Приведенные ниже ключевые слова можно использовать в качестве префиксов при объявлении переменных:
static — Если глобальная переменная объявляется с префиксом static, это означает, что переменная не должна быть доступна вне шейдера. Другими словами, она будет локальной для шейдера. Если же с префиксом static объявляется локальная переменная, то она будет вести себя так же, как локальная статическая переменная в С++. Это значит, что она инициализируется один раз при первом выполнении функции, а затем ее значение сохраняется между вызовами функции. Если в объявлении переменной нет инициализации, ей автоматически присваивается значение 0.
static int x = 5;
uniform — Если переменная объявлена с префиксом uniform, это означает, что она инициализируется вне шейдера, например в коде приложения, и передается в шейдер.
extern — Если переменная объявлена с префиксом extern, это значит, что она должна быть доступна вне шейдера, например из кода приложения. Этот префикс можно указывать только для глобальных переменных. Нестатические глобальные переменные будут внешними по умолчанию.
shared — Если переменная объявлена с префиксом shared, это указывает каркасу эффектов (см. главу 19), что переменная совместно используется несколькими эффектами. Префикс shared может использоваться только для глобальных переменных.
volatile — Если переменная объявлена с префиксом volatile, это указывает каркасу эффектов (см. главу 19), что значение переменной будет часто изменяться. Префикс volatile может использоваться только для глобальных переменных.
const — Ключевое слово const в HLSL имеет тот же самый смысл, что и в C++. Значит, если переменная объявлена с префиксом const, то она является константой и ее значение не может меняться.
const float pi = 3.14f;
netlib.narod.ru | < Назад | Оглавление | Далее > |