2D oyunlar ve modern OpenGL


10

Preconcepts

Tamam, şimdiye kadar topladığım şey şu:

  • sabit boru hattı kullanma (kullanımdan kaldırıldı veya kullanımdan kaldırılacak)
  • vbos store "object models" (çoğunlukla n köşe verileri)
  • vaos, verilerin nasıl düzenlendiğini açıklar, böylece çizme çağrıları, her tür vbo'nun ne tür köşe bilgileri için ne olduğunu bilir (bir vao, birden çok vbo'ya başvurabilir, tersi oldukça zordur)
  • her çizim çağrısı ayrıca gölgelendiricilere köşe verileri gönderir

3D'yi nasıl görüyorum (isteğe bağlı)

Bu bilgiler göz önüne alındığında, modern OpenGL ile 3D karmaşık nesneler çizmenin çok güzel olduğunu görebiliyorum. Temel olarak yerel koordinatları olan VBO'lara bir grup nesne modelini (muhtemelen Blender veya diğer benzer yazılımlardan) yüklersiniz ve daha sonra bir nesnenin her örneğine dünya alanına çizmek için farklı bir gölgelendirici parametresi (ofset) sağlarsınız.

Sorun / soru

2B'de sorunlar ve öncelikler tamamen farklıdır. Çok karmaşık nesneler çizmezsiniz, karmaşık projeksiyon matrislerine ihtiyacınız yoktur ve whatnot ve gölgelendiriciler çok daha basittir.

Modern OpenGL ile sık sık (gerçekten sık sık, temelde her karede) değişen geometri çizmenin en iyi yolu nedir?

Aşağıdaki paragrafta, ilgilendiğim değişiklik türlerini daha iyi tanımlayan bazı sorunlar fikirlerini (daire ve dikdörtgen sorunu) görebilirsiniz.

Denemelerim (isteğe bağlı)

Ekranda temel 2B geometri çizmekle nasıl başa çıkacağımı düşünmeye başladım:

  • bir kare: [(1, 0), (1, 1), (0, 1), (0, 0)]yerel alandaki bir karenin geometrisi için bir VBO yükleyin , ardından gölgelendiriciye gerçek kare genişliği ve dünya koordinatları ve renk bilgileri sağlayın

serin, kolay görünüyor. Bir daireye geçelim:

  • bir daire: üçgen fan ... eh. ne kadar hassasiyet (tepe noktası sayısı)? küçük daireler için hassasiyet küçük ve hata daireler için hassasiyet yüksek olmalıdır. Açıkça 1 VBO yüklemek her durumda uygun olmayabilir. Bir daire daha büyük olacak şekilde yeniden boyutlandırıldığı için kesinlik eklemem gerekirse ne olur?

Daha az serin. Biraz daha kolay bir şeye, bir dikdörtgene geçelim:

  • bir dikdörtgen: ha. "genel dikdörtgen geometrisi" yoktur. Sadece bir genişlik / yükseklik oranına sahipsiniz ve hepsi bu, ancak boyut değişirse her dikdörtgen muhtemelen farklıdır.

Gördüğünüz gibi, işler oradan yokuş aşağı gidiyor. Özellikle karmaşık çokgenler ve ne ile.

Kod politikası yok: P

Sadece fikir bir bakış gerekir, hiçbir kod gerekli, özellikle C veya C ++ kodu. Sadece şöyle bir şey söyleyin: "bu köşe verisiyle bir VBO yapın ve sonra bağlayın, ...".


Sanırım ne istediğini anlıyorum, ama bu soruya biraz daha yön vermek isteyebilirsiniz. Ne sorulduğu biraz belirsiz - aslında yakın bir sebep.
Lysol

@AidanMueller Ne demek istediğinden emin değilim, ama ihtiyacı hissedersen daha fazla yön vermek için çekinmeyin.
Ayakkabı

En iyi cevap şu anda "Ana sorunuz öyle görünüyor" diyerek başlıyor. Bu, ne sorduğunuzun belirsiz olduğunu gösterir. Belki sorunuzun sonunda bilmediğiniz şeylerin bir özetini vermelisiniz. Sonuçta bu bir soru-cevap, tartışma değil.
Lysol

@AidanMueller Bu bağlamda inanmıyorum. "Asıl sorunuz ..." gibi görünüyor ve daha sonra gönderdiğim soruyu aktarıyor. Bu aslında alıntılanacak kadar açık olduğunu gösterir. Ayrıca ifade, sorumun belirsiz olduğunu değil, ana bir soru ve başka bir ikincil soru olduğunu gösterir (yani: sunduğum belirli vakaların çözümü nedir). Şu anki sorumla ilgili problemi gerçekten görmüyorum ve görünüşe göre hem cevapları çok yararlı hem de noktaya bulduğum için cevap verenler bile görmedi.
Ayakkabı

Bir parça gölgelendirici ile hassas bir daire çizebilirsiniz.
user253751

Yanıtlar:


5

Ana sorunuz şu şekildedir:

Modern OpenGL ile sık sık (gerçekten sık sık, temelde her karede) değişen geometri çizmenin en iyi yolu nedir?

Çoğu yönden, 2d ve 3d OpenGL arasında büyük bir fark yoktur. Grafik ardışık düzen, ekstra bir koordinat olan Z'ye sahip ve bu da 2d'de fazla kullanılmayacak, ama hepsi bu.

Her çizimdeki geometriyi değiştirmenin birkaç yolu vardır.

  • Her karede CPU tarafından sağlanan yeni tepe noktalarını itebilirsiniz. ( Arabelleklerin yeniden kullanılmasına ilişkin bazı notlar için /programming/14155615/opengl-updating-vertex-buffer-with-glbufferdata adresine bakın .)

  • İle mevcut bir tamponun farklı bölümlerini çizebilirsiniz glDrawArrays(mode, first, count). Animasyon döngüye girerse, belki de farklı tepe noktası listelerine sahip önceden hesaplanmış kareleri büyük bir arabellek içine yerleştirebilir ve her karenin tamponunun uygun kısmını çizebilirsiniz.

  • Köşe listesini tek tip bir dizi veya doku gibi diğer verilerle etkileyebilirsiniz. Köşe gölgelendiricinizde, bu verileri okuyun ve uygun şekilde uygulayın. Bunlar sadece GPU'ya veri sunmak için kullanılan diğer deyimlerdir ve muhtemelen performansta çok fazla fark olmayacaktır.

  • Aynı geometriye ait birçok örneğiniz varsa (muhtemelen niteliklerden etkilenirse), glDrawElementsInstanced()yararlı olabilir

  • Tepe listesini, köşe, geometri veya mozaik gölgeleyicilerinde algoritmik olarak etkileyebilirsiniz. Animasyon matematiksel olarak açıklanabilirse, aynı köşe listesini tutabilir ve her karede yalnızca birkaç gölgelendirici üniformasını değiştirebilirsiniz.

Ve belki de animasyonunuz, tüm animasyonlar cpu tarafından piksel piksel veya önceden diskten oluşturulmuş olarak saf dokular olarak ifade edilebilir.

Genel olarak, "Bilgisayarlar hızlı, mümkün olan en kolay şekilde çalışmasını sağlayın. birincisi, bellek ayak izi ikinci. "

Başka sorunuz , "Daire ve dikdörtgen çizmenin iyi bir yolu nedir?"

Daireler.

  • Mozaik shader (veya geometri shader) ile olabilir senin geometri dinamik hale getirmek.

  • Kareler çizebilirsiniz ve parça gölgelendiricinizde yalnızca yarıçap içinde opak (alfa = 1.0) ve yarıçap dışında şeffaf (alfa = 0.0) olabilir. Sonra her seferinde piksel mükemmel. (Kare tepe noktalarınızı -1 ila +1 yapın ve parça gölgelendiricisinde şöyle bir şey yapın outColor.a = dot(coord.xy, coord.xy) < 1.0 ? 1.0 : 0.0;. Ayrıca kenarı biraz pürüzsüzleştirebilir, orada güzel görünecektir ...)

  • Her zaman, örneğin 120 üçgen bir fan kullanabilirsiniz. Muhtemelen yeterince iyi.

