netlib.narod.ru | < Назад | Оглавление | Далее > |
Мы можем написать код нашего HLSL-шейдера непосредственно в исходном коде приложения в виде длинной строки символов. Однако более удобный и правильный подход — разделить код шейдеров и код приложения. Поэтому мы будем писать наши шейдеры в программе Notepad и сохранять их как обычные текстовые файлы ASCII. Затем для компиляции наших шейдеров мы воспользуемся функцией D3DXCompileShaderFromFile (раздел 16.2.2).
В качестве примера, рассмотрим приведенный ниже простой вершинный шейдер, написанный на HLSL и сохраненный в текстовый файл с именем Transform.txt. Полный код проекта находится в папке с именем Transform, расположенной в сопроводительных файлах к данной главе. Вершинный шейдер преобразует вершину путем применения комбинации матриц вида и проекции а также присваивает рассеиваемой составляющей цвета вершины синий цвет.
///////////////////////////////////////////////////////////////////// // // Файл: transform.txt // // Автор: Фрэнк Д. Луна (C) All Rights Reserved // // Система: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP, // MSVC++ 7.0 // // Описание: Вершинный шейдер, преобразующий вершину с помощью // комбинации матриц преобразования вида и проекции и устанавливающий // для вершины синий цвет // ///////////////////////////////////////////////////////////////////// // // Глобальные переменные // // Глобальная переменная для хранения комбинации // матриц преобразования вида и проекции. // Мы инициализируем эту переменную в приложении. matrix ViewProjMatrix; // Инициализация глобального вектора для синего цвета vector Blue = {0.0f, 0.0f, 1.0f, 1.0f}; // // Структуры // // Входная структура описывает вершины, которые будут // передаваться в шейдер. Здесь входная вершина содержит // только данные о местоположении. struct VS_INPUT { vector position : POSITION; }; // Выходная структура описывает вершину, которая // возвращается шейдером. Здесь выходная вершина // содержит данные о местоположении и цвет struct VS_OUTPUT { vector position : POSITION; vector diffuse : COLOR; }; // // Главная Точка Входа. Обратите внимание, // что функция получает в своем параметре копию // входной вершины и возвращает копию вычисленной // выходной вершины. // VS_OUTPUT Main(VS_INPUT input) { // Обнуляем данные выходной вершины VS_OUTPUT output = (VS_OUTPUT)0; // Преобразование пространства вида и проекция output.position = mul(input.position, ViewProjMatrix); // Делаем рассеиваемую составляющую цвета синей output.diffuse = Blue; // Возвращаем спроецированную и окрашенную вершину return output; }
Сначала мы объявляем две глобальные переменные:
matrix ViewProjMatrix; vector Blue = {0.0f, 0.0f, 1.0f, 1.0f};
Первая переменная, ViewProjMatrix, относится к типу matrix, который представляет матрицы 4 × 4 и является встроенным типом HLSL. Эта переменная хранит комбинацию матриц вида и проекции и, следовательно, описывает оба эти преобразования. Благодаря комбинированию преобразований мы обойдемся одной операцией умножения вектора на матрицу вместо двух. Обратите внимание, что нигде в исходном коде шейдера нет инициализации этой переменной. Это объясняется тем, что мы инициализируем данную переменную из приложения, а не в шейдере. Обмен данными между приложением и программой шейдера является одной из наиболее часто используемых операций, и ее исследованию посвящен раздел 16.2.1.
Вторая переменная, Blue, относится к встроенному типу vector, который представляет четырехмерный вектор. Мы просто инициализируем его компоненты для синего цвета, рассматривая его как цветовой вектор RGBA.
За объявлением глобальных переменных следует объявление двух специальных структур, которые мы будем называть входной (input) и выходной (output) структурами. Для вершинных шейдеров эти структуры описывают данные вершины, которые соответственно, получает и возвращает наш шейдер.
struct VS_INPUT { vector position : POSITION; }; struct VS_OUTPUT { vector position : POSITION; vector diffuse : COLOR; };
В рассматриваемом примере вершина, поступающая на вход шейдера содержит только данные о местоположении. Возвращаемая нашим шейдером вершина содержит сведения о местоположении а также данные цвета.
Синтаксическая конструкция с двоеточием применяется для указания способа использования переменной. Это похоже на поле настраиваемого формата вершин (FVF) в структуре данных вершины. Например, во входной структуре данных VS_INPUT, у нас есть член
vector position : POSITION;
Конструкция : POSITION означает, что переменная position типа vector используется для описания местоположения передаваемой шейдеру вершины. В качестве другого примера можно рассмотреть описание члена структуры VS_OUTPUT:
vector diffuse : COLOR;
Здесь : COLOR означает, что переменная diffuse типа vector применяется для описания цвета возвращаемой шейдером вершины. О доступных идентификаторах способов использования переменных, применяемых для вершинных и пиксельных шейдеров, мы поговорим в следующих двух главах.
Подобно программам на C++, у каждой программы на HLSL есть точка входа. В нашем примере вершинного шейдера мы назвали являющуюся точкой входа функцию Main, но это не обязательно. В качестве точки входа шейдера может использоваться любая функция, независимо от ее имени. Учтите, что у этой функции должны быть входные параметры, которые используются для передачи данных исходной вершины в шейдер. Кроме того, функция должна возвращать выходную структуру, применяемую для возврата вершины, обработанной нашим шейдером.
VS_OUTPUT Main(VS_INPUT input) {
float4 Main(in float2 base : TEXCOORD0, in float2 spot : TEXCOORD1, in float2 text : TEXCOORD2) : COLOR { ... }Параметры передаются в шейдер; в данном примере мы передаем шейдеру три набора координат текстуры. Шейдер возвращает единственное значение цвета, на что указывает констркукия : COLOR следующая за сигнатурой функции. Это определение эквивалентно следующему:
struct INPUT { float2 base : TEXCOORD0; float2 spot : TEXCOORD1; float2 text : TEXCOORD2; }; struct OUTPUT { float4 c : COLOR; }; OUTPUT Main(INPUT input) { ... }
Код функции, являющейся входной точкой, отвечает за вычисление данных возвращаемой вершины на основе полученных данных исходной вершины. Рассматриваемый в примере шейдер просто преобразует координаты вершины в пространство вида и пространство проекции, устанавливает для вершины синий цвет и возвращает полученную в результате вершину. Сперва мы создаем экземпляр выходной структуры VS_OUTPUT и присваиваем всем ее членам 0.
VS_OUTPUT output = (VS_OUTPUT)0; // обнуляем все члены
Затем наш шейдер выполняет преобразование координат исходной вершины, умножая ее на переменную ViewProjMatrix с помощью функции mul, которая является встроенной функцией, выполняющей операции умножения вектора на матрицу и умножения матрицы на матрицу. Преобразованный вектор местоположения вершины мы сохраняем в члене position экземпляра выходной структуры данных:
// Преобразование и проекция output.position = mul(input.position, ViewProjMatrix);
Затем мы устанавливаем член данных, задающий рассеиваемую составляющую цвета, равной вектору Blue:
// Делаем рассеиваемую составляющую цвета синей output.diffuse = Blue;
И, наконец, мы возвращаем полученную вершину:
return output; }
netlib.narod.ru | < Назад | Оглавление | Далее > |