Агностичні мости API (тобто OpenGL / D3D / Що б там не було). Чи використовуєте ви їх, як їх виготовляєте. Про і Кон у [закрито]


12

Ви робите 3d двигун. Вам хочеться найкращого з багатоплатформних світів. Раптом ви зрозумієте, що якщо ви хочете використовувати Direct3D на машинах Windows та OpenGL на OSX / Linux, вам доведеться пожертвувати підтримуваними функціями як найменш загального знаменника.

Деякі можуть використовувати OpenGL через три ОС ', оскільки він, мабуть, є найменш загальним знаменником сам по собі. Все добре. Тоді вам потрібно перенести графічний інтерфейс API в GX Nintendo, ви також повинні зробити шлях PS3 та Xbox360.

Що ти робиш? Ви розробляєте свій власний API, який є найменш загальним знаменником сам по собі і виписуєте його допоміжні реалізації для кожної платформи, або ви пишете для кожної платформи свою власну гілку?

Якщо ви вирішили створити власний API, чи використовуєте ви шаблон моста чи власний вуду? Де зупиняється божевілля, де ти усвідомлюєш усе, і підхід до кухонної мийки повинен припинитися, і ти, як правило, маєш окремий двигун для кожної платформи як галузь. Або ви дотримуєтесь всього та кухонної мийки та зберігаєте специфіку платформи у спеціалізаціях, що стосуються модулів для кожної платформи.

Відповіді:


9

Я не прихильник найменш поширеного підходу до знаменника. Якщо ви це зробите, у вас можуть виникнути каліки та низькі показники.

Натомість те, що я робив у минулому, - це забезпечити функціонування трохи більш високого рівня в бібліотеці. Ця бібліотека є (в основному) API агностиком і може використовуватися в будь-якому місці, але реалізація бібліотеки є абсолютно різною для різних платформ / графічних програм. Так, наприклад, замість функції SetStateX () у вас є більш високі функції, такі як RenderMesh () або CreateRenderTarget ().

Це буде більше роботи, ніж дійсно тонкий шар щоразу, коли ви переходите на нову платформу, але це цілком варто того, тому що ви зможете реалізувати речі оптимальним чином для цієї платформи, і ви зможете взяти перевага рідних, унікальних особливостей.

Ще одне: не бійтеся трохи порушити інкапсуляцію. Немає нічого страшнішого в тому, щоб знати, що ти знаходишся на платформі з певними можливостями і не в змозі ними користуватися. Залишити задній простір такого роду, щоб код вищого рівня може скористатися платформою, дуже корисно (наприклад, можливість отримати пристрій D3D або контекст OpenGL).


3
Я думаю, ви сказали те, що я намагався сказати, тільки краще.
AShelly

6

Все, що я можу сказати, - подивіться на Ogre3D . Він написаний на C ++, з відкритим кодом (ліцензія на MIT зараз) і працює на будь-якій великій платформі. Він абстрагує api-рендерінг і може переключитися з використання DirectX на OpenGL лише за допомогою декількох налаштувань. Однак я недостатньо знаю про відмінності між наборами функцій DirectX і OpenGL, щоб сказати, що вона робить або не підтримує певну функцію.

Torchlight від Runic Games був написаний за допомогою Ogre, і я грав це на Mac і ПК, і він працює дуже добре на обох.


2
+1 для підходу Огре. Я знаю про це, прочитав частину коду. Мені було більше цікаво почути особисті історії про підхід, хоча і що інші люди роблять у такій ситуації.
Ключовий кадр

2
Дякую! Ну, я б зробив це здебільшого так, як це зробив Огре. Я використовував підхід «Інтерфейс / Фабрика» у багатьох розробках крос-платформ, і я фактично не впевнений, як би це зробив інакше. Я б сказав, що вам абсолютно потрібно працювати на декількох платформах одночасно. Не намагайтеся кодувати все в Windows, а не намагайтеся, наприклад, передати порт на Mac.
Кейсі

Так! Мені стало дуже набридло прокручувати власну перехресну API-обгортку, і тоді я просто почав використовувати Ogre. Не озирнувся. :)
jacmoe

1

Я цього не робив для графіки, але створив міжплатформенний аудіоінструмент (PC / XBOX / PS2). Ми пішли шляхом створення власного API з можливостями найменшого загального знаменника, а також додатковими можливостями платформи. Ось кілька засвоєних уроків:

Ключ полягає у визначенні шляху обробки, який інкапсулює основні можливості кожної платформи та дозволяє рости. Для цього вам потрібно зрозуміти API низького рівня кожної платформи, щоб ви могли визначити правильні абстракції. Переконайтесь, що ланцюжок працює на найменш здатній платформі, забезпечуючи при цьому доступ до вдосконалених функцій наймобільнішої форми. Зробіть роботу, щоб виправити це, і ви заощадите багато зусиль пізніше.

Для звуку ланцюжок був чимось на кшталт SoundSources -> [Decoders] -> Buffers -> [3D Positioner] ->[Effects] -> Players.

Для графіки це може бути Model -> Shapes -> Positioner -> Texturer -> [Lighting] -> [Particle Effects] -> Renderer. (Це, мабуть, зовсім неправильний набір, я не графік).

