uEngine4 Serüveni – BasicGLPainter – II

Evet dostlar, GLPainter sınıfımızın kalan kabiliyetlerine bakma vakti geldi. Bu yazımızda aşağıdaki yazılarda eksik bıraktığımız konulara değinerek, GLPainter’ı sizlerin kullanımına sunuyorum.

uEngine4 Serüveni – Giriş (Painter Sınıfları)

uEngine4 Serüveni – BasicGLPainter – I

Bir önceki yazımda GLPainter ile metin gösterimi ve resim çizmeye yönelik kabiliyetlere değinmiştik. Şimdi, kalan hususlara değinelim. Bunlardan ilki dönüşümler, diğeri ise stencil operasyonları.

Dönüşümler (“Transformations”)

Dönüşümler mevzusuna aslında SDLPainter’da biraz değinmiştim. SDL2 ile bütün sahneyi veya ilgili nesneleri topyekün ya da tek tek taşıma ya da döndürme ya da boyutlandırmanın bir yöntemi yok (detaylar için https://wiki.libsdl.org/SDL2/APIByCategory sayfasına göz atabilirsiniz). Her ne kadar bu temel uygulamalar için çok sıkıntı olmasa da, harita ve benzeri uygulamalarda hayatınız oldukça zorlaştırabilmekte. GLPainter’ın en büyük avantajlarından birisi de bu transformasyonlar. Peki nedir bu dönüşümler?

Dönüşümler aslında bilgisayar grafiklerinin temelini oluşturulan kavramlardan birisidir ve genel olarak 2B/3B nesnelerin konum, yön ya da boyutlarını modifiye etmek için kullanılan matematiksel operasyonlardır. 2B temel bilgisayar grafikleri dönüşümleri şunlardır:

  • Döndürme (rotation),
  • Taşıma (translation),
  • Boyutlandırma (scaling)

bunlarından yanında aşağıdaki türetilmiş dönüşümler de kullanılmaktadır:

  • Yansıma (reflection)
  • Kaydırma (shearing)

Bütün bu operasyonlar matris işlemleri aracılığı ile gerçekleştirilir ve her birine karşılık gelen matris gösterimleri bulunmaktadır. 2B/3B noktalar ile ifade edilen nesnelerin her bir noktasına bunlar uygulanarak, yukarıda verilen işlevler gerçekleştirilir.

Aşağıda, 2B bir nokta döndürmenin grafiksel gösterimini ve bundan matris formu nasıl edeceğimiz göstereceğiz:

2D Derivation Rotation Matrix

Yukarıdaki grafikte görüleceği üzere x ve y noktaları aşağıdaki şekilde bulunabilir:

x=rcos(α)

y=rsin(α)

döndürme sonucu elde edilen x’ ve y’ noktaları ise aşağıdaki şekilde bulunabilir:

x=rcos(α+β)

y=rsin(α+β)

Şimdi x ve y formüllerini, cos/sin’leri, r/r’ ‘leri de yerine koyduğumuzda aşağıdaki formülleri elde ediyoruz:

x=rcos(α)cos(β)rsin(α)sin(β)

y=rcos(α)sin(β)+rsin(α)cos(β)

Bunlara da x=rcos(α), y=rsin(α)’ları koyarsak

x=xcos(β)ysin(β)

y=xsin(β)+ycos(β)

elde ediyoruz. Bunun matris formu ise aşağıdaki gibi olmakta:

burada 2×2’lik matrise β açısı ile 2B dönüşüm matrisi denilmektedir.

Tabi yukarıda verdiğimiz sadece döndürme matrisi. Bunun benzeri taşıma ve boyutlandırma için de oluşturulabilir. Aşağıda verilen resimde, 2B için kullanılabilecek bütün dönüşüm matrisleri tek resimde özetlenmiştir:

2D affine transformation matrix. | Matrices math, Math formulas, Math

sonuç olarak oyunlarda gördüğünüz milyonlarca noktanın konumlandırılması/boyutlandırılması ya da döndürülmesi aslında bu matrislerin birbirleri ile çarpılması ile elde edilmekte. 3B uzaya geçince ve işin içine perpektif hesaplamaları da girince, bu matrisler bir nebze karışabilir ama şu an mevzumuz 2B ile sınırlı.

Tabi ki, GLPainter’ın temel motivasyonu sizleri bütün bu detaylardan korumak ama neden bunlara girdin o zaman sevgili yazılımperver diyebilirsiniz 😀

İşin şakası bir yana, 2B/3B görselleştirme ya da oyun işine girecekseniz bunları sular, seller gibi bilmenizde fayda var, onu da buraya not düşelim. Şimdi gelelim GLPainter ile bunları nasıl yapabileceğinize. Önce API’lerimizi bir sıralayalım:

Yukarıda da bahsettiğim üzere bu dönüşümlerin matrise çevrilmesinin arkasında yatan en önemli motivasyon aslında bunların çarpımı sayesinde tek bir matris elde edip bunu uygulamaktan geçer. Arkadaki matematiğe baktığınızda da bunu rahat bir şekilde görebilirsiniz. Elbette burada dikkat etmeniz gereken en önemli konu, bunların sıralamasının önemli olduğu ve çarpım yaparken de birleştirmede kullandığınız bileşenlerin sağdan sola doğru uygulandığıdır. Örneğin bir nesnemizi, (x, y, z) ekseninde (1, 2, 3) taşıyıp, 2 birim ölçeklendirme istiyorsak, önce taşıma/öteleme, sonra ölçeklendirme matrisini yerleştirip çarpıyoruz:

Bu matrisleri çarptığımızda aşağıdaki matrisi elde ederiz:

Bunu uygularken de önce ölçeklendirme sonra boyutlandırma yapılır. Gerçekten de aşağıdaki örnekte göreceğiniz üzere kullanacağınız dönüşüm API’lerinin sıralaması da bununla uyumlu olmalıdır. Döndürmeyi de ekleyecek olursak, özel bir durum yok ise önce ölçeklendirme, sonra döndürme ve en son da taşıma işlemleri yapılır. Bu üç dönüşümü 2B için gösteren örneği aşağıda görebilirsiniz (uEngine4 reposu içerisinde gl_example projesinde ilgili kullanımı birebir görebilirsiniz):

Yukarıdaki örnekte dönüşüm çağrılarının sırasını değiştirerek, bunun çizimleri ve animasyonu nasıl etkilediğini birinci elden görebilirsiniz. Elbette, OpenGL dönüşüm olayı oldukça derin, gerekirse o konuya da ayrıca girebiliriz ama yukarıdaki örnek BasicGLPainter’ın temel kabiliyetlerini güzel bir şekilde ortaya koymakta. Şimdi gelelim stencil operasyonlarına.

Stencil Testi

Stencil testi aslına bakarsanız bu ve önceki yazımda bahsettiğim özelliklere nazaran daha ileri seviye bir özellik. Normal kullanımlarda çok ihtiyacınız olacağınız düşünmüyorum ama velev ki oldu, BasicGLPainter size bunu da sunuyor olacak 😀

Peki stencil test ne anlama geliyor? Stencil test, fragment shader sonrasında her bir pixel için yapılan teste deniliyor. Bu testin sonucuna göre ilgili piksel gösteriliyor ya da gösterilmiyor (test kalırsa). Stencil testi için, aynı derinlik testinde olduğu gibi ayrı “buffer” ‘lar kullanılmakta. Bu sebeple de SDL2 kullanıyorsanız, buna ilişkin ayarlamaları yapmanız gerekiyor. Elbette, BasicGLPainter sizler için bunu arka planda hallediyor 👍

Kaynaklar kısmında verdiğim sitelerde bu konuya ilişkin oldukça detaylı bilgiler bulabilirsiniz fakat benim hoşuma giden bir örneği de burada göstermeden geçemeyeceğim:

Soldaki resim, stencil testi uygulamadan önceki sahne ve ilgili stencil test açıldığında ve ilgili testlerin geçtiği kısımlar nihayetinde kullanıcıya sunuluyor.

Şimdi gelelim bu test kısmına. OpenGL bu testi neye göre yapıyor. Öncelikle stencil testinin aktifleştirilmesi gerekiyor. Sonrasında ise glStencilFunc, glStencilMask ve glStencilOp ile bu testi şekillendirebiliyorsunuz. Sizlerin de tahmin edebileceğiniz üzere, bu ayarlar ile oldukça ilginç işlevleri gerçekleştirmeniz mümkün ama ben BasicGLPainter kapsamında temel kırpma kabiliyeti için (“clip”) bu testi kullandım. Peki bunu nasıl kullanacaksınız? Öncelikle API’lerimize bir bakalım:

Tabi bunları nasıl kullanacağımız da önemli öyle değil mi, hemen bir örneğe bakalım:

Yukarıdaki örnekte, ortasında bir delik olan kareyi BasicGLPainter ile nasıl kolay bir şekilde çizebileceğimiz gördük.

Evet bu yazım ile birlikte BasicGLPainter tanıtım serimizin sonuna geldik. BasicGLPainter ile bir çok temel oyun için ihtiyaç duyacağınız 2B grafikleri çizdirebilirsiniz. Elbette, uEngine4 serimiz burada bitmiyor, bir sonraki yazımda görüşmek dileğiyle, bol kodlu günler diliyorum.

Kaynaklar

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Bu site, istenmeyenleri azaltmak için Akismet kullanıyor. Yorum verilerinizin nasıl işlendiği hakkında daha fazla bilgi edinin.