Nesneye Dayalı OpenGL


12

Bir süredir OpenGL kullanıyorum ve çok sayıda öğretici okudum. Birçoğunun hala sabit boru hattını kullanmasının yanı sıra, genellikle tüm başlatma, durum değişiklikleri ve çizimi tek bir kaynak dosyaya atarlar. Bu, bir öğreticinin sınırlı kapsamı için iyidir, ancak tam bir oyuna nasıl ölçeklendirileceğini anlamakta zorlanıyorum.

OpenGL kullanımınızı dosyalara nasıl böldünüz? Kavramsal olarak, mesela, tamamen ekrana bir şey yapan bir oluşturma sınıfına sahip olmanın faydalarını görebiliyorum, ancak gölgelendiriciler ve ışıklar gibi şeyler nasıl çalışır? Işıklar ve gölgelendiriciler gibi şeyler için ayrı sınıflarım olmalı mı?


1
Dışarıda açık kaynak oyunları ve daha fazla koda sahip daha büyük öğreticiler var. Bazılarını kontrol edin ve kodun nasıl düzenlendiğini görün.
MichaelHouse

Motorları oluşturma konusunda yeni mi başlıyorsunuz?
Samaursa

Bu soru, kapsamı daraltmadan makul bir şekilde cevaplanamaz. Ne inşa etmeye çalışıyorsun? Ne tür bir oyun, ne tür grafikleri var, vb?
Nicol Bolas

1
@Sullivan: "Bu tür kavramların neredeyse her oyuna uygulanacağını düşündüm." Yapmazlar. Benden Tetris yapmamı istersen, büyük bir ambalaj katmanı ya da OpenGL'nin etrafında bir şey yapmaya zahmet etmeyeceğim. Doğrudan kullanın. Benden Mass Effect gibi bir şey yapmamı istersen, oluşturma sistemimizin etrafında birden fazla soyutlama katmanına ihtiyacımız olacak. Unreal motorunu Tetris'e atmak, sinek avlamak için bir av tüfeği kullanıyor; görevi doğrudan elle kodlamaktan çok daha zor hale getirir. Yalnızca büyük ve siz bir sistemin karmaşık olarak inşa etmeliyiz ihtiyaç ve hiçbir büyük.
Nicol Bolas

1
@Sullivan: Sorunuzun tek karmaşıklığı, birden fazla dosyaya bölme hakkında konuştuğunuz yer. Bu Tetris'de bile yapacağım bir şey. Ve Tetris ve Unreal motoru arasında birçok karmaşıklık seviyesi var. Yine: hangisini soruyorsun?
Nicol Bolas

Yanıtlar:


6

Bence OO OpenGL o kadar da gerekli değil. Gölgelendirici, model vb. Sınıf hakkında konuştuğunuzda farklıdır.

Temel olarak önce oyun / motor başlatma (ve diğer şeyler) yapardınız. Daha sonra dokuları, modelleri ve gölgelendiricileri RAM'e (gerekirse) ve Arabellek Nesnelerine yükleyebilir ve gölgelendiricileri yükleyebilir / derleyebilirsiniz. Bundan sonra, veri yapınızda veya gölgelendirici sınıfınızda, modelde gölgelendiricilerin, model ve doku tampon nesnelerinin int kimlikleri vardır.

Bence çoğu motorun motor bileşenleri vardır ve hepsinin belirli arayüzleri vardır. İncelediğim tüm motorlar Renderer veya SceneManager veya her ikisi gibi bazı bileşenlere sahiptir (oyunun / motorun karmaşıklığına bağlıdır). Bundan sonra OpenGLRenderer sınıfına ve / veya Renderer arabirimini uygulayan DXRenderer'a sahip olabilirsiniz. Daha sonra SceneManager ve Renderer'ınız varsa aşağıdakilerden bazılarını yapabilirsiniz:

  • Traverse SceneManager ve her nesneyi göndermek Oluşturucu oluşturma için
  • Bazı SceneManager yönteminde büyük harfe kapsülleme
  • Gönder SceneManager için Oluşturucu bunu kolları böylece

Renderer muhtemelen oluşan her kafesin çizim fonksiyonunu çağıran nesnenin çizim fonksiyonunu çağırır ve mesh doku nesnesini bağlar, gölgelendiriciyi bağlar, OpenGL çizim fonksiyonunu çağırır ve daha sonra gölgelendiricileri, doku ve nesne veri tamponu nesnelerini kullanır.

NOT: Bu sadece örnektir, SceneManager'ı daha ayrıntılı olarak incelemeniz ve en iyi uygulama seçeneğinin ne olduğunu görmek için kullanım durumunuzu analiz etmeniz gerekir.

Elbette, hem video hem de RAM bellek kullanımı ile ilgilenecek MemoryManager , ResourceLoader vb.Gibi diğer motor bileşenlerine sahip olacaksınız , böylece belirli modelleri / gölgelendiricileri / dokuları gerektiği gibi yükleyebilir / boşaltabilirler. Bunun için kavramlar arasında bellek önbellekleme, bellek haritalama vb. Yer alır.

Diğer oyun motorlarının daha ayrıntılı açıklamasına bir göz atın, birçoğu var ve belgeleri hemen hemen mevcut.

Fakat evet, sınıflar hayatı kolaylaştırır; bunları tamamen kullanmalı ve kapsülleme, kalıtım, arayüzler ve daha havalı şeyleri hatırlamalısınız.


Aradığım cevap buydu. Ancak, “... dokuları, modelleri ve gölgelendiricileri RAM'e (gerekirse) ve Arabellek Nesnelerine yükle ve gölgelendiricileri yükle / derle ...” dediğinizde, beni orijinal soruma geri getiriyor; modeller ve gölgelendiriciler gibi şeyleri kapsüllemek için nesneleri kullanmalı mıyım?
Sullivan

nesne bir sınıf örneğidir ve 'bunları tamamen kullanmalısınız'.
edin-m

Üzgünüm, 'nesneleri nasıl kullanmalıyım' diye sormak istedim. Benim hatam.
Sullivan

Sınıf tasarımınıza bağlıdır. Bazı temel örnekler sezgisel olacaktır, örneğin: object3d (sınıf) mesh (sınıf); her kafesin malzemesi (sınıfı) vardır; her malzeme dokuya (sınıf veya sadece id olabilir) ve gölgelendiriciye (sınıf) sahiptir. Ancak her bileşen hakkında okuduğunuzda, SceneManager, Renderer, MemoryManager yapmak için farklı ama eşit yaklaşımlar göreceksiniz (bunların hepsi tek sınıf veya birden fazla, devralınan vb. Olabilir). Bu konu üzerine onlarca kitap yazılmıştır (oyun motoru mimarisi) ve soruyu ayrıntılı olarak cevaplamak için bir kişi yazabilir.
edin-m

Sanırım alacağım en iyi cevap bu. Yardımınız için teşekkür ederiz :)
Sullivan

2

OpenGL'de zaten bazı 'Nesne' kavramları var.

Örneğin, kimliği olan herhangi bir şey bir nesne olarak geçebilir (Özellikle 'Nesneler' olarak adlandırılan şeyler de vardır). Tamponlar, Dokular, Köşe Tampon Nesneleri, Köşe Dizi Nesneleri, Çerçeve Tampon Nesneleri vb. Küçük bir çalışma ile sınıfları çevreleyebilirsiniz. Bağlamınız uzantıları desteklemiyorsa, eski kullanımdan kaldırılmış OpenGL işlevlerine geri dönmenin kolay bir yolunu da sunar. Örneğin, bir VertexBufferObject glBegin (), glVertex3f () vb. Kullanmaya geri dönebilir.

Geleneksel OpenGL kavramlarından uzaklaşmanız gerekebilecek birkaç yol vardır, örneğin muhtemelen arabellek nesnelerine arabelleklerle ilgili meta verileri depolamak istersiniz. Örneğin, arabellek köşeleri saklıyorsa. Köşelerin formatı nedir (yani konum, normaller, metin kartları vb.). Hangi ilkelleri kullanır (GL_TRIANGLES, GL_TRIANGLESTRIP, vb ...), boyut bilgisi (kaç şamandıra saklanır, kaç üçgen temsil eder, vb ...). Bunları çizim dizileri komutlarına takmayı kolaylaştırmak için.

OGLplus'a bakmanızı tavsiye ederim . OpenGL için C ++ bağlamaları.

Ayrıca glxx , bu sadece uzantı yükleme için.

OpenGL API'sini kaydırmanın yanı sıra, biraz daha yüksek bir seviye oluşturmaya da bakmalısınız.

Örneğin, tüm gölgelendiricilerinizden yükleyen ve kullanan bir malzeme yöneticisi sınıfı. Ayrıca, mülklerin kendilerine aktarılmasından da sorumlu olacaktır. Bu şekilde arayabilirsiniz: material.usePhong (); material.setTexture (sometexture); material.setColor (). Bu, gölgelendiricilerinizin 1 blokta kullandığı tüm özellikleri içeren 1 büyük tampona sahip olmak için paylaşılan tek biçimli tampon nesneleri gibi daha yeni şeyleri kullanabileceğiniz için daha fazla esneklik sağlar, ancak desteklenmiyorsa her bir gölgelendirici programına yüklemeye geri dönersiniz. 1 büyük monolitik gölgelendiriciye sahip olabilir ve destekleniyorsa tek tip rutinleri kullanarak farklı gölgelendirici modelleri arasında geçiş yapabilir veya bir grup farklı küçük gölgelendiriciyi kullanmaya geri dönebilirsiniz.

Gölgelendirici kodunuzu yazmak için GLSL özelliklerinden harcamalara da bakabilirsiniz. Örneğin #include, gölgelendirici yükleme kodunuza inanılmaz derecede kullanışlı ve uygulanması çok kolay olacaktır (bunun için bir ARB uzantısı da vardır). Kodunuzu, hangi uzantıların desteklendiğine bağlı olarak anında oluşturabilirsiniz, örneğin paylaşılan bir tek tip nesne kullanın veya normal üniformaları kullanmaya geri dönün.

Son olarak, sahne grafikleri, özel efektler (bulanıklık, parıltı), gölgeler, aydınlatma ve benzeri çoklu işleme geçişleri gerektiren şeyleri yapan daha yüksek düzeyli bir oluşturma hattı API'si isteyeceksiniz. Ve dahası, grafik API ile hiçbir ilgisi olmayan ama sadece bir dünyadaki nesnelerle ilgilenen bir oyun API'sı.


2
"OGLplus'a bakmanızı tavsiye ederim. OpenGL için C ++ bağlamaları." Buna karşı tavsiye ederim . RAII'yi seviyorum, ancak çoğu OpenGL nesnesi için tamamen uygunsuz. OpenGL nesneleri genel bir yapı ile ilişkilidir: OpenGL bağlamı. Bu nedenle, bir bağlama sahip olana kadar bu C ++ nesnelerini oluşturamazsınız ve içerik zaten yok edilmişse bu nesneleri silemezsiniz. Ayrıca, küresel durumu değiştirmeden nesneleri değiştirebileceğiniz yanılsamasını verir . Bu bir yalan (EXT_DSA kullanmadığınız sürece).
Nicol Bolas

@NicolBolas: Bir bağlam olup olmadığını kontrol edip sadece başlatabilir miyim? Ya da sadece yöneticilerin OpenGL bağlamı gerektiren nesneleri yaratmasına izin verebilir misiniz? --- btw, harika bir dizi öğretici (profilinizdeki bağlantı)! Her nasılsa, OpenGL / Graphics'i ararken onlara hiç rastlamadım.
Samaursa

@Samaursa: Hangi amaçla? OpenGL nesneleri için bir yöneticiniz varsa, o zaman ... gerçekten nesnelerin kendilerine bakmasına gerek yoktur; yönetici onlar için yapabilir. Bunları yalnızca bir bağlam mevcut olduğunda başlatırsanız, düzgün şekilde başlatılmamış bir nesneyi kullanmaya çalışırsanız ne olur? Sadece kod tabanınızda kırılganlık yaratır. Ayrıca, küresel nesnelere dokunmadan bu nesneleri değiştirme yeteneği hakkında söylediğim hiçbir şeyi değiştirmez.
Nicol Bolas

