netlib.narod.ru | < Назад | Оглавление | Далее > |
Частицы — это очень маленькие объекты, которые обычно математически моделируются как точки. Из этого следует, что примитивы точек (D3DPT_POINTLIST из D3DPRIMITIVETYPE) стоят в первых строчках списка кандидатов на отображение частиц. Однако примитивы точек визуализируются как единственная точка. Это не предоставляет нам достаточной гибкости, поскольку могут требоваться частицы разного размера и текстуры частиц могут даже наноситься на карту. даже вся карта может быть тексурирована этими частицами. До Direct3D 8.0 способ обойти накладываемые на примитивы точек ограничения состоял в том, чтобы не использовать их вообще. Вместо этого для отображения частиц программисты использовали щиты (billboard). Щит — это прямоугольник, который мировая матрица всегда ориентирует так, чтобы лицевой стороной он был обращен к камере.
В Direct3D 8.0 появился специальный точечный примитив, называемый точечный спрайт (point sprite), который замечательно подходит для реализации систем частиц. В отличие от обычных точечных примитивов точечному спрайту может быть назначена текстура, которая может изменять свой размер. В отличие от щита мы можем описать точечный спрайт с помощью одной точки, что экономит память и время процессора, ведь нам надо обрабатывать одну вершину, а не четыре как у щита (прямоугольника).
Для описния местоположения и цвета наших частиц мы будем использовать следующий формат вершин:
struct Particle { D3DXVECTOR3 _position; D3DCOLOR _color; static const DWORD FVF; }; const DWORD Particle::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
В структуре просто хранятся местоположение вершины и ее цвет. В зависимости от требований вашего приложения вы можете хранить также и набор координат текстур. Текстурирование точечных спрайтов мы рассмотрим в следующем разделе.
В структуру Particle можно добавить переменную с плавающей точкой, задающую размер частицы. Для этого к описанию настраиваемого формата вершин следует добавить флаг D3DFVF_PSIZE. Если частица может иметь собственный размер, мы сможем реализовать множество эффектов, основанных на изменении размеров отдельных частиц. Однако большинство видеокарт не поддерживают такой способ управления размером частиц, поэтому мы не будем обсуждать его. (Чтобы убедиться, что ваша видеокарта поддерживает эту возможность проверьте флаг D3DFVFCAPS_PSIZE в члене FVFCaps структуры D3DCAPS9.) Вместо этого мы будем управлять размером частиц с помощью режимов визуализации, как показано ниже. Вот пример структуры данных вершины с членом, определяющим размер:
struct Particle { D3DXVECTOR3 _position; D3DCOLOR _color; float _size; static const DWORD FVF; }; const DWORD Particle::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_PSIZE;
Обратите внимание, что даже если возможность D3DFVFCAPS_PSIZE не поддерживается, можно управлять размерами отдельных частиц с помощью вершинных шейдеров. Вершинные шейдеры рассматриваются в четвертой части этой книги.
Поведение точечных спрайтов в основном контролируется через режимы визуализации. Сейчас мы рассмотрим эти режимы.
D3DRS_POINTSPRITEENABLE — Логическое значение. Значение по умолчанию — false.
True указывает, что установленная в данный момент текстура накладывается на точечные спрайты целиком.
False указывает, что на точечный спрайт накладывается только тот тексель текстуры, который задан координатами текстуры точечного спрайта (если координаты текстуры присутствуют в структуре данных вершины точечного спрайта).
_device->SetRenderState(D3DRS_POINTSPRITEENABLE, true);
D3DRS_POINTSCALEENABLE — Логическое значение. Значение по умолчанию — false.
True указывает, что размер точки интерпретируется в единицах пространства вида. Единицы пространства вида просто ссылаются на трехмерную точку в пространстве камеры. В этом случае размер точечного спрайта масштабируется в зависимости от того, как далеко он находится. В результате, подобно всем другим объектам, частицы расположенные далеко от камеры будут выглядеть меньше, чем частицы, расположенные близко к камере.
False указывает, что размер точки интерпретируется в единицах экранного пространства. Единицы экранного пространства это отображаемые на экране пиксели. Так что если вы укажете false и, например, установите размер точечного спрайта равным 3, то он будет занимать на экране область размером 3 × 3 пикселя.
_device->SetRenderState(D3DRS_POINTSCALEENABLE, true);
D3DRS_POINTSIZE — Используется для задания размера точечных спрайтов. Значение интерпретируется либо как единицы пространства вида, либо как единицы экранного пространства, в зависимости от установленного значения режима D3DRS_POINTSCALEENABLE. Приведенный ниже фрагмент кода устанавливает размер точки равным 2.5 единицам:
_device->SetRenderState(D3DRS_POINTSIZE, d3d::FtoDw(2.5f));
Функция d3d::FtoDw — это вспомогательная функция, добавленная нами в файлы d3dUtility.h/cpp, которая выполняет приведение типа float к типу DWORD. Нам приходится выполнять эту операцию потому что функция IDirect3DDevice9::SetRenderState ожидает значения типа DWORD а не float.
DWORD d3d::FtoDw(float f) { return *((DWORD*)&f); }
D3DRS_POINTSIZE_MIN — Задает минимальный размер точечного спрайта. Приведенный ниже пример устанавливает минимальный размер равным 0.2:
_device->SetRenderState(D3DRS_POINTSIZE_MIN, d3d::FtoDw(0.2f));
D3DRS_POINTSIZE_MAX — Задает максимальный размер точечного спрайта. Приведенный ниже пример устанавливает максимальный размер равным 5.0:
_device->SetRenderState(D3DRS_POINTSIZE_MAX, d3d::FtoDw(5.0f));
D3DRS_POINTSCALE_A, D3DRS_POINTSCALE_B, D3DRS_POINTSCALE_C — Эти три константы позволяют управлять тем, как будет меняться размер точечного спрайта при изменении расстояния от него до камеры.
Для вычисления итогового размера точечного спрайта на основании расстояния до камеры и рассматриваемых констант Direct3D использует следующую формулу:
где:
FinalSize — Итоговый размер точечного спрайта после вычислений расстояния.
ViewportHeight — Высота порта просмотра.
Size — Исходный размер, определяемый установленным значением режима визуализации D3DRS_POINTSIZE.
A, B, C — Значения, заданные режимами визуализации D3DRS_POINTSCALE_A, D3DRS_POINTSCALE_B и D3DRS_POINTSCALE_C соответственно.
D — Расстояние от точечного спрайта до камеры в пространстве вида. Поскольку в пространстве вида камера находится в начале координат, это расстояние вычисляется по формуле
где (x, y, z) — это координаты местоположения точечного спрайта в пространстве вида.
Приведенный ниже пример устанавливает значения констант таким образом, чтобы с увеличением расстояния размер точечных спрайтов уменьшался:
_device->SetRenderState(D3DRS_POINTSCALE_A, d3d::FtoDw(0.0f)); _device->SetRenderState(D3DRS_POINTSCALE_B, d3d::FtoDw(0.0f)); _device->SetRenderState(D3DRS_POINTSCALE_C, d3d::FtoDw(1.0f));
У частиц может быть множество других атрибутов, помимо местоположения и цвета; например, у каждой частицы может быть своя скорость. Однако, эти дополнительные атрибуты не нужны для визуализации частицы. Соответственно мы храним данные для визуализации частицы и дополнительные атрибуты в разных структурах. Создавая, уничтожая и обновляя частицы мы работаем с их атрибутами; затем, когда все готово к визуализации, мы копируем местоположение и цвет частицы в структуру Particle.
Атрибуты частицы зависят от того, какую именно модель частиц мы создаем. Однако, мы можем выделить несколько общих атрибутов, которые перечислены в приведенном ниже примере структуры данных. Большинству систем частиц не потребуются все эти атрибуты, а для некоторых систем надо будет добавить дополнительные атрибуты отсутствующие в списке.
struct Attribute { D3DXVECTOR3 _position; D3DXVECTOR3 _velocity; D3DXVECTOR3 _acceleration; float _lifeTime; float _age; D3DXCOLOR _color; D3DXCOLOR _colorFade; bool _isAlive; };
_position — Местоположение частицы в мировом пространстве.
_velocity — Скорость частицы, обычно измеряемая в условных единицах в секунду.
_acceleration — Ускорение частицы, обычно измеряемое в условных единицах за секунду.
_lifeTime — Сколько времени должно пройти до гибели частицы. Например, мы можем указать, что частицы образующие лазерный луч пропадают через указанный период времени.
_age — Текущий возраст частицы.
_color — Цвет частицы.
_colorFade — Как цвет частицы меняется с течением времени.
_isAlive — True если частица жива, false если она погибла.
netlib.narod.ru | < Назад | Оглавление | Далее > |