API agnostik köprüleri (ör. OpenGL / D3D / Whatever). Onları nasıl kullanıyorsunuz? Pro'lar ve Con'lar [kapalı]


12

Bir 3d motor yapıyorsunuz. Çok platformlu dünyaların en iyisini istiyorsunuz. Birdenbire, Direct3D'yi Windows makinelerinde ve OpenGL'yi OSX / Linux'ta kullanmak istiyorsanız, her ikisinin de desteklenen özelliklerini en az ortak paydaya feda etmeniz gerektiğinin farkına varın.

Bazıları OpenGL'yi üç işletim sisteminde kullanabilirler, çünkü kendi başına en az ortak payda olduğu görülmektedir. Her şey yolunda. Ardından, grafik API'nizin arka ucunu Nintendo'nun GX'ine taşımalısınız, ayrıca bir PS3 ve Xbox360 yolu yapmanız gerekir.

Ne yaparsın? Kendi başına en az ortak payda olan kendi API'nızı tasarlıyor musunuz ve her platform için bunun için arka uç uygulamaları mı yazıyorsunuz yoksa kendi dalı olan her platform için mi yazıyorsunuz?

Kendi API'nızı tasarlamayı seçerseniz, köprü deseni veya kendi voodoo'unuzu mu kullanıyorsunuz? Delilik her şeyin farkına varacağınız yerde durur ve mutfak lavabosu yaklaşımı durmalıdır ve temel olarak her platform için bir şube olarak ayrı motorunuz vardır. Ya da her şeye ve mutfak lavabosuna bağlı kalırsınız ve her platform için arka uç modülü uzmanlıklarında platform özelliklerini saklarsınız.

Yanıtlar:


9

Ben en az ortak payda yaklaşımının hayranı değilim. Bunu yaparsanız, sakat özellikler ve düşük performans elde edebilirsiniz.

Bunun yerine, geçmişte yaptığım şey, bir kütüphanede biraz daha yüksek düzeyde işlevsellik sağlamaktır. Bu kütüphane (çoğunlukla) API agnostiktir ve her yerde kullanılabilir, ancak kütüphanenin uygulanması farklı platformlar / grafik arka uçları için tamamen farklıdır. Örneğin, SetStateX () işlevine sahip olmak yerine, RenderMesh () veya CreateRenderTarget () gibi daha yüksek işlevlere sahipsiniz.

Yeni bir platforma geçtiğinizde gerçekten ince bir katmandan daha fazla iş olacak, ancak tamamen buna değecek, çünkü işleri bu platform için en uygun şekilde uygulayabileceksiniz ve özgün, benzersiz özelliklerin avantajı.

Bir şey daha var: Kapsüllemeyi hafifçe kırmaktan korkmayın. Belirli yeteneklere sahip bir platformda olduğunuzu bilmenin ve onları kullanamamanın daha sinir bozucu bir şey yoktur. Daha yüksek seviyeli kodların platformdan yararlanabilmesi için bir tür arka kapı bırakmak çok faydalıdır (örneğin, D3D cihazını veya OpenGL içeriğini alabilmek).


3
Sanırım söylemeye çalıştığım şeyi söyledin, sadece daha iyi.
AShelly

6

Söyleyebileceğim tek şey Ogre3D'ye bir göz atmak . C ++, Açık kaynak (şimdi MIT Lisansı) ile yazılmıştır ve kutudan çıkan her büyük platformda çalışır. Oluşturma api'sini soyutlar ve DirectX kullanmaktan OpenGL'ye birkaç ayarla geçiş yapabilir. Ancak, DirectX ve OpenGL özellik kümeleri arasındaki farkların belirli bir özelliği desteklemediğini veya desteklemediğini söylemek için yeterli bilgim yok.

Runic Games'in Torchlight'ı Ogre kullanılarak yazıldı ve Mac ve PC'de oynadım ve her ikisinde de çok iyi çalışıyor.


2
Ogre yaklaşımı için +1. Bunu biliyorum, bazı kodları okudum. Yine de yaklaşım ve diğer insanların bu gibi durumlarda ne yaptıkları hakkında kişisel hikayeler duymakla daha fazla ilgilendim.
Anahtar Kare

2
Teşekkürler! Bunu çoğunlukla Ogre'nin yaptığı gibi yapardım. Arayüz / Fabrika yaklaşımını bir çok çapraz platform geliştirmesinde kullandım ve aslında bunu nasıl yapacağımı bilmiyorum. Yine de aynı anda birden fazla platformda çalışmanız gerektiğini söyleyebilirim. Windows'daki her şeyi denemeye ve kodlamaya çalışmayın ve örneğin Mac'e bağlantı kurmaya çalışın.
Casey

Evet! Kendi çapraz API paketleyicimi yuvarlamaktan gerçekten yoruldum ve sonra Ogre'yi kullanmaya başladım. Geriye bakmadım. :)
jacmoe

1

Bunu grafikler için yapmadım, ancak platformlar arası bir ses araç seti (PC / XBOX / PS2) oluşturdum. İsteğe bağlı platforma özel yeteneklerin yanı sıra, en az ortak payda kapasitesine sahip kendi API'mızı oluşturma yoluna gittik. İşte alınan bazı dersler:

