Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Принцип организации графического движка

11K
09 сентября 2007 года
coolcoder
39 / / 14.08.2006
Сел недавно кодить некое подобие 3д движка на основе директХ, и тут же натолкнулся на ряд проблем. Начну описывать по порядку.
Для начала сразу скажу, что боюсь называть это «движком», ибо это не движок пока вовсе, а просто надстройка над директиксом. Я просто задался целью создать приемлемую для меня архитектуру, которая позволяла бы мне создавать модульные, масштабируемые приложения, которые можно было бы легко расширять. Глядя на стандартные примеры из сдк понял, что в них все процедурно-ориентированное, и чтобы добавить новую сущнгость, например, понятие ОБЪЕКТА, нужно будет переписать практически все процедуры, мне же хочется модульности. Решил сделать всё объектно-ориентированным, но теперь, по мере кодинга, немного запутался в связях между сущностями.
Для начала решил определиться с основными классами. Ими стали класс Объекта, Сцены и Движка. В движок я засунул все служебные переменные, необходимые для инициализации директа и создания директового девайса, необходимого для отображения. Сцена у меня содержит настройки окна (в случае, если прога работает в оконном режиме) и список всех объектов, которые должны быть отрендерены. Для этого я воспользовался вектором из стандартной библиотеки, а в главном цикле проге происходит рендеринг всех объектов, входящих в список, думаю, смысл понятен… Так вот отсюда мой первый вопрос: должен ли каждый объект включать метод
 
Код:
Render()
или же все объекты должны рендериться движком, то есть вот так:
 
Код:
Engine::Render(Object& obj);

И так для каждого объекта сцены? Но тогда получится, что движку будет необходимо «знать» обо всех возможных видах объектов, ведь класс Object – это просто абстрактный класс. Либо можно сделать просто чтобы все объекты сцены представлялись движку как меши и движок занимался непосредственно рендерингом мешей (ну и их текстурированием)?
Короче, пока мой основной вопрос: какая сущность должна рендерить объекты сцены : сами эти объекты должны заниматься своим рендерингом или их должен рендерить движок?
391
09 сентября 2007 года
Archie
562 / / 03.02.2005
Выполнять задачу должен тот объект, который содержит наибольшее кол-во информации для этого (так говорит К.Ларман в "Шаблонах проектирования"). Программные объекты не обязательно соответствуют объектам реального мира. А твой вопрос из разряда, как лучше:
 
Код:
window->close();

или
 
Код:
windowManager->close(window);

но, наверное, тут сомнений должно быть меньше :)
11K
09 сентября 2007 года
coolcoder
39 / / 14.08.2006
Цитата: Archie

А твой вопрос из разряда, как лучше:
 
Код:
window->close();

или
 
Код:
windowManager->close(window);



хм, ну и все-таки, какой именно вариант предпочтительнее из этих вот предложенных тобой двух?

391
09 сентября 2007 года
Archie
562 / / 03.02.2005
Оба варианта можно реализовать.
С одной стороны, движку нужна информация об объекте, чтобы отрисовать его, с другой стороны, объекту может потребоваться информация о состоянии движка (и других объектах), чтобы отрисовать себя.
Но первый вариант (когда объект сам себя отрисовывает) будет все же логичнее и нагляднее.
А Engine::Render(Object& obj) в итоге сведется к чему-то типа:
 
Код:
Engine::Render(Object& obj) {
  obj.Render();
}

:)
11K
09 сентября 2007 года
coolcoder
39 / / 14.08.2006
Я вот просто думаю сделать базовый класс для всех возможных объектов, чтобы движку они все представлялись мешами, которые он и будет рендерить пофигивая на навешанные навороты. Попробую сделать так…
353
11 сентября 2007 года
Nixus
840 / / 04.01.2007
По-моему, если пишешь движок, то рендерер нужно сделать отдельным интерфейсом. На вскидку:

Код:
class iRenderer: public iObject
{
public:
      virtual int Init(sGraphicsMode*, iViewport* = 0) = 0;
      virtual void Shutdown() = 0;

      // ...

      virtual void BeginFrame(sView& View) = 0;
      virtual void EndFrame() = 0;

      // ...
};

// ...

class sEngine: public iObject
{
public:
     sView View;
     iRenderer* pRenderer;
     iViewport* pViewport;

     // ...

     void Update();
};

void sEngine::Update()
{
     if(CheckRenderer())
    {
          pRenderer->BeginFrame(View);
          // ....
          pRenderer->EndFrame();
    }
}
7
15 сентября 2007 года
@pixo $oft
3.4K / / 20.09.2006
Если не секрет,скажи:
1)с чего вдруг ты решил написать движок?Захотелось Half Life ускорить?Если да,то помогу,чем смогу(оптимизация по скорости не повредит!)
2)ты уверен,что допишешь его?
3)надо ли делать классовую структуру движку?Не лучше ли в формате API?
Ты дал мало информации по организации движка:что он будет делать,как.Распиши подробней
309
16 сентября 2007 года
el scorpio
1.1K / / 19.09.2006
coolcoder
Для этого используются "абстрактные" методы - виртуальные методы с "нулевым" кодом. К примеру, класс Object должен иметь набор свойств/методов, которыми можно описать все необходимые "общие" действия.
Соотвественно, производные классы, описывающие объекты конкретного вида, будут содержать в себе переопределённые методы, реализующие конкретный вариант данного действия
А то, как это делать - разницы особой нет.
Хотя по логике вещей, объекты могут быть самого разного типа, а их отображение - выполняться принципиально различающимися способами. Поэтому лучше всё-таки объявить абстрактный метод void Object::Render (void). Так будет больше свободы в описании конкретной реализации данного действия.
255
17 сентября 2007 года
Dart Bobr
1.4K / / 09.04.2004
автору, очень рекомендую для прочтения книгу - GPU Gems. Многие вопросы отпадут сами по себе..
а по поводу твоего поста могу сказать, что есть смысл каждый обжект делить на меши.. каждый меш - можна уже будет рассматривать как отдельную единицу(которую нужно\ненужно рендерить, для этого тоже есть стандартные техники, уже даже хардварные). Для каждого типа материала - совокупность всех мешей - собирается в батч.. для каждого батча(!!) вызывается метод рендер. Почему так, а не иначе? Можно конечно и по-другому, но, так будет быстрее, потому-что смена материала - дорого по времени.
534
04 октября 2007 года
HarryAxe
448 / / 19.01.2006
Алилуйя, братья! Для работы непосредственно с графикой в DXSDK есть нехилый фреймворк, так что нефиг париться. Движок же не есть класс, включающий в себя сущности наподобие "объект", "свет" и "камера". Это - целая концепция, и чем она кучерявее, тем большим потенциалом движок обладает. На одной лишь технической стороне визуализации анимированной сцены уедешь совсем недалеко. Объекта со сценой мало. Необходимо так же понятие действия, менеджера объектов, очереди действий, связей и групп и т. д. А ещё всю эту философию нужно прикрутить к существующему API. Так что, заявлять синими буквами "Я делаю 3д двиг" крайне преждевременно.
Объек только выглядит. Любые изменения формы, содержания и смысловой нагрузки объектов должны выполнять действия (actions).
Цитата:
есть смысл каждый обжект делить на меши.. каждый меш - можна уже будет рассматривать как отдельную единицу

С точки зрения технической реализации, любую сетку необходимо разбивать на составляюцие части по признаку различия материалов/шейдерных эффектов. Это требует как D3D, так и OGL.

Цитата:
Я вот просто думаю сделать базовый класс для всех возможных объектов, чтобы движку они все представлялись мешами, которые он и будет рендерить пофигивая на навешанные навороты. Попробую сделать так…

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

26K
06 октября 2007 года
Rotveiler
20 / / 29.08.2007
Цитата: HarryAxe
Алилуйя, братья! Для работы непосредственно с графикой в DXSDK есть нехилый фреймворк, так что нефиг париться.



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

353
06 октября 2007 года
Nixus
840 / / 04.01.2007
Цитата: Rotveiler
В производительных проектах нужно структурное программирование а ООП лишний раз тормозит программу.


А с чего бы это ООП тормознее? Тормознее когда руки не оттуда растут.

