Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DirectX.docx
Скачиваний:
2
Добавлен:
01.05.2025
Размер:
1.15 Mб
Скачать

Урок 9. Шейдеры в Direct3d11

В этом уроке вы узнаете: какая архитектура шейдеров; какую роль выполняют шейдеры в DirectX приложении; что такое язык HLSL и для чего он предназначен, ознакомитесь со базовыми принципами программирования HLSL.

Шейдеры

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

Сейчас шейдеры являются ключевым аспектом DirectX приложения. Фактически, трудно что-нибудь сделать без их использования. Вся графика игр, многочисленные спецэффекты, и тот реализм, который на сегодняшний день достигла графическая часть игр – это всё получилось благодаря использованию шейдеров. Взглянем лишь на некоторые примеры использования шейдеров:

  • Обычное применение: матрицы камеры и освещениями в вершинномшейдере, текстуры и определение текущего цвета пикселя в пиксельном шейдере

  • Композиции из нескольких текстур, использования глубоких текстур, для тонкой детализации ландшафта и моделей

  • Эффекты освещения и теней

  • Системы частиц – туман, задымление а также различные виды вспышек

На самом деле, данный список можно продолжать, кажется бесконечно. Существует слишком много примеров применения шейдеров, чтобы даже их просто перечислить. Запустите любую новую игру и существующий список применения шейдеров может быть пополнен несколькими, а то и десятками новых применений шейдеров.

Особенности компиляции и загрузки шейдера

Хотя шейдер является очень низкоуровневой структурой – он должен выполняться очень быстро, но вы можете его писать на языке, подобном C++, этот язык называется HLSL. Это потому, что шейдер на ходу компилируется в машинный код видеоускорителя. Кроме того, не нужен специальный компилятор. Язык HLSL является стандартным и его компиляция осуществляется на ходу любой 3d системой, например DirectX или OpenGL. Таким образом, вы просто указываете на исходный файл формата .fx и он автоматически загружается, компилируется и выполняется непосредственно в вашем 3d приложении.

Язык HLSL

Взглянем на пример шейдера с точки зрения программирования. Посмотрим на типичный код шейдера:

//------------------------------------------------------------------------------------

// Constant Buffer Variables

//------------------------------------------------------------------------------------

Texture2D txDiffuse : register( t0 );

SamplerState samLinear : register( s0 );

//------------------------------------------------------------------------------------

cbuffer ConstantBuffer: register( b0 )

{

    matrix World;

    matrix View;

    matrix Projection;

    float4 vMeshColor;

 

};

//------------------------------------------------------------------------------------

struct VS_INPUT

{

    float4 Pos : POSITION;

    float2 Tex : TEXCOORD0;

};

 

struct PS_INPUT

{

    float4 Pos : SV_POSITION;

    float2 Tex : TEXCOORD0;

};

//------------------------------------------------------------------------------------

// Vertex Shader

//------------------------------------------------------------------------------------

PS_INPUT VS( VS_INPUT input )

{

    PS_INPUT output = (PS_INPUT)0;

    output.Pos = mul( input.Pos, World );

    output.Pos = mul( output.Pos, View );

    output.Pos = mul( output.Pos, Projection );

    output.Tex = input.Tex;

 

    return output;

}

//------------------------------------------------------------------------------------

// Pixel Shader

//------------------------------------------------------------------------------------

float4 PS( PS_INPUT input) : SV_Target

{

    return txDiffuse.Sample( samLinear, input.Tex ) * vMeshColor;

}

Вы видите, что весь код шейдера может быть разбит на три ключевых раздела. Это: объявления глобальных переменных – констант шейдера представленных в виде константного буфера, код вершинного шейдера, и наконец,  код пиксельного шейдера. В дальнейших разделах мы поэтапно рассмотрим структуру языка HLSL.

Типы данных HLSL

В каждом языке существуют различные встроенные типы данных. В языке HLSL типы данных носят некоторый математический оттенок, то есть в нем много типов данных наподобие векторов и матриц. Итак, таблица типов данных HLSL:

Тип данных

Примечание

Buffer

Массив

Scalar

Одно компонентная скалярная величина

Vector,Matrix

Несколько компонентный вектор или матрица

Sampler, Texture

Встроенные типы данных – сэмплер, текстура

Struct, User Defined

Пользовательский тип данных

