Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DirectX. Продвинутая Анимация (2004) [rus].pdf
Скачиваний:
335
Добавлен:
16.08.2013
Размер:
8.39 Mб
Скачать

282

Глав

Комбинирование разностей

На данный момент мы посчитали разности значений координат вершин и нормалей. Следующим шагом является масштабирование каждой из этих разностей на величину комбинирования, используемую для каждого меша. Например, если вы хотите, чтобы первая анимация (открытия рта) использовала только 50 процентов разности (означая, что рот откроется только на половину), вы умножаете значения на 0.5.

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

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

float Blendl =1.0f;//Использовать 100% разностей float Blend2 =1.of;

Для комбинирования разностей вам просто необходимо умножить их на только что определенные значения комбинирования.

// Применить значения комбинирования vecPosDiff1 *=Blendl;vecNormalDiff1 *=Blend1; vecPosDiff2 *=Blend2;vecNormalDiff2 *=Blend2;

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

// Получить соответствующие значения комбинированных разностей D3DXVECTOR3 vecBlendedPos =vecPosDiff1 +vecPosDiff2; D3DXVECTOR3vecBlendedNormal=vecNormalDiff1+vecNormalDiff2;

Последним шагом является прибавление комбинированных разностей к координатам вершин и нормалей базового меша и сохранение результата в буфере вершин комбинированного меша.

//Прибавить разности к значениям базового меша и сохранить результат pBlendedVertices->vecPos =vecBlendedPos + \

pBaseVertices->vecPos;

// Нормализовать нормали перед сохранением!

D3DXVECTOR3 vecNormals =BlendedNormal+pBaseVertices->vecNormal; D3DXVec3Normalize(&pBlendedVertices->vecNormal, &vecNormals);

Комбинирование морфированных анимаций

Все, что остается сделать, - это увеличить указатели буферов вершин для обработки следующей вершины в каждом меше, закрыть кодовый блок for...next для завершения обработки вершин и разблокировать буферы вершин.

// Перейти к следующим вершинам pBaseVertices++;pBlendedVertices++; pTarget1Vertices++;pTarget2Vertices++;

}//Следующая итерация цикла

//Разблокировать буферы вершин pBlendedMesh->UnlockVertexBuffer(); pTarget2Mesh->UnlockVertexBuffer(); pTarget1Mesh->UnlockVertexBuffer(); pBaseMesh->UnlockVertexBuffer();

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

Что это, скажите вы? Вы бы выбрали более быстрый способ комбинирования мешей? Хорошо, мой друг, боги программирования услышали ваши молитвы, и скоро вы увидите как можно использовать вершинные шейдеры для выполнения всей грязной работы комбинирования за вас!

Создание вершинных шейдеров комбинированного морфирования

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

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

284 Глава 10

Комбинированный вершинный шейдер будет работать аналогично тому, как вы непосредственно комбинировали координаты вершин ранее в этой главе. Для каждого комбинируемого меша вам необходимо получить доступ к его буферу вершин. Используя вершинные шейдеры, необходимо будет ассоциировать каждый буфер вершин с потоком вершин. Вместо того чтобы для получения данных вершин блокировать буфер вершин, вы используете данные потока вершин (как ассоциировано в объявлении вершин) для получения координат и нормалей.

Единственно проблемой является то, что вершинные шейдеры не могут использовать так много потоков. В дополнение, каждый вершинный шейдер имеет доступ к ограниченному количеству вершинных регистров (таких как координаты, нормали и текстурные координаты). DirectX 8 и 9 ограничивает число вершинных регистров 16, так что приходится считать каждый кусочек информации.

Если структура вершин должна содержать по крайне мере координаты вершины, нормаль и текстуру (всего три регистра на один поток), то вы можете использовать только пять мешей, один из которых базовый. В вершинном шейдере вы можете установить до четырех комбинированных мешей. Первым шагом к созданию вершинного шейдера комбинированного морфирования является определение структур и объявлений вершин. Помните, что необходимо сохранять минимальное количество данных (максимум три используемых регистра), так что структура вершины может выглядеть так:

typedef struct {

D3DXVECTOR3 vecPos; //Координаты вершины D3DXVECTOR3 vecNormal; //Нормаль вершины float u,v; //Текстурные координаты

} sBlendVertex;

Комментарии внутри структуры sBlendVertex говорят сами за себя, так что я пропущу объяснения и перейду к объявлению вершин.

// Объявления и интерфейсы вершинного шейдера D3DVERTEXELEMENT9 g_MorphBlendMeshDecl [] ==

{

//Первый поток используется для базового меша

//задать положение, нормаль и текстурные координаты {0,0,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT, \

D3DDECLUSAGE_POSITION,0 }, {0,12,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,

D3DDECLUSAGE_NORMAL,0 }, {0,24,D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,

D3DDECLUSAGE_TEXCOORD,0 },

//Второй поток используется для первого меша {1,0,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,

D3DDECLUSAGE_POSITION,1 },

Комбинированиеморфированныханимаций

{1,12,D3DDECLTYPE_FLOAT3,D3DDECLMETH0D_DEFAULT, D3DDECLUSAGE_NORMAL,1 },

{1,24,D3DDECLTYPE_FLOAT2,D3DDECLMETH0D_DEFAULT, D3DDECLUSAGE_TEXCOORD,1 },

// Третий поток используется для второго меша {2,0, D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,

D3DDECLUSAGE_POSITION,2 }, {2,12,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,

D3DDECLUSAGE_NORMAL,2 }, {2,24,D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,

D3DDECLUSAGE_TEXCOORD,2 } ,

// Четвертый поток используется для третьего меша ' {3,0,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,

D3DDECLUSAGE_POSITION,3 }, {3,12,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,

D3DDECLUSAGE_NORMAL,3 }, {3,24,D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,

D3DDECLUSAGE_TEXCOORD,3 },

// Пятый поток используется для четвертого меша {4,0, D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,

D3DDECLUSAGE_POSITION,4 }, {4,12,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,

D3DDECLUSAGE_NORMAL,4 }, {4,24,D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,

D3DDECLUSAGE_TEXCOORD,4 },

D3DDECL_END()

};

В g_BlendMorphDecl вы можете видеть объявление пяти потоков, содержащих трехмерное положение, нормаль и двухмерные текстурные координаты. Первый поток имеет индекс использования 0, второй поток имеет индекс использования 1 и т. д. Это означает, что у вершинного шейдера будет доступ к пяти используемым типам для каждой компоненты вершины (положения, нормали и текстурных координат). В таблице 10.1 показаны типы данных, хранимые в каждом вершинном регистре.

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

Замечание. Вы можете найти вершинный шейдер комбинированного морфирования (MorphBlend.vsh) на компакт диске. Посмотрите конец этой главы для получения дополнительной информации о демонстрационной программе комбинированного морфирования.

286

Глава10

 

Таблица 10.4. Назначение вершинных регистров комбинированной

морфируемой анимации

 

 

 

Вершинный регистр

Назначение

 

 

v0

Трехмерные координаты первого (базового) меша

 

 

v1

Нормаль первого (базового) меша

 

 

v2

Текстурные координаты первого (базового) меша

 

 

v3

Трехмерные координаты второго меша

 

 

v4

Нормаль второго меша

 

 

v5

Текстурные координаты второго меша

 

 

v6

Трехмерные координаты третьего меша

 

 

v7

Нормаль третьего меша

 

 

v8

Текстурные координаты третьего меша

 

 

v9

Трехмерные координаты четвертого меша

 

 

v10

Нормаль четвертого меша

 

 

v11

Текстурные координаты четветого меша

 

 

v12

Трехмерные координаты пятого меша

 

 

v13

Нормаль пятого меша

 

 

v14

Текстурные координаты пятого меша

 

 

Эта разность масштабируется на заданное процентное соотношение (с помощью константы вершинного шейдера, находящейся в диапазоне от 0 до 1), и результат, полученный от каждого комбинируемого меша, добавляется к результирующему набору координат положения, нормали и текстурных координат выходной вершины. Просто, не правда ли?

