Архитектура движка.Статьи

EngineResearch(1): CatMother RenderAPI

Автор:

Были использованы исходные коды проекта CatMother http://catmother.sourceforge.net/  (C) 2003 Cat Mother, Ltd.

В свободное время разглядывал следующие проекты:

•  CatMother
•  OGRE
•  RGDE
•  Linderdaum
•  UniGine
•  IrrLicht
•  Genesis 3d
•  Quake2
•  Quake3
•  XEngine
•  WildMagic
•  Torque Engine (не shader-based)

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

•  Texture
•  Material
•  Mesh
•  Render-state
•  Render-pass
•  Technique
•  Shader
•  Camera

1. CatMother Engine

1.1 Texture

1.1.1 Обзор

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

То есть:

class BaseTextureImplInterface {
public:
  virtual ~BaseTextureImplInterface() {}
};

class BaseTexture
{
public:
  virtual void  addReference() = 0;
  virtual void  release() = 0;
  virtual void  destroy() = 0;
  virtual long  textureMemoryUsed() const = 0;  
  virtual BaseTextureImplInterface*  impl() = 0;
protected:
  BaseTexture() {}
  virtual ~BaseTexture() {}
private:
  BaseTexture( const BaseTexture& );
  BaseTexture& operator=( const BaseTexture& );
};

От BaseTexture наследуются два других интерфейса, это CubeTexture и  обычная текстура Texture.

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

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

CubeTexture состоит из шести частей, как и положено. Может быть сформирована через объект Surface, который, в свою очередь, может быть загружен как готовый ресурс, либо создан из обычной текстуры.

К общим частям Texture и CubeTexture относится наличие методов  создания mipmaps. Они либо вычисляются внутренними средствами реализации, либо задаются извне.

Примечательным является наличие методов textureMemoryUsed и Load/Unload. Первый, предположительно, может применяться для эвристических оценок при run-time оптимизациях. Вторые два должны  обеспечить явную загрузку и выгрузку данных из GPU.

1.1.2 Иерархия классов

catmother_textureclass | EngineResearch(1): CatMother RenderAPI

Основной интерфейс – это BaseTexture, он объявляет методы для подсчета ссылок. Интерфейс специализируется в Texture и CubeTexture. Эти интерфейсы очень похожи. Они определяют методы для загрузки и работы с текстурой на низком уровне (lock/unlock/data). Загрузка происходит через объект Surface, представляющий собой обертку над битовой картой определенного формата.

BaseTexture связан с BaseTextureImplInterface через свой виртуальный метод. Это сделано единственно для того, чтобы было возможно преобразование BaseTexture  Dx9Texture (или в любую другую реализацию текстуры) с применением static_cast и одного виртуального вызова. Именно по этой причине заведены интерфейсы, которые содержат только пустой виртуальный деструктор: BaseTextureImplInterface и DX9BaseTextureImplInterface.

1.1.3 Выводы

Приведенная структура создана для поддержки Multi-API. Тем не менее, даже по реализации видно, что можно легко обойтись обычным static_cast и исключить множественное наследование.

1.2 Материал

1.2.1 Обзор

Для материалов есть базовый класс Material, который кроме прочего предусматривает подсчет ссылок и самоклонирование. По сути, материал является агрегатором почти всех возможных рендер-состояний, касающихся части ffp:
•  Depth-тест
•  Blend-режим
•  Режим отсечения граней
•  Stencil-тест

Кроме того, материал предусматривает работу с текстурами и установку режима смешения на каждой из стадий:
•  Источник вершинного цвета diffuse/specular/ambient;
•  Аргумент для TexEnvi;
•  Вид операции TexEnvi;
•  Источник текстурных координат (либо явно заданные, либо полученные в результате различных преобразований вершинных атрибутов, например, позиция вершин, приведенная к пространству камеры);
•  Режим фильтрации;
•  Режим обработки координат (wrapping).

Есть еще методы для запрета/разрешения освещения и установки флага Z-сортировки полигонов. Также материал обеспечивает настройку формата вершин.

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

Использование материала сводится к вызову трех функций. Первые две – это begin и end, подразумевающие установку и откат состояний, begin возвращает требуемое число проходов, которое использует материал. Третья функция – apply, вызывается для инициализации очередного прохода.

1.2.2 Иерархия классов

catmother_materialclass | EngineResearch(1): CatMother RenderAPI

Dx9RenderingState – структура, в которой хранятся настройки материала.  При вызове apply, Dx9Material передает эту структуру объекту, ответственному за коммуникацию с GAPI (Dx9GraphicsDevice), а последний уже производит установку состояний.

1.2.3 Концептуальная схема 

catmother_materialusage | EngineResearch(1): CatMother RenderAPI

Настройки (setup)

Из режимов (Modes) предусмотрен только режим сортировки полигонов по глубине. Под режимом понимается требуемый режим действий надсистемы. Так, например, материал не занимается сортировкой полигонов, а только может указывать на необходимость выполнения сортировки.

Любое использование текстур возможно только через материалы. В коде устанавливается константа – максимальное количество текстурных слоев, которое может содержаться в любом материале. Под текстурным слоем понимается совокупность ссылки на текстуру (BaseTexture) и настроек текстурной стадии (см. 1.2.1).

Остальные настройки (States) соответствуют конкретным рендер-состояниям (см. 1.2.1).

Второстепенные методы (services)

Есть подсчет ссылок, возможность полного клонирования и проверки совместимости материала с устройством вывода.

Непосредственное использование (usage)

Флаги (Flags) реализованы как методы, возвращающие булево значение. Флаги отражают некоторые установленные состояния (States) и режимы (Modes). Таким образом, возможно формирование более оптимального порядка следования материалов, чем может дать простая сортировка по материалам.

Про Begin, End, Apply – см 1.2.1.


1.2.4 Выводы

1.  Проверку на совместимость можно убрать, добавив например, метод Commit, который произведет дальнейшую настройку в зависимости от доступных возможностей устройства.
2.  Методы Begin, Apply, End относятся к категории критичных, так как вызываются в цикле вывода.
3.  По реализации видно, что класс материала – един на весь RenderAPI (Dx9GraphicsDevice создает экземпляры только класса Dx9Material). В то же время метод Begin требует всегда только одного прохода, вне зависимости от настроек. Это говорит о том, что класс не дописан до конца, либо имеются нестыковки на верхних уровнях.
4.  Метод Apply инициирует создание структуры Dx9RenderingState и её заполнение в соответствии с настройками, которые хранятся в приватных переменных материала. Далее, по ссылке эта структура отдается в Dx9GraphicsDevice через метод setRenderState, где осуществляется процесс перевода настроек в вызовы функций Direct3D, которые уже устанавливают нужные состояния.

Если не придираться к реализации, то остаются вопросы по общей структуре.

•  Во-первых, на мой взгляд, не следует устанавливать все состояния на этапе «применения» (apply) материала, но устанавливать только те, которые действительно изменились по сравнению с предыдущим материалом. Или, лучше по сравнению с предыдущим состоянием Dx9GraphicsDevice.
•  Невозможно сортировать по набору текстур.
•  Трудно сортировать по состояниям вообще.
•  Проверку на совместимость убрать и сразу собирать такие материалы, которые совместимы с устройством.
•  В Material нет ничего от programmable pipeline. Этот вопрос будет рассмотрен далее.

Страницы: 1 2 Следующая »

9 февраля 2006 (Обновление: 24 сен 2006)

Комментарии [15]