netlib.narod.ru< Назад | Оглавление | Далее >

Частицы

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

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

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


Рис. 2.22. Обычно для частиц вы будете использовать изображение круга, как показано здесь. Когда вы используете материалы, изображение при рисовании окрашивается

Рис. 2.22. Обычно для частиц вы будете использовать изображение круга, как показано здесь. Когда вы используете материалы, изображение при рисовании окрашивается


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

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

Вот пример, который создает буфер вершин частицы и рисует его на видеоустройстве:

// g_pD3DDevice = ранее инициализированный объект устройства

// Определяем структуру данных вершины и дескриптор
typedef struct {
    FLOAT x, y, z; // Локальные 3-D координаты
    FLOAT u, v;    // Координаты текстуры
} sVertex;
#define VertexFVF (D3DFVF_XYZ | D3DFVF_TEX1)

// Буфер вершин частицы и текстура
IDirect3DVertexBuffer9 *g_pParticleVB = NULL;
IDirect3DTexture9 *g_pParticleTexture = NULL;

BOOL SetupParticle()
{
    BYTE *Ptr;
    sVertex Verts[4] = {
        { -1.0f,  1.0f, 0.0f, 0.0f, 0.0f },
        {  1.0f,  1.0f, 0.0f, 1.0f, 0.0f },
        { -1.0f, -1.0f, 0.0f, 0.0f, 1.0f },
        {  1.0f, -1.0f, 0.0f, 1.0f, 1.0f }
    };

    // Создаем буфер вершин частицы и заполняем его данными
    if(FAILED(g_pD3DDevice->CreateVertexBuffer(
                    sizeof(sVertex) * 4, 0, VertexFVF,
                    D3DPOOL_MANAGED, &g_pParticleVB, NULL)))
        return FALSE;

    if(FAILED(g_pParticleVB->Lock(0,0, (void**)&Ptr, 0)))
        return FALSE;

    memcpy(Ptr, Verts, sizeof(Verts));
    g_pParticleVB->Unlock();

    // Получаем текстуру частицы
    D3DXCreateTextureFromFile(g_pD3DDevice, "particle.bmp",
                              &g_pParticleTexture);
        return TRUE;
}

BOOL DrawParticle(float x, float y, float z, float scale)
{
    D3DXMATRIX matWorld, matView, matTransposed;
    D3DXMATRIX matTrans, matScale;
    D3DMATERIAL9 d3dm;

    // Устанавливаем состояния визуализации
    // (альфа-смешивание и атрибуты)
    g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    g_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    g_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

    // Включаем фоновый свет
    g_pD3DDevice->SetRenderState(D3DRS_AMBIENT, 0xffffffff);

    // Устанавливаем буфер вершин частицы в качестве
    // источника потоковых данных
    g_pD3DDevice->SetStreamSource(0, g_pParticleVB,
                                     0, sizeof(sVertex));

    // Настраиваем вершинный шейдер на тип вершин частицы
    g_pD3DDevice->SetFVF(VertexFVF);

    // Устанавливаем текстуру
    g_pD3DDevice->SetTexture(0, g_pParticleTexture);

    // Устанавливаем цвет частицы
    ZeroMemory(&d3dm, sizeof(D3DMATERIAL9));
    d3dm.Diffuse.r = d3dm.Ambient.r = 1.0f;
    d3dm.Diffuse.g = d3dm.Ambient.g = 1.0f;
    d3dm.Diffuse.b = d3dm.Ambient.b = 0.0f;
    d3dm.Diffuse.a = d3dm.Ambient.a = 1.0f;
    g_pD3DDevice->SetMaterial(&d3dm);

    // Строим матрицу масштабирования
    D3DXMatrixScaling(&matScale, scale, scale, scale);

    // Строим матрицу перемещения
    D3DXMatrixTranslation(&matTrans, x, y, z);

    // Строим матрицу щита
    g_pD3DDevice->GetTransform(D3DTS_VIEW, &matView);
    D3DXMatrixTranspose(&matTransposed, &matView);

    // Комбинируем матрицы в единую матрицу мирового преобразования
    D3DXMatrixMultiply(&matWorld, &matScale, &matTransposed);
    D3DXMatrixMultiply(&matWorld, &matWorld, &matTrans);

    // Устанавливаем мировое преобразование
    g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);

    // Рисуем частицу
    g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

    // Выключаем альфа-смешивание
    g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

    return TRUE;
}

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

Законченный пример приложения, демонстрирующего достаточно сложный вариант применения частиц, вы найдете в проекте Particle на сопроводительном CD-ROM к этой книге (загляните в папку \BookCode\Chap02\Particle).


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz