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

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

mad r4,r2,с4.у,r4 ;Добавить полученные координаты к r4 sub r3,v7,r1 ;Получить разность нормалей

mad r5,r3,c4.y,r5 ;Добавить полученную нормаль к r5

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

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

mad r4,r2,c4.z,r4 ; Добавить полученные координаты к r4 sub r3,v10,r1 ; Получить разность нормалей

mad r5,r3,c4.z,r5 ; Добавить полученную нормаль к r5

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

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

mad r4,r2,c4.w,r4 ; Добавить полученные координаты к r4 sub r3,v13,r1 ; Получить разность нормалей

mad r5,r3,c4.w,r5 ; Добавить полученную нормаль к r5

После того как вы получили результирующую комбинированную вершину (в r4), вершинный шейдер должен преобразовать ее положение на матрицу объединенного преобразования мира, вида и проекции (хранимой в константах от с0 до с3). Что же касается нормали (сохраненной в r5), вы можете векторно умножить ее на обратное направление света (хранимое в с5) для получения рассеянной компоненты цвета, используемого для затемнения многоугольников.

; Спроецировать положение, используя преобразование мир*вид*проекция m4x4 oPos,r4,c0

;Векторно умножить нормаль на обратное направление света dp3 oD0,r5,-c5

Наконец, текстурные координаты могут быть взяты из регистра вершин базового меша v2 и помещены в выходной регистр текстуры t0.

;Сохранить текстурные координаты mov oT0.xy,v2

На этом заканчивается программирование вершинного шейдера. Все, что остается сделать, - это поместить шейдер в проект и выяснить, как заставить его работать.

Использование вершинного шейдера морфируемого комбинирования

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

290

Глава 10

ID3DXMesh

*pBaseMesh;

ID3DXMesh

*pMesh1,*pMesh2,*pMesh3,*pMesh4;

Предположим то же самое и для вершинного шейдера и объявления вершин - что вы уже загрузили их и получили их правильные интерфейсы:

IDirect3DVertexShader9 *pShader;

IDirect3DVertexDeclaration9 *pDecl;

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

pDevice->SetFVF(NULL); //Очистить использование FVF pDevice->SetVertexShader(pShader); //Установить вершинный шейдер pDevice->SetVertexDeclaration(pDecl); //Установить объявления

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

// Получить размер вершины

DWORD VertexStride =D3DXGetFVFVertexSize(pBaseMesh->GetFVF()); //Получить указатели на буферы вершин

IDirect3DVertexBuffer9 *pBaseVB; IDirect3DVertexBuffer9 *pMesh1VB,*pMesh2VB; IDirect3DVertexBuffer9 *pMesh3VB,*pMesh4VB;

pBaseMesh->GetVertexBuffer(&pBaseVB); pMesh1->GetVertexBuffer(&pMesh1VB); pMesh2->GetVertexBuffer(&pMesh2VB); pMesh3->GetVertexBuffer(&pMesh3VB); pMesh4->GetVertexBuffer(&pMesh4VB); //Установить потоки вершин

pDevice->SetStreamSource(0,pBaseVB,VertexStride); pDevice->SetStreamSource(1,pMesh1VB,VertexStride); pDevice->SetStreamSource(2,pMesh2VB,VertexStride); pDevice->SetStreamSource(3,pMesh3VB,VertexStride); pDevice->SetStreamSource(4,pMesh4VB,VertexStride);

Теперь необходимо получить текущие матрицы преобразования мира, вида

ипроекции вашего 3D устройства. Эти матрицы объединяются, транспонируются

исохраняются в регистры констант вершинного шейдера с с0 до с3. Следующий код замечательно с этим справляется.

//Получить матрицы мира, вида и проекции D3DXMATRIX matWorld,matView,matProj; pDevice->GetTransform(D3DTS_WORLD,&matWorld);

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

pDevice->GetTransform(D3DTS_VIEW,&matView); pDevice->GetTransform(D3DTS_PR0JECTI0N,&matProj);

//Получить матрицу мир*вид*проекция и установить ее D3DXMATRIX matWVP;

matWVP =matWorld *matView *matProj; D3DXMatrixTranspose(&matWVP,&matWVP); g_pD3DDevice->SetVertexShaderConstantF(0,(float*)&matWVP,4);

Для управления величиной комбинирования для каждого меша просто измените значения, хранимые в регистре с4. Регистр х константы с4 представляет собой величину комбинирования для первого меша и меняется в диапазоне от 0 до 1 (или больше, если вы хотите получить преувеличенные результаты).

Замечание.НасамомделевынедолжнывызыватьGetTransformдляполученияразличныхматрицпреобразования.Этиматрицыдолжныхранитьсяввашемприложении,повозможности(нонеобязательно)наглобальномуровне.

Аналогично и для с4.у, c4.z, c4.w - каждый меш имеет регистр, хранящий величину комбинирования (у для второго меша, z для третьего, w для четвертого). Пока что установим значения комбинирования в 100 процентов (сохраняя значение 1.0 для каждого значения комбинирования в объекте D3DXVECTOR4) и сохраним эти значения в константе вершинного шейдера с4, используя функцию SetVertexShaderConstantF .

//Установить величины комбинирования

D3DXVECTOR4 vecBlending =D3DXVECTOR4(1.0f,1.0f,1.0f,1.0f); pDevice->SetVertexShaderConstantF(4,(float*)&vecBlending,1);

Последнее что нужно сделать, это установить направление света сцены (то же самое, что использовалось в структуре D3DLIGHT9) в константу вершинного шейдера с5. Например, если вы хотите, чтобы свет (расположенный в мировом пространстве) был направлен вниз, вы можете использовать вектор с координатами 0,1,0. (Заметьте, что используете объект D3DXVECTOR4 для сохранения направления вектора, в противоположность объекту D3DXVECTOR3 просто задайте 0 в качестве компоненты w.)

//Установить вектор света

D3DXVECTOR3 vecLight =D3DXVECTOR4(0.0f,1.0f,0.0f,0.0f); pDevice->SetVertexShaderConstantF(5,(float*)&vecLight,1);

Т. к. вы получаете данные вершин из набора объектов ID3DXMesh, вам необходимо установить буфер индексов, потому что все объекты ID3DXMesh используют индексированные списки элементарных объектов. Необходимо установить буфер индексов только базового меша, потому что буферы индексов одинаковы у всех мешей. Следующий код устанавливает буфер индексов базового меша:

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