@NicolBolas: "bir bağlam olana kadar bu C ++ nesneleri oluşturamazsınız" ... bu çıplak OpenGL yapıları kullanmaktan farklı mıdır? Gözlerimde, oglplus::Contextsınıf bu bağımlılığı son derece görünür kılıyor - bu bir sorun olur mu? Yeni OpenGL kullanıcılarının birçok problemden kaçınmasına yardımcı olacağına inanıyorum.
xtofl

1

Modern OpenGL'de, oluşturulmuş nesneyi farklı vaos ve gölgelendirici programları kullanarak neredeyse tamamen birbirinden ayırabilirsiniz. Ve bir nesnenin uygulanması bile birçok soyutlama katmanına ayrılabilir.

Örneğin, bir arazi uygulamak istiyorsanız, yapıcısı arazinin köşe noktalarını ve dizinlerini oluşturan ve bunları dizi arabelleklerine ayarlayan bir TerrainMesh tanımlayabilirsiniz ve - bir özellik konumu verirseniz verilerinizi gölgelendirir. Ayrıca, nasıl oluşturulacağını da bilmeli ve oluşturmayı ayarlamak için yaptığı tüm bağlam değişikliklerini geri almaya özen göstermelidir. Bu sınıfın kendisi onu gerçekleştirecek olan gölgelendirici programı hakkında hiçbir şey bilmemeli ve sahnedeki diğer nesneler hakkında hiçbir şey bilmemelidir. Bu sınıfın üstünde gölgelendirici kodunun farkında olan bir Arazi tanımlayabilirsiniz ve görevi gölgelendirici ve TerrainMesh arasında bağlantı oluşturmaktır. Bu, nitelik ve üniform konumlar elde etmek ve dokularda yükleme ve bunun gibi şeyler anlamına gelmelidir. Bu sınıf, arazinin nasıl uygulandığı, hangi LoD algoritmasını kullandığı hakkında hiçbir şey bilmemelidir, sadece araziyi gölgelendirmekten sorumludur. Bunun üstünde, behivour ve çarpışma algılama gibi OpenGL olmayan işlevleri tanımlayabilirsiniz.

Bu noktaya gelindiğinde, OpenGL düşük seviyeli olarak kullanılmak üzere tasarlanmış olsa da, yine de gerçek dışı bir oyun boyutuna sahip uygulamalara ölçeklendirmenize izin veren bağımsız soyutlama katmanları oluşturabilirsiniz. Ancak istediğiniz / ihtiyacınız olan katman sayısı gerçekten istediğiniz uygulamanın boyutuna bağlıdır.

Ama bu boyut hakkında kendinize yalan söyleme, 10k hat uygulamasında Unity'nin nesne modelini taklit etmeye çalışma, sonuç tam bir felaket olacaktır. Katmanları kademeli olarak oluşturun, sadece gerektiğinde soyutlama katmanlarının sayısını artırın.


0

ioDoom3 muhtemelen harika bir başlangıç ​​noktasıdır, çünkü harika kodlama uygulamalarını takip etmek için Carmack'e güvenebilirsiniz. Ayrıca Doom3'te megatexturing kullanmadığına inanıyorum, bu yüzden bir render borusu olarak nispeten düz.


6
"Harika kodlama uygulamalarını takip etmek için Carmack'e güvenebileceğinizden" Oh adamım, bu iyi bir soru. Carmack harika C ++ kodlama uygulamasını takip eder. Bu bir isyan! Oh ... şaka yapmıyordun. Um ... hiç onun koduna baktın mı? O bir C programcısı ve böyle düşünüyor. Hangi C için iyi, ama soru C ++ hakkında .
Nicol Bolas

C arka planından geldim, bu yüzden kodu bana çok mantıklı geliyor: P ve evet, deprem tabanlı oyunlar üzerinde biraz zaman harcadı.
chrisvarnz
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.