Напишіть інтерфейсний API, який обробляє основні об'єкти, і задній кінець, орієнтований на платформу, який відображає API для можливостей низького рівня. Забезпечте найкращі зусилля для кожної можливості. Наприклад, на ПК та XBOX 3D-позиціонування аудіо було зроблено з використанням HRTF можливостей звукових мікросхем, в той час як PS2 використовував просту панораму і зникає. Графічний двигун може зробити щось подібне із освітленням.

Реалізуйте якомога більше переднього кінця за допомогою нейтрального коду платформи. Код для приєднання об'єкта реверберації до звукового об'єкта або текстурного об’єкта до об’єкта форми повинен бути повністю поширеним, як і код для перетворення та обробки активних об'єктів. З іншого боку, об'єкти низького рівня можуть бути повністю платформенними, за винятком загального інтерфейсу.

Переконайтеся, що API або файли конфігурації дозволяють користувачеві вказувати параметри, що стосуються платформи. Ми намагалися уникнути виштовхування коду для платформи на рівень гри, зберігаючи його у файлах конфігурації: Конфігураційний файл однієї платформи може вказати "ефект: SuperDuperParticleGenerator", а інший каже "ефект: SoftGlow"

Однозначно розробляти платформи паралельно. Переконайтесь, що конкретні інтерфейси платформи чітко визначені та перевірені самостійно. Це перешкоджає великій кількості "це рівень платформи чи API?" проблеми при налагодженні.


0

Я пишу ігровий движок з відкритим кодом під назвою YoghurtGum для мобільних платформ (Windows Mobile, Android). Це була одна з моїх великих проблем. Спочатку я вирішив це так:

class RenderMethod
{

public:

  virtual bool Init();
  virtual bool Tick();
  virtual bool Render();

  virtual void* GetSomeData(); 

}

Ви помітили це void*? Це тому, що RenderMethodDirectDrawповертає поверхню DirectDraw, а RenderMethodDirect3Dповертає пул вершин. Все інше також розкололося. У мене був Spriteклас, який мав або SpriteDirectDrawвказівник, або SpriteDirect3Dвказівник. Це свого роду смоктало.

Тому останнім часом я багато переписував речі. Що я маю зараз - це RenderMethodDirectDraw.dllі є RenderMethodDirect3D.dll. Насправді ви можете спробувати використовувати Direct3D, відмовитися та використовувати DirectDraw замість цього. Це тому, що API залишається тим самим.

Якщо ви хочете створити спрайт, ви робите це не безпосередньо, а через завод. Потім фабрика викликає правильну функцію в DLL і перетворює її в батьківську.

Отже, це в RenderMethodAPI:

virtual Sprite* CreateSprite(const char* a_Name) = 0;

І це визначення в RenderMethodDirectDraw:

Sprite* RenderMethodDirectDraw::CreateSprite(const char* a_Name)
{
    bool found = false;
    uint32 i;
    for (i = 0; i < m_SpriteDataFilled; i++)
    {
        if (!strcmp(m_SpriteData[i].name, a_Name))
        {
            found = true;
            break;
        }
    }

    if (!found) 
    {
        ERROR_EXPLAIN("Could not find sprite named '%s'", a_Name);
        return NULL; 
    }

    if (m_SpriteList[m_SpriteTotal]) { delete m_SpriteList[m_SpriteTotal]; }
    m_SpriteList[m_SpriteTotal] = new SpriteDirectDraw();

    ((SpriteDirectDraw*)m_SpriteList[m_SpriteTotal])->SetData(&m_SpriteData[i]);

    return (m_SpriteList[m_SpriteTotal++]);
}

Сподіваюся, це має сенс. :)

PS Я хотів би використовувати STL для цього, але немає підтримки на Android. :(

В основному:

  • Зберігайте кожен рендер у власному контексті. Або DLL, або статична бібліотека, або просто купа заголовків. Поки у вас є RenderMethodX, SpriteX і StuffX, ви золоті.
  • Вкрасти, як можна більше, від джерела Огре.

EDIT: Так, має сенс мати такі віртуальні інтерфейси. Якщо ваша перша спроба не вдалася, ви можете спробувати інший метод візуалізації. Таким чином, ви можете зберегти весь метод надання коду агностичним.


1
Чи справді має сенс мати віртуальний інтерфейс, якщо ви ніколи не будете мати більше, ніж одну реалізацію одночасно?
NocturnDragon

0

Мені подобається використовувати для цього SDL . У нього є вікні рендерінгу для D3D, OpenGl, OpenGL ES, і кілька інших певних платформних програм, і він доступний для всіляких різних платформ, і в даний час перебуває в активному розвитку, з прив’язками до багатьох різних мов.

Він абстрагує різні концепції рендерінгу та робить створення відео (а також обробку звуку та введення та кілька інших речей) доступним у простому, платформенному API. І його розробив Сем Лантінга, один із провідних розробників компанії Blizzard, спеціально для того, щоб полегшити перенесення ігор та створити кросплатформові ігри, тому ви знаєте, що маєте справу з високоякісною бібліотекою.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.