Anahtar, her platformun temel yeteneklerini kapsayan ve büyümeye izin veren bir işleme yolu tanımlamaktır. Bunu yapmak için, doğru soyutlamaları tanımlayabilmeniz için her platformun düşük seviye API'sini gerçekten anlamanız gerekir. En yetenekli platformun gelişmiş özelliklerine erişim sağlarken zincirin en az yetenekli platform için çalıştığından emin olun. Bunu doğru yapmak için çalışın ve daha sonra çok çaba sarf edeceksiniz.

Ses için, zincir böyle bir şeydi SoundSources -> [Decoders] -> Buffers -> [3D Positioner] ->[Effects] -> Players.

Grafikler için olabilir Model -> Shapes -> Positioner -> Texturer -> [Lighting] -> [Particle Effects] -> Renderer. (Bu muhtemelen tamamen yanlış bir set, ben grafik adamı değilim).

Temel nesnelerinizi işleyen bir ön uç API ve API'yı düşük düzey yeteneklerle eşleyen platforma özgü bir arka uç yazın. Her yetenek için en iyi çabayı gösterin. Örneğin, PC ve XBOX'ta 3D ses konumlandırma, ses yongalarının HRTF yetenekleri kullanılarak yapıldı, PS2 basit bir kaydırma ve solma kullandı. Bir grafik motoru aydınlatmaya benzer bir şey yapabilir.

Platform nötr koduyla ön ucun mümkün olduğunca fazlasını uygulayın. Bir yankı nesnesini bir ses nesnesine veya şekil nesnesine bir doku varlığına atta etmek için kullanılan kodun, etkin nesneleri yinelemek ve işlemek için olduğu gibi, tamamen yaygın olması gerekir. Diğer yandan, düşük seviyeli nesneler ortak arayüz dışında tamamen platforma özgü olabilir.

API veya yapılandırma dosyalarının kullanıcının platforma özgü seçenekleri belirtmesine izin verdiğinden emin olun. Platforma özel kodu yapılandırma dosyalarında tutarak oyun seviyesine itmekten kaçınmaya çalıştık: Bir platformun yapılandırma dosyası "effect: SuperDuperParticleGenerator" belirtebilirken, diğeri "effect: SoftGlow"

Kesinlikle platformları paralel olarak geliştirin. Platforma özgü arayüzlerin iyi tanımlandığından ve test edilebilir olduğundan emin olun. Bu, "platform düzeyi mi yoksa API düzeyi mi?" hata ayıklama sırasında sorunlar.


0

Mobil platformlar için (Windows Mobile, Android) YoghurtGum adlı açık kaynaklı bir oyun motoru yazıyorum. Bu benim en büyük problemlerimden biriydi. İlk olarak şu şekilde çözdüm:

class RenderMethod
{

public:

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

  virtual void* GetSomeData(); 

}

Sen gördün mü void*? Çünkü bir köşe havuzu döndürürken RenderMethodDirectDrawDirectDraw yüzeyi RenderMethodDirect3Ddöndürür. Diğer her şey de bölünmüştü. İşaretçi ya da işaretçi Spriteolan bir sınıfım vardı . Biraz emdi.SpriteDirectDrawSpriteDirect3D

Son zamanlarda bir çok şeyi yeniden yazıyorum. Şimdi sahip olduğum şey a RenderMethodDirectDraw.dllve a RenderMethodDirect3D.dll. Aslında, Direct3D'yi kullanmayı deneyebilir, başarısız olabilir ve bunun yerine DirectDraw'ı kullanabilirsiniz. Çünkü API aynı kalır.

Bir hareketli grafik oluşturmak istiyorsanız, bunu doğrudan değil, bir fabrika aracılığıyla yapabilirsiniz. Fabrika daha sonra DLL'de doğru işlevi çağırır ve bir üst öğeye dönüştürür.

Yani, bu RenderMethodAPI'da:

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

Ve bu tanım 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++]);
}

Umarım bu mantıklı gelir. :)

PS Bunun için STL kullanmış olmak isterdim, ancak Android'de destek yok. :(

Temelde:

  • Her render'i kendi bağlamında tutun. Bir DLL ya da statik bir kütüphane ya da sadece bir grup üstbilgi. Bir RenderMethodX, SpriteX ve StuffX'iniz olduğu sürece altınsınız.
  • Ogre kaynağından mümkün olduğunca çalın.

EDIT: Evet bunun gibi sanal arayüzlere sahip olmak mantıklı. İlk denemeniz başarısız olursa, başka bir oluşturma yöntemi deneyebilirsiniz. Bu şekilde tüm kod oluşturma yönteminizi agnostik tutabilirsiniz.


1
Aynı anda birden fazla etkinleştirme yapmayacaksanız sanal bir arayüze sahip olmak gerçekten anlamlı mı?
NocturnDragon

0

Bunun için SDL kullanmayı seviyorum . D3D, OpenGl, OpenGL ES ve bir avuç diğer platforma özgü arka uç için oluşturucu arka uçları var ve birçok farklı dile bağlanan her türlü farklı platformda ve şu anda aktif olarak geliştiriliyor.

Farklı oluşturucu kavramlarını soyutlar ve basit, platformlar arası bir API'de video oluşturmayı (ses ve girişi ve birkaç başka şeyi işlemeyi sağlar) kullanılabilir hale getirir. Blizzard'ın önde gelen geliştiricilerinden Sam Lantinga tarafından özel olarak taşıma oyunlarını yapmak ve platformlar arası oyunları daha kolay oluşturmak için tasarlandı, böylece yüksek kaliteli bir kütüphane ile uğraştığınızı biliyorsunuz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.