534
07 октября 2007 года
HarryAxe
448 / / 19.01.2006
Цитата: Rotveiler
Эх, только вот тогда со скоростью придется распрощаться. В производительных проектах нужно структурное программирование а ООП лишний раз тормозит программу.


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

353
08 октября 2007 года
Nixus
840 / / 04.01.2007
Цитата: HarryAxe
мы теряем несколько наносекунд при выполнении какого-то вызова


Да не теряем мы ничего при ООП, откуда вы это взяли? Даже наоборот, приобретаем в некоторых реализациях.

Сравним

 
Код:
object_t obj;
do_action(&obj);

и
 
Код:
object_c obj;
obj.do_action();


В реализации ОО-вызовов от MS передача укзателя на объект осуществляется в регистре ecx, а не в стеке, как в первом листинге. Поэтому скорость выполнения во втором случае будет даже больше, при других равных условиях.
534
10 октября 2007 года
HarryAxe
448 / / 19.01.2006
Под потерей наносекунд я имел в виду потери при работе механизма вызова виртуальных функций
353
10 октября 2007 года
Nixus
840 / / 04.01.2007
Цитата: HarryAxe
Под потерей наносекунд я имел в виду потери при работе механизма вызова виртуальных функций


Ну здесь мы чуть-чуть потеряем, согласен. Но это не проблема ООП. Если брать код с одинаковыми возможностями, то ООП нисколько не уступает структурному подходу (это для параноиков).

255
10 октября 2007 года
Dart Bobr
1.4K / / 09.04.2004
О, господи, да тут пахнет холиваром..
Я вот только что подумал.. Давайте подумаем над тем, что графический движок должен делать, и чего он делать не должен, тогда сразу станет ясно, сколько времени мы так сказать потеряем, если будем использовать ООП.
Итак, графический движок должен, загружать обьекты и текстуры в видеопамять, производить трансформацию координат, отсечение невидимвых граней, наложение материалов, расчет освещения, ну и наложение эффектов.
Итак, учитывая то, что нормально написаный движок производит трансформацию координат при помощи вершинного шейдера, отсечение невидимых граней сначала на уровне бсп - просчитывается заранее, а более подробный анализ также реализован аппаратно, расчет освещения и пост процессинг выполняются при помощи пиксельных шейдеров, то главная задача - следить за своевременной загрузкой данных в видео память.. Собственно говоря, Загрузка данных может быть всегда выделена в отдельный поток.. поэтому потери в несколько наносекунд будут незаметны(ну, все есстественно зависит от рук), зато удобство работы с объектной моделью просто неоспоримо.
Это, конечно, мое имхо, так как я профессионально такими вещами не занимался..
534
11 октября 2007 года
HarryAxe
448 / / 19.01.2006
Цитата: Dart Bobr
О, господи, да тут пахнет холиваром..


Отнюдь. Мы живём в третьем тысячелетии, и каждому, по-моему, должно быть понятно, что ООП - более удачная технология, нежели любая вариация на тему процедурно-ориентированных техник программирования. Лучше настолько же, насколько электролобзик круче ножовки. Пропил одинаковый и там, и там. Однако, издержки при использовании нового инструмента и овладением навыком работы с ним ничтожно малы, по сравнению с предоставляемым им потенциалом и удобством в обращении. Кто не согласен - сносите Винды (их ядра жрут-то ого-го) и ставьте что-нибудь из прошлого века. MSDOS вполне подойдёт. А заодно напишите консольную версию вашего любимого web-браузера. А то, при использовании окон, с производительностью, поди, пришлось навеки распрощаться...

ООП само по себе издержек в производительности за собой практически не влечёт. Зато их может обеспечить абстрагирование, которого можно с помощью ООП достичь. Для того, чтобы перейти на более высокий уровень абстракции, зачастую необходимо, чтобы существующая прослойка была законченной, то есть робастной и самодостаточной. А это - некий код, приводящий её в такое состояние, код, корректно снимающий сделанные изменения, плюс код, обеспечивающий работу самой системы абстрагирования. Да туда же можно приписать и код, обслуживающий возможность повторного использования (вряд ли кто станет отрицать, что это - веское преимущество при использовании ООП). Это может быть, например, система проверок на корректность предоставленной блоку кода информации. Такая проверка нередко бывает излишней при использовании, например, класса, в тех условиях, для которых он и был создан. Зато она бывает безумно полезной при портировании класса в иное приложение. Вот вам и издержки.
Однако, их можно уменьшить в разы, если чётко себе представлять, из каких логических компонент состоит ядрышко, и каков характер взаимодействия между ними. Такого понимания, на мой взгляд, при работе над проектами, номинирующими на звание "сложный", да к тому же с возможностью растянуть сроки выполнения, необходимо достичь прежде, чем написать хоть строчку кода. Так, может, выдвинем фразу