Посмотрите на код вершин, чтобы увидеть что происходит.

;v0 =Положеyие (xyz) базового меша ;v1 =Нормаль (xyz) базового меша

;v2 =Текстурные координаты (ху) базового меша

;

;v3 комбинированное положение (xyz) первого меша ;v4 комбинированная нормаль (xyz) первого меша

;v5 =Комбинированные текстурные координаты (ху) первого меша

;v6 комбинированное положение (xyz) второго меша ;v7 комбинированная нормаль (xyz) второго меша

Комбинированиеморфированныханимаций

;v8 комбинированные текстурные координаты (ху) второго меша

;

;v9 =Комбинированное положение (xyz) третьего меша ;v10 =Комбинированная нормаль (xyz) третьего меша

;v11 =Комбинированные текстурные координаты (ху) третьего меша

;

;v12 =Комбинированное положение (xyz) четвертого меша ;v13 =Комбинированная нормаль (xyz) четвертого меша

;v14 =Комбинированные текстурные координаты (ху) четвертого меша

;

;с0-с3 =матрица мир+вид+проекция

;c4 комбинированные значения 0-1 (mesh1,mesh2,mesh3,mesh4) ;c5 =направление света

vs. 1.0

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

От с0 до с3 должны содержать транспонированную матрицу преобразования мир*вид*проекция.

с4 содержит значения комбинирования для каждого меша (с4.х для меша 1, с4.у для меша 2, c4.z для меша 3 и c4.w для меша 4).

с5 содержит вектор направления света.

Явернусь к этим константам немного позже; а пока я продолжу код вершинного шейдера. После комментариев я добавил необходимую версию вершинного шейдера. Как вы можете видеть, вершинный шейдер комбинированного морфирования требует вершинного шейдера версии 1.0, который должен поддерживаться большинством карт, к тому времени, как вы будете читать эту книгу.

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

;объявить привязывание dcl_position v0 ;базовый меш dcl_normal v1

dcl_texcoord v2

dcl_position1 v3 ;первый меш dcl_normal1 v4

dcl_texcoord1 v5

dcl_position2 v6 ;второй меш dcl_normal2 v7

dcl_texcoord2 v8

288

dcl_position3 v9 ;третий меш dcl_normal3 v10 dcl_texcoord3 v11

dcl_position4 v12 ;четвертый меш dcl_normal4 v13

dcl_texcoord4 v14

После ассоциирования регистров вершин вы можете получить доступ к данным вершин, используя регистры от v0 до v14. Регистр v0 содержит координаты вершины базового меша; регистр v6 содержит координаты вершины второго меша и т. д.

В начале фактического кода вершинного шейдера координаты вершины базового меша и его нормаль помещаются в два временных регистра (r0 и r1).

; Поместить базовые координаты и нормаль в регистры r0 и r1 mov r0,v0 ;координаты (r0)

mov r1,v1 ;нормаль (r1)

Шейдер использует эти два регистра только в качестве ссылок, так что они не будут переписаны при вызове последующих функий (по крайне мере до завершения работы шейдера, как вы скоро увидите). Следующий кусочек кода вычисляет разность координат базового меша и меша, заданного в качестве первого комбинируемого, который использует регистры вершин начиная с v3 до v5. Разность масштабируется (умножается) на значение константы с4.х (значение от 0 до 1) и прибавляется к начальным координатам из r0, хранимым в регистре r4. На протяжении оставшейся работы вершинного шейдера r4 будет содержать результирующие координаты вершины комбинированного меша. Точно такой же процесс повторяется для нормалей, а результат хранится в r5. Посмотрите:

;Получить разности первого комбинируемого меша и добавить их ;к результату

sub r2,v3,r0 ;Получить разность координат mad r4,r2,c4.х,r0 ;Поместить результат в r4 sub r3,v4,r1 ;Получить разность нормалей

mad r5,r3,c4.х,r1 ; Поместить результат в r4

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

;Получить разности второго комбинированного меша и добавить их к ; результату

sub r2,v6,r0 ;Получить разность координат

Соседние файлы в предмете Программирование на C++