Создание игр » DirectX 9, Featured » Vertex shaders
Vertex shaders
Vertex shader (вершинный шейдер) занимается обработкой данных вершин модели. Такие данные как координаты вершины в пространстве, текстурные координаты, тангент-вектор, бинормаль, нормаль обрабатываются как раз вершинными шейдерами. Кроме того, vertex shader занимается преобразованием модели из пространства модели в пространство мира/вида/проекции. Он может сам генерировать текстурные координаты или менять форму самой модели, например, “пустить” волны по ровной поверхности воды или как-то изогнуть модель, провести трансформации в соответствии со скелетной анимацией, может почитать освещённость вершин модели и много чего ещё…
Давайте более подробно разберём тему вертексных шейдеров (vertex shaders) и научимся их применять.
Vertex shader, как и прочие виды шейдеров, представляет из себя ни что иное, как функцию, которая получает какие-то параметры на входе и отдаёт результат на выходе. В предыдущем уроке мы уже использовали достаточно простой vertex shader:
struct VS_OUTPUT // тут будет результат работы шейдера { float4 Pos : POSITION; // позиция вертекса float4 Color: COLOR0; // цвет вертекса }; // сама функция шейдера. кстати, она может иметь любое имя. void main(float3 Pos : POSITION/* позиция вертекса в мире*/, float4 Color: COLOR0 /* цвет вертекса*/, out VS_OUTPUT Out /* а это результат, т.к. ключевое слово out */) { // просто передём исходные параметры в пиксельный шейдер Out.Pos = float4(Pos, 1); // не изменяем координаты Out.Color = Color; // и не изменяем цвет } |
В этом примере видно, как получаются данные от vertex’а в шейдер. Но не понятно, как получать данные НЕ из vertex’а. Например, какие-то матрицы, или, скажем, цвет освещения. Не будем же мы запихивать такие данные в каждый вертекс, тем более, что эти данные общие для всех вертексов? Конечно же, не будем. Для этого существует возможность передавать данные непосредственно в шейдер их программы. Но эти данные будет нельзя изменить в шейдере, их можно только читать, но нельзя в них записывать. Потому они называются константы. И эти константы хранятся в константном буфере каждого шейдера. Кстати, этот константный буфер мы тоже уже получили в примере предыдущего урока:
D3DXCompileShader(srcVS.c_str(), srcVS.length(), NULL, NULL, "main", "vs_2_0", D3DXSHADER_OPTIMIZATION_LEVEL3, &pShaderBuff, &pErrors, &pConstTableVS/* А вот и таблица констант шейдера*/); |
Все функции для работы с таблицей констант описаны в DirectX SDK, потому я не буду дублировать информацию – если Вам интересно, просто найдите в указателе “ID3DXConstantTable” и почитайте. Я же просто покажу пример того, как работать с этой таблицей.
Давайте для начала немного усложним наш вертексный шейдер:
// vertex transformations world float4x4 mWorld; // vertex transformation view/projection float4x4 mViewProjection; struct VS_OUTPUT { float4 Pos : POSITION; float4 Color: COLOR0; }; VS_OUTPUT main(float3 Pos : POSITION0, float4 Color: COLOR0) { VS_OUTPUT Out; // tranform vertex float4 pos = mul(float4(Pos, 1), mWorld); Out.Pos = mul(pos, mViewProjection); Out.Color = Color; return Out; } |
И после этого можно задавать константы шейдера mViewProjection и mWorld из нашего кода на плюсах:
// передаём матрицу мира в вертексный шейдер pConstTableVS->SetMatrix(m_pd3dDevice, "mWorld", &mat); // передаём матрицу вида/проекции в вертексный шейдер pConstTableVS->SetMatrix(m_pd3dDevice, "mViewProjection", &matViewProj); |
В следующем уроке мы чуть более подробно рассмотрим пиксельные шейдеры и после этого займёмся более интересными вещами )
А вот и проект с исходным кодом к статье.
И небольшой видео-пример того, как vertex shader может помочь в анимации растительности:
Немного позже, в следующих уроках, я покажу и расскажу, как добиться такого эффекта.
Раздел: DirectX 9, Featured · Теги: Shader, Vertex shader
И опять спасибо!