Цитата: Dart Bobr
Давайте подумаем над тем, что графический движок должен делать, и чего он делать не должен...

на первый план, только в несколько иной форме: а чё вообще от системы требуется-то? Наличия каких возможностей мы добиваемся?

505
17 октября 2007 года
vAC
343 / / 28.02.2006
HarryAxe правильно говорит. Сначала спросите у клиента: а что вы хотите от системы? Может вы собираетесь делать то, что уже до вас уже сделали, и смысла в этом не будет никакого, проще преобрести готовый продукт. Собирите всю информацию, сделайте выработку требований. По требованиям решите вопрос технической возможности реализации проекта. Определитесь с инструментарием. Разбейте систему на подсистемы, подсистемы на классы, классы на данные и методы. В этом и есть прелесть ООП: после процесса проектирования у вас есть почти готовая архитектура. Останеться определить типы связей между объектами системы (has, use, ассоциация, агрегирование, наследование) сведя их к минимуму. Для этих целей можно конечно использовать CASE-технологии, но я предпочитаю не использовать такие технологии. Для удобства можно воспользоваться UML (одним из создателей является Гради Буч - пионер ООП). Только после этого можно приступать к конструированию (кодированию), и то, успех не гарантирован.

Могу сказать на 90%, что при таком подходе, автор топика не допишет движок, будет несколько раз начинать его заново, каждый раз меняя некоторую часть системы, но до логического конца дойти ему не удастся - фундамент будет трескаться то в одном месте, то в другом. К тому же такого рода ПО не под силу одному человеку, необходимо собирать команду. При этом сразу вспоминаю байку про то, как программисты дом строили :)
12K
11 ноября 2007 года
MuHAOS
63 / / 06.12.2006
Кому интересно вот моя 3-д игра http://muhasoft.phpnet.us/files/rc/d3d.rar. Написана в перемешку процедурним и ООП стилем. Все начиналось с камеры плавающей вокруг 3-д квадратиков, потом то добавил сьо добавил и так до скрипт-процесора.
11K
14 ноября 2007 года
coolcoder
39 / / 14.08.2006
Да причем тут вообще тормозность-нетормозность? Я же поднял тему о самом принципе организации двига, а конкретно: кто кого должен рендерить. Но вроде уже решил, что раз директу в конечном итое все объекты представляются как набор вершин и ему безразличны всякие навороты, то пускай он и рендерит вообще все объекты сам, а не объекты должны рендерить себя. Наверное так... Поправьте меня, если я неправ, укажите на вверное решение.
9.4K
15 ноября 2007 года
AIGrifon
165 / / 13.11.2007
coolcoder, загляни на
ogre3d.ru
Огр - это как раз ОО движок, который работает и с DX, и с OGL. Рапространяется вместе с исходниками. Написан на cpp. Посмотри на его иерархию - может найдешь что-то полезное.
11K
22 ноября 2007 года
coolcoder
39 / / 14.08.2006
В таком случае не бодрее ли смотреть на Source Engine, например? Но это я так, в шутку. Пока делаю потихоньку, в мозгах думаю. Если что напишу - дам поглядеть.
11K
28 декабря 2007 года
coolcoder
39 / / 14.08.2006
Не, сорсовый движок, по-моему, плохо подходит, ибо я всегда был против всяческих надстроек и выступал за их сведение к минимуму. С этой же точки зрения мне не подходит ни один готовый двиг.
11K
28 декабря 2007 года
coolcoder
39 / / 14.08.2006
Предлагаю всем, кто располагает какой-либо информацией о принципах организации игрового двига и игрового цикла, выкладывать инфу сюда либо делиться ссылками.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог