forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Проекты C++ (http://forum.boolean.name/forumdisplay.php?f=56)
-   -   [TrueHorror] - разработка (http://forum.boolean.name/showthread.php?t=17293)

mr.DIMAS 08.01.2014 22:23

Ответ: [TrueHorror] - разработка
 
Цитата:

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


Немного посидев на юнити, привык к подобному использованию объектов гуи, типа кнопок и прочего.

Код:

if( Button( blablabla ) == blablabla )
{
    do_smth
}

типа нигде не создаем объект у себя в коде скрипта.

и немного все прикинув, сделал у себя в двиге также.

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

Правильно ли я уловил идею что используют в юнити?

Samodelkin 09.01.2014 00:54

Ответ: [TrueHorror] - разработка
 
Цитата:

Это добавляет оверхеда в виде функций связок( luaBind не предлагать ). Я решил обособить движок чтобы игру саму писать на си++, ибо со скриптами геморроя дофига.
Так может сразу на ассемблере? Уж лучше будет небольшой оверхед исполнения программы чем оверхед работы программиста/разработчика. Это очевидно что чем выше абстракция и чем эта абстракция нативнее по отношению к мыслительным процессам людей - тем лучше. Писать игру на с++ - потратишь столько же времени сколько и на создание движка и проблем будет не меньше. А потом это всё может оказаться неприспособленным к последующему проекту и всё придется делать сначала.

Думай в первую очередь о простоте кода, ты его для людей пишешь, а не для компьютеров. А для оптимизации выполнения будет достаточно критические участки грамотно написать - это меньше 5% кода наверняка.

pax 09.01.2014 00:58

Ответ: [TrueHorror] - разработка
 
Цитата:

Сообщение от mr.DIMAS (Сообщение 271748)
На скринах можно заметить z fighting. Сразу вопрос как в ДХ 9 его убрать?

везде он убирается чаще всего уменьшением разницы между near и far камеры. Не стоит ставить их к примеру 0.001 и 10000, лучше 0,01 и 1000 ну и меньше лучше. В некоторых случаях лучше использовать две камеры, одна для заднего плана, вторая для переднего (которая выполняет очистку только буфера глубины).

Samodelkin 09.01.2014 01:30

Ответ: [TrueHorror] - разработка
 
Цитата:

В некоторых случаях лучше использовать две камеры, одна для заднего плана, вторая для переднего (которая выполняет очистку только буфера глубины).
Не совсем понятно. Есть примеры использования?

pax 09.01.2014 07:22

Ответ: [TrueHorror] - разработка
 
Цитата:

Сообщение от Samodelkin (Сообщение 272298)
Не совсем понятно. Есть примеры использования?

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

SBJoker 09.01.2014 11:43

Ответ: [TrueHorror] - разработка
 
Цитата:

Сообщение от pax (Сообщение 272311)
К примеру в космосиме можно планеты рендерить отдельной камерой, а корабли своей, рассчитанной на близкое расстояние. В общем применимо когда задний план расположен далеко и выполнен не скайбоксом.

Интересно при этом было бы посмотреть на метод объединения таких рендеров без ошибок сортировок между планетами и кораблями.

Samodelkin 09.01.2014 12:17

Ответ: [TrueHorror] - разработка
 
Цитата:

Сообщение от SBJoker (Сообщение 272315)
Интересно при этом было бы посмотреть на метод объединения таких рендеров без ошибок сортировок между планетами и кораблями.

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

mr.DIMAS 09.01.2014 19:16

Ответ: [TrueHorror] - разработка
 
Цитата:

Сообщение от Samodelkin (Сообщение 272296)
Так может сразу на ассемблере? Уж лучше будет небольшой оверхед исполнения программы чем оверхед работы программиста/разработчика. Это очевидно что чем выше абстракция и чем эта абстракция нативнее по отношению к мыслительным процессам людей - тем лучше. Писать игру на с++ - потратишь столько же времени сколько и на создание движка и проблем будет не меньше. А потом это всё может оказаться неприспособленным к последующему проекту и всё придется делать сначала.

Думай в первую очередь о простоте кода, ты его для людей пишешь, а не для компьютеров. А для оптимизации выполнения будет достаточно критические участки грамотно написать - это меньше 5% кода наверняка.

Воу воу паринь палехчи.

Дело в том что я уже попробовал писать игру на скриптах. Для этого я завернул все функции движка в луа-обертки, и получилось так что я пишу всю игру на луа. То есть в экзешнике запускается луа виртуальная машина и все выполняется на ней. Но блин, какой смысл писать на луа, когда то же можно написать на си? Гибкость изменения скриптов без перекомпиляции? Сейчас, когда движок отделен от игры, скорость компиляции+линковки игровой части 0,57 сек. Кароч приведи весомые аргументы использования скриптов в маленьком игровом проекте.

По поводу опций компилятора. Нужно ли для движка выключить поддержку исключений( в движке не использую их )? Тут довольно хорошие доводы в пользу отключения .

Samodelkin 09.01.2014 22:51

Ответ: [TrueHorror] - разработка
 
Цитата:

По поводу опций компилятора. Нужно ли для движка выключить поддержку исключений( в движке не использую их )? Тут довольно хорошие доводы в пользу отключения .
2006 год? Сейчас уже С++11 и там хорошие исключения.

Цитата:

Дело в том что я уже попробовал писать игру на скриптах. Для этого я завернул все функции движка в луа-обертки, и получилось так что я пишу всю игру на луа. То есть в экзешнике запускается луа виртуальная машина и все выполняется на ней. Но блин, какой смысл писать на луа, когда то же можно написать на си? Гибкость изменения скриптов без перекомпиляции? Сейчас, когда движок отделен от игры, скорость компиляции+линковки игровой части 0,57 сек. Кароч приведи весомые аргументы использования скриптов в маленьком игровом проекте.
Первый движок я делал как по образу интерфейсов dxsdk так и opengl. Главные две ошибки были в том что:
1. Я пытался сделать универсальный движок.
2. Как следствие пытался сделать максимально гибкий API.

ИМХО, проблема заключалась в неправильном понимании движка. Я его считал еще одним уровнем абстракции и обобщения более низкоуровневого функционала. На самом деле движок должен выполнять более конкретные задачи. Сейчас я считаю что делать универсальный движок в корне неверное решение - для этих целей есть UDK, Unity3D и прочие решения. Лучше определиться с парой-тройкой игр (или одной большой игрой), которые собираешься делать и исходить из того что нужно для этой игры. Не пытаться делать что то еще "на всякий случай" - только то что необходимо. Как следствие отсюда можно легко обнаружить что весь предполагаемый гибкий функционал движка превращается в вполне понятный жесткий последовательный набор действий, для воспроизведения/рендера игровой медии. Таким образом никаких мега гибких API как в тех же библиотеках dxsdk вообще не нужно. Если правильно подобрать набор тулз для запланированных проектов, можно в целом обойтись только ими и минимальными возможностями скриптинга. Для более сложных случаев возможно потребуется написать библиотеку с игровыми кодами.

Для маленького игрового проекта движок не нужен вообще - используй функционал dx напрямую из игровых кодов.

mr.DIMAS 11.01.2014 01:16

Ответ: [TrueHorror] - разработка
 
Появился вопрос про правильную организацию рендеринга. Алгоритм описывать долго, поэтому код( unordered_map<IDirect3DTexture9*,vector<Mesh*>> g_meshes )

Код:

for( auto groupIterator = g_meshes.begin(); groupIterator != g_meshes.end(); ++groupIterator )
    {
      IDirect3DTexture9 * texture = groupIterator->first;
      auto & meshes = groupIterator->second;

      g_device->SetTexture( 0, texture );

      g_textureChanges++;

      for( auto meshIterator = meshes.begin(); meshIterator != meshes.end(); ++meshIterator )
      {
        Mesh * mesh = *meshIterator;
        SceneNode * node = mesh->parent;

        if( !IsMeshVisible( mesh )) // frustum cull
          continue;
        if( !node->visible )
          continue;
        if( node->parent )
          if( !node->parent->visible )
            continue;
        if( !mesh->ib )
          continue;
        if( !mesh->vb )
          continue;

        D3DXMATRIX world; GetD3DMatrixFromBulletTransform( node->globalTransform, world );
        g_device->SetTransform( D3DTS_WORLD, &world );
        g_lightShader->vsc->SetMatrix( g_device, g_lightShader->vWorld, &world );   
        g_device->SetStreamSource( 0, mesh->vb, 0, sizeof( Vertex ));
        g_device->SetIndices( mesh->ib ); 

        g_device->SetRenderState ( D3DRS_ALPHABLENDENABLE, FALSE );

        // draw mesh with each light
        for( size_t j = 0; j < g_lights.size(); j++ )
        {
          Light * light = g_lights.at( j );       

          SetLightShaderFor( light );         

          if( !LightIntersectsMesh( mesh, light ))
            continue;   

          g_device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, mesh->vertexCount, 0, mesh->faceCount );

          g_dips++;

          if( j == 0 )
          {
            g_device->SetRenderState ( D3DRS_ALPHABLENDENABLE, TRUE );
            g_device->SetRenderState ( D3DRS_SRCBLEND, D3DBLEND_ONE );
            g_device->SetRenderState ( D3DRS_DESTBLEND, D3DBLEND_ONE );
          }
        }     
      }

Немного про алгоритм всё таки напишу. При добавлении меша в рендерер, он помещается в соответствующую группу с определенной текстурой - таким образом можно избежать подобной отрисовки

Код:

g_device->SetTexture( 0, A );
g_device->DrawPrimitive( ... );
g_device->SetTexture( 0, B );
g_device->DrawPrimitive( ... );

То есть сортируем меши по текстуре.

Каждый меш отрисовываем всеми источниками света с аддитивным блендингом.

Есть какие либо замечания\поправки\баги в алгоритме?

Samodelkin 11.01.2014 02:40

Ответ: [TrueHorror] - разработка
 
Группировать по текстуре, шейдерам, эффектам это правильно. Но вот рисовать что-то более одного раза без особой на то причины - странно. Нельзя заранее определить какие источники света действуют на примитив и список с ними передать в пиксельный шейдер, который сразу сложит результат яркости для каждого пикселя? Еще посмотри deferred shading - необязательно сразу освещение целиком в screen space переводить, но кое что оттуда можно полезное взять, например методы локализации источников света.

mr.DIMAS 11.01.2014 13:49

Ответ: [TrueHorror] - разработка
 
Цитата:

Но вот рисовать что-то более одного раза без особой на то причины - странно.
Код:

if( !LightIntersectsMesh( mesh, light ))
            continue;

Определяет пересечение ограничивающей сферы у света и AABB у меша.
Цитата:

Нельзя заранее определить какие источники света действуют на примитив и список с ними передать в пиксельный шейдер, который сразу сложит результат яркости для каждого пикселя?
Тоесть ты предлагаешь написать шейдер который будет принимать N количество источников света, а а в данный момент времени будут использоваться M? У меня раньше такой шейдер был, но там в любом случае на объект действовало 6 источников даже если их не существовало.

Mr_F_ 11.01.2014 13:50

Ответ: [TrueHorror] - разработка
 
Цитата:

Нельзя заранее определить какие источники света действуют на примитив и список с ними передать в пиксельный шейдер, который сразу сложит результат яркости для каждого пикселя?
Можно, но зато с мультипасс подходом можно каждый пасс куллить стенсилом. Хотя при скорости арифметики нынешних видях, это не даст особо профита. Другое дело - если в радиусе лайта надо семплить тень с каким-нибудь тяжёлым PCFом, но тоже не факт что динамик бранчинг по радиусу тут будет чем-то хуже стенсила.

Samodelkin 11.01.2014 17:50

Ответ: [TrueHorror] - разработка
 
Цитата:

Тоесть ты предлагаешь написать шейдер который будет принимать N количество источников света, а а в данный момент времени будут использоваться M? У меня раньше такой шейдер был, но там в любом случае на объект действовало 6 источников даже если их не существовало.
Да, 4-6 источников достаточно. Если их меньше чем в шейдере то просто заполняй нулями яркость оставшихся, а в функции шейдера которая их считает просто сделай условие, если сила источника == 0, то он сразу отбрасывается.

Цитата:

Определяет пересечение ограничивающей сферы у света и AABB у меша.
Ну вот нормально, можешь в редакторе карты еще сделать доп. функцию которая проверяет на одновременное пересечение более 6 источников света, чтобы мэперочел более равномерно источники расставлял.

mr.DIMAS 11.01.2014 17:53

Ответ: [TrueHorror] - разработка
 
Цитата:

Сообщение от Samodelkin (Сообщение 272401)
Да, 4-6 источников достаточно. Если их меньше чем в шейдере то просто заполняй нулями яркость оставшихся, а в функции шейдера которая их считает просто сделай условие, если сила источника == 0, то он сразу отбрасывается.

Уже сделал. На тестовой сцене со старым шейдером и алгоритмом отрисовки было 350 дипов максимум. сейчас максимум 100. epic win


Часовой пояс GMT +4, время: 04:47.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot