Rendering Sprites (Sprite Render Etme)
Oyun dünyamızın şu an karanlık boşluğuna biraz can katmak için sprite'lar çizeceğiz. Sprite, birçok tanımı olan ve özünde daha büyük bir dünyada konumlandırmak için bazı verilerle (konum, döndürme, boyut gibi) birlikte kullanılan bir 2D görüntüdür. Temelde sprite'lar, 2D oyunlarda kullandığımız render edilebilir görüntü/doku nesneleridir.
Önceki bölümlerde olduğu gibi vertex verilerinden 2D şekil oluşturabilir, tüm verileri GPU'ya aktarabilir ve dönüşümleri elle yapabiliriz. Ancak bu gibi büyük bir uygulamada 2D şekil render etme üzerinde bazı soyutlamalar tercih edilir.
Bu bölümde minimum kod miktarıyla çok sayıda benzersiz sprite render edebileceğimiz bir render sınıfı tanımlıyoruz. Bu sayede oyun kodunu ayrıntılı OpenGL render kodundan soyutluyoruz. Önce uygun bir projeksiyon matrisi ayarlamamız gerekiyor.
2D Projeksiyon Matrisi
Koordinat sistemleri bölümünden bildiğimiz gibi projeksiyon matrisi, tüm görünüm uzayı koordinatlarını clip-space (ve ardından normalize edilmiş cihaz) koordinatlarına dönüştürür. Uygun projeksiyon matrisi oluşturup koordinatlarla doğrudan NDC olarak çalışmak yerine çalışması daha kolay farklı koordinatlarla çalışabiliriz.
Oyun tamamen 2D olduğundan koordinatlara hiçbir perspektif uygulamamıza gerek yok; bu nedenle ortografik projeksiyon matrisi render için son derece uygun. Ortografik projeksiyon matrisi tüm koordinatları NDC'ye dönüştürdüğünden, dünya koordinatlarını şu şekilde ekran koordinatları olarak belirtebiliriz:
glm::mat4 projection = glm::ortho(0.0f, 800.0f, 600.0f, 0.0f, -1.0f, 1.0f);İlk dört argüman sırasıyla projeksiyon frustum'unun sol, sağ, alt ve üst kısımlarını belirtir. Bu projeksiyon matrisi 0 ile 800 arasındaki tüm x koordinatlarını -1 ile 1'e, 0 ile 600 arasındaki tüm y koordinatlarını -1 ile 1'e dönüştürür. Sahnenin sol üst koordinatı (0, 0), sağ alt kısmı ise (800, 600) olur; tıpkı ekran koordinatları gibi.

Bu, 2D oyunlar için oldukça sezgisel olan, tüm vertex koordinatlarını ekrandaki piksel koordinatlarına eşit değerlerle belirlememizi sağlar.
Sprite Render Etmek
Gerçek bir sprite render etmek çok karmaşık değil. Model matrisiyle dönüştürebileceğimiz dokulu bir quad oluşturuyoruz; ardından daha önce tanımladığımız ortografik projeksiyon matrisiyle yansıtıyoruz.
Breakout tek sahneli bir oyun olduğundan view/kamera matrisine gerek yoktur. Projeksiyon matrisini kullanarak dünya uzayı koordinatlarını doğrudan NDC'ye dönüştürebiliriz.
Bir sprite'ı dönüştürmek için şu vertex shader'ı kullanırız:
Hem konum hem doku koordinatı verilerini tek bir vec4 değişkeninde sakladığımıza dikkat edin.
Fragment shader görece basittir. Bir doku ve renk vektörü alır; her ikisi de fragment'ın nihai rengini etkiler. Uniform renk vektörü sayesinde sprite renklerini oyun kodundan kolayca değiştirebiliriz:
Sprite render etmeyi daha organize hale getirmek için tek bir fonksiyonla sprite render edebilen bir SpriteRenderer sınıfı tanımlıyoruz:
Başlatma
initRenderData fonksiyonu quadVAO'yu yapılandırır:
Burada (0, 0)'ın quad'ın sol üst köşesi olduğu bir vertex kümesi tanımladık. Bu, quad üzerinde öteleme veya ölçekleme dönüşümleri uyguladığımızda bunların quad'ın sol üst konumundan dönüştürüleceği anlamına gelir. Bu yaklaşım 2D grafik/GUI sistemlerinde yaygın kabul görmekte; elemanların konumları elemanın sol üst köşesine karşılık gelir.
Tüm sprite'lar aynı vertex verisini paylaştığından sprite renderer için yalnızca tek bir VAO tanımlamamız yeterli.
Render Etmek
Sprite render etmek çok zor değil; sprite renderer'ın shader'ını kullanır, bir model matrisi yapılandırırız ve ilgili uniform'ları ayarlarız. Burada önemli olan dönüşümlerin sırası:
Bir sahnede nesneyi döndürme ve ölçekleme dönüşümleriyle konumlandırmak istediğinizde önce ölçekleme, sonra döndürme, son olarak öteleme yapılması önerilir. Matris çarpma sağdan sola gerçekleştiğinden matrisi ters sırada dönüştürürüz: önce öteleme, sonra döndürme, ardından ölçekleme.
Döndürme dönüşümü biraz karmaşık görünebilir. Dönüşümler bölümünden bildiğimiz gibi döndürmeler her zaman orijin (0, 0) etrafında gerçekleşir. Quad'ın vertex'lerini (0, 0)'ın sol üst köşe olduğu şekilde belirttiğimizden tüm döndürmeler bu noktada gerçekleşir; bu istenmeyen sonuçlar doğurur. Döndürme orijinini quad'ın merkezine taşımak istiyoruz; böylece quad sol üst köşe yerine merkezi etrafında düzgünce döner. Bunu çözmek için önce quad'ı yarısı kadar öteliyoruz; böylece döndürmeden önce merkezi (0, 0) koordinatında olur.

Önce quad'ı ölçeklendirdiğimizden sprite'ın merkezine ötelemek için sprite'ın size vektörüyle çarpmamız gerekir. Döndürme dönüşümü uygulandıktan sonra önceki ötelemeyi tersine çeviririz.
Tüm bu dönüşümleri birleştirerek her sprite'ı istediğimiz şekilde konumlandırabilir, ölçeklendirebilir ve döndürebiliriz.
Sprite renderer'ın tam kaynak kodu: başlık, kod.
Merhaba Sprite!
SpriteRenderer sınıfıyla nihayet gerçek görüntüleri ekrana render etme imkânımız var! Oyun kodunda birini başlatıp favori dokumuzı yükleyelim:
Render fonksiyonunda maskotumuzun düzgün görünüp görünmediğini kontrol edelim:
Sprite'ı ekranın merkezine yakın konumlandırıyoruz; yüksekliği genişliğinden biraz daha fazla. Aynı zamanda 45 derece döndürüyor ve yeşil renk veriyoruz. Sprite'a verdiğimiz konumun sprite'ın quad'ının sol üst vertex'ine eşit olduğuna dikkat edin.
Her şeyi doğru yaptıysanız şu çıktıyı alırsınız:

Güncellenmiş oyun sınıfının kaynak kodunu buradan bulabilirsiniz.
Render sistemi çalışır hale geldiğine göre sonraki bölümde oyunun seviyelerini oluşturmaya devam edeceğiz.
Last updated