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

Использованиечастицванимации

337

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

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

Рисование частиц с помощью квадратных полигонов

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

Вершины

Полигоны

Рис. 12.4. Частица, имеющая размер 10 единиц, имеет протяженность 5 единиц в направлениях осей х и у

338

Глава 12

 

В дополнение к координатам вершин, используемым при рисовании частицы,

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

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

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

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

Предположим, вы хотите, чтобы частица была 20 единиц в ширину и 50 единиц в высоту. Этот размер применяется только к осям х и у (т. к. на самом деле частица является плоским объектом, который всегда направлен к смотрящему). При создании частицы ее центр располагается в начале координат мира. Используя размеры частицы, вы можете создать вершины, представляющие ее углы. Эти вершины располагаются, используя размеры частицы, деленные пополам, в качестве смещения. Например, частица размеров 20x50 лежит от-10 до 10 на оси х и от-25 до 25 на оси у.

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

typedef struct {

D3DXVECTOR3 vecPos; // Координаты вершины частицы D3DCOLOR Diffuse; // Рассеянный цвет

Использование частицванимации

float u, v; // Текстурные координаты } sVertex;

Не забудьте определять объявление FVF для только что созданной структуры.

#define VERTEXFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)

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

Буфер вершин можно создать, используя следующий код:

IDirect3DVertexBuffer9 *pVB = NULL; pDevice->CreateVertexBuffer(4*sizeof(sVertex), \

D3DUSAGE_WRITEONLY, \ VERTEXFVF, D3DPOOL_DEFAULT, \ &pVB, NOLL);

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

//Size = размер частицы, в данном случае 10.0 float Size = 10.0;

//Получить размер,деленный пополам, для установки координат вершин float HalfSize = Size / 2.0f;

//Заблокировать буфер вершин и заполнить его данными вершин sVertex *Vertex = NULL;

pVB->Lock(0, 0, (void**)&Vertex, 0);

//Верхний левый угол, вершина номер 0

pVB[0].vecPos = D3DXVECTOR3(-Size, Size, 0.0f); pVB[0].Diffuse = D3DCOLOR_RGBA(255,255,255,255); pVB[0].u = 0.0f; pVB[0].v = 0.0f;

//Верхний правый угол, вершина номер 1 pVB[1].vecPos = D3DXVECTOR3(Size, Size, 0.0f); pVB[1].Diffuse = D3DCOLOR_RGBA(255,255,255,255) ; pVB[1].u = 1.0f; pVB[1].v = 0.0f;

//Нижний левый угол, вершина номер 2 pVB[2].vecPos = D3DXVECTOR3(-Size, -Size, 0.0f); pVB[2].Diffuse = D3DCOLOR_RGBA(255,255,255,255); pVB[2].u = 0.0f; pVB[2].v = 1.0f;

340

Глава 12

//Нижний правый угол, вершина номер 3 pVB[3].vecPos = D3DXVECTOR3(Size, -Size, 0.0f); pVB[3].Diffuse = D3DCOLOR_RGBA(255,255,255,255); pVB[3].u = 1.0f; pVB[3].v = 1.0f;

//Разблокировать буфер вершин

pVB->Unlock();

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

Также необходимо повернуть многоугольники таким образом, чтобы они были направлены на смотрящего, что, как вы помните, является целью биллбординга. Необходимо вычислить биллборд-преобразование, чтобы повернуть многоугольники

ксмотрящему. Используя это преобразование, вы добавляете координаты частицы

вместо, где она должны быть нарисована (в мировых координатах).

Предупреждение. Использование функции GetTransform для получения преобразования Direct3D сильно замедляетработу и не всегда возможно. Лучше всего хранить глобальныепреобразованиямира,видаипроекции,которыеможнопотомиспользовать.Однако покая последую плохим путем и буду использовать GetTransform вучебных целях.

Для создания биллборд-преобразования необходимо получить матрицу преобразования вида и вычислить обратную ей матрицу (таким образом меняя порядок содержащихся в ней преобразований на обратный), используя функцию D3DXMatrixInverse, как показано тут:

// Получить матрицу преобразования вида и обратить ее D3DXMATRIX matView;

pDevice->GetTransform(D3DTS_VIEW, &matView); D3DXMatrixInverse(&matView, NULL, &matView);

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

Использованиечастицванимации

//Положим ParticleXPos,ParticleYPos и ParticleZPos содержат мировые

//координаты рисуемой частицы. Добавить координаты рисуемой частицы matView._41 = ParticleXPos;

matView._42 = ParticleYPos; matView._43 = ParticleZPos;

//Установить результирующую матрицу в качестве преобразования мира pDevice->SetTransform(D3DTS_WORLD, &matView);

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

Пропустив установку z-буфера (вы должны были сделать ее ранее), вы можете включить альфа тестирование и альфа смешивание так:

// Включить альфа тестирование

pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); pDevice->SetRenderState(D3DRS_ALPHAREF, 0x08); pDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);

// Включить альфа смешивание (простого добавочного типа) pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR); pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);

Что касается альфа-тестирования, я выбрал использования правила сравнения больше или равно. Это означает, что если пиксели текстуры частицы имеют значение альфа большее или равное 8, то они визуализируются, в противном же случае они пропускаются. Использование альфа-тестирования означает необходимость использования функции D3DXCreateTextureFromFileEx для загрузки текстур, задав цветовой режим, использующий альфа каналы (такой как D3DFMT_A8R8G8B8), и цветовой ключ непрозрачного черного (D3DCOLOR_RGBA(0,0,0,255)), как показано в следующем кусочке кода:

D3DXCreateTextureFromFileEx(

pDevice,

"Particle.bmp",

D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX DEFAULT, D3DCOLOR_RGBA(0,0,0,255), NULL, NULL, &pTexture);

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