Dikdörtgenler.

  • Sanırım bu soruya kendi sorunuzu cevapladınız. Ne önermek iyi çalışır!

Parça gölgelendirici / yarıçap oldukça düzgün, teşekkürler. Kendi soruma cevap vermeme gelince, ne demek istediğini anladığımı sanmıyorum.
Ayakkabı

Oh, tıpkı bir karede olduğu gibi, genişliği kontrol etmeyi de (üniforma ile, sanırım) ve "Sadece bir genişlik / yükseklik oranınız var ve hepsi bu, ama boyut değişirse her dikdörtgen muhtemelen farklıdır" yazdınız. . Bu nedenle, bir dikdörtgen için kare ile aynı işlemi yapın, ancak 3 (x, y, w) yerine 4 değere (x, y, w, h) ihtiyacınız olacaktır. Veya dört üniforma olarak (xlow, xhigh, ylow, yhigh) geçin. (0,0) - (1,1) girişinizle, Vertex Shader'ın ihtiyaç duyduğu şeyi yapması yeterlidir.
david van brink

Anlıyorum, bu mantıklı.
Ayakkabı

Modern GL'de sabit fonksiyon boru hattından GL_TRIANGLE_FAN gibi otomatik bir fan var mı?
John P

5

Bu konuda uzman olduğumu söyleyemem ve oyun projelerimde 3D tarafında daha fazla yoğunlaştım, bu yüzden 2D tarafım genellikle 3D tarafı için yapılan şeyleri kullanmak oldukça basit; ve açıkçası, perspektifim oyun tarafında, bu yüzden 2B grafiklerim spriteları geometriden ziyade karıştırmakla ilgili. Bu açıdan bakıldığında,

1) Kareler ve dikdörtgenler oldukça kolaydır. VBO'da her şeyi karıştırmak için kullandığım tek bir 1x1 kutum var. Bu "birim kutusu" ile gölgelendiriciye MVP matrislerini geçiyorum ve kutuyu doğru boyutlara ölçeklemek için ek ölçeklendirme ile birleştirdim - bildiğiniz gibi, farklı x ve y ölçeğine sahip olabilirsiniz.

Benim amacım için, "birim kutusu" kullanmaktan bir tür parçacık motoruna geçerek 2D spriteları karıştırmayı düşünüyorum, ama bu başka bir hikaye.

2) Dairelerle fazla çalışmadım, sadece belirli sayıda köşeye sahip sabit VBO'lar kullanıyorum. Ancak, daire için çizilen köşe sayısını etkilemek için biraz adım atabileceğimi hayal edebiliyorum.

VBO verilerini gölgelendirici özniteliklerine bağlarken glVertexAttribPointer kullanıyorum. (Ben kullandığım) serpiştirilmiş veri için kullanılmak üzere tasarlanmış adım parametresi vardır. Ancak bu şekilde kullanmak mümkün olabilir:

glVertexAttribPointer(..., n * sizeof(VERTEX_DATA), ...);

... her n. köşeyi tampondan almak, böylece daire için çizilen köşe sayısını etkilemek. Daire için çizilen köşe sayısını etkileyen farklı adımlarla aynı VBO'ya sahip birkaç VAO oluşturabilirim. Bunu denemedim, diye düşündüm.

Genel olarak, evet, VBO'lar ile çalışmak ve böyle CPU tarafı tweaking biraz daha karmaşık hale getirir, neden GPU tarafında (gölgelendiriciler) tweaking yapmak için farklı şeyler çalışıyorum. Yine de, bu makaleye göre, çok sayıda CPU tarafı "müdahalesine" ihtiyacınız olsa bile VBO'ların kullanımı modern donanımda daha verimlidir:

http://www.quelsolaar.com/opengl_performance.txt

Umarım bu, yönlerinizi tasarlamanıza ve karar vermenize yardımcı olur.


2
"daire için çizilen köşe sayısını etkilemek için ince ayar" Süper serin!
david van brink
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.