Рассмотрим эти типы данных. Тип данных Scalar определяет скалярную величину и может быть одним из следующих:

bool

int

uint

half

float

double

Тип данных Vector и Matrix обозначается добавлением количества компонент к типу данных scalar. Например, Float4 определяет четырехкомпонентный вектор. Для матрицы, например Float4x4 добавляется NxN, то есть указывается размеренность матрицы. Пример определения вектора и матрицы:

float3 fVector = { 0.2f, 0.3f, 0.4f };

double3x3 dMatrix;  

float2x2 fMatrix = { 0.0f, 0.1, // row 1

                     2.1f, 2.2f // row 2  };

Типы Sampler используется для описания типа фильтрации текстуры. Тип Texture для указания на используемую текстуру. Примеры определений для этих типов данных, тип данных Sampler и Texture:

Texture2D txDiffuse : register( t0 );

SamplerState samLinear : register( s0 );

ТипданныхTexture:

float4 Color=txDiffuse.Sample( samLinear, input.Tex ) * vMeshColor;

Операции ветвления кода в HLSL

В большинстве случаев код HLSL выполняется построчно, то есть одна строка, или инструкция потом следующая и так далее. Но в некоторых случаях, можно добавлять циклы и условные переходы. Обратите внимание, что так как HLSL должен работать быстро, то ветвления в коде HLSL должны быть скорее исключением, чем практикой.

Операция ветвления

Примечание

break

Операция прерывания цикла

continue

Продолжение цикла

discard

Специфическое ветвление для пиксельногошейдера

do

Ветвление

for

Цикл

if

Условный переход

switch

Операция выбора

while

Ветвление

Операции ветвления в HLSL имеют тот же синтаксис, что и в языке C++.

Определения функций и блоки в HLSL

Остальная структура языка может быть сведена к следующей таблице:

Элемент

Примечание

Функции

Определение функций

Операции ветвления

См. предыдущий раздел

Блоки

Блок определяется символами {}

Выражение return

Операция возвращения из блока функции

Выражения

Любое математическое выражение а также оператор присваивания.

Операторы

Пример символов операторов: +,-,*,/,=,+=,++,<<,>>,==,!=,>=,!

Встроенные функции

Intrinsic Functions

Определение функций имеет некоторые характерные черты в HLSL. Об этом далее.

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

Для вершинного и пиксельного шейдера существуют определенные типы данных, присущие им в качестве входящих данных и выходящих функций. Итак, вершинныйшейдер принимает в себя входящие данные, которые должны полностью соответствовать формату вершинного буфера. Пример формата входящих данных для вершинного шейдера:

struct VS_INPUT

{

    float3 Pos          : POSITION;         //position

    float3 Norm         : NORMAL;           //normal

    float2 Tex          : TEXCOORD0;        //texture coordinate

};

Выходящими данные вершинныйшейдер возвращает операцией return. Они должны содержать структуру, хранящую координаты а также любые другие произвольные данные.

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

struct PS_INPUT

{

    float4 Pos : SV_POSITION;

    float3 Norm : TEXCOORD0;

    float2 Tex : TEXCOORD1;

};

Пример входящего формата пиксельного шейдера эта структура PS_INPUT. Пиксельный шейдер операцией return может возвратить единственную переменную формата float4, определяющую цвет точки.

float4 color= g_txDiffuse.Sample( ...

return color;

Встроенные функции HLSL

Встроенные функции HLSL позволяют осуществлять многие операции, которые невозможно выполнить обычным кодом HLSL. Встроенные функции обозначаются IntrinsicFuncions. В число этих функций входят математические функции, операции с матрицами и векторами, операции выборки из текстур а также много другое. Вот пример некоторых из встроенных функций HLSL:

abs

sin

cos

dot

cross

fmod

log

mul

max

min

round

sqrt

tan

tex1d

tex2d

texCUBE

В этом отрывке кода из вершинного шейдера

output.Pos = mul( output.Pos, View );

output.Pos = mul( output.Pos, Projection );

output.Norm = mul( input.Norm, World );

легко найти места, в которых вызывается встроенная функция шейдера mul, соответствующая операции умножения матриц.

Заключение

В этом уроке вы познакомились непосредственно с тем, что представляет из себяшейдер. HLSL не так сложен как многие другие языки, так как программы на нем – точнее фрагменты кода для пиксельного и вершинного шейдера – получаются очень короткими.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]