Programlama yönü ve bileşenlerin birbirleriyle nasıl konuştuğu hakkında biraz yazmaya karar verdim. Belki bazı bölgelere ışık tutacaktır.
Sunum
Sorunuzda yayınladığınız tek bir görüntünün ekranda çizilmesi bile ne gerekiyor?
Ekranda üçgen çizmek için birçok yol vardır. Basit olması için, hiçbir köşe arabelleğinin kullanılmadığını varsayalım. (Bir köşe arabelleği , koordinatları sakladığınız bir bellek alanıdır.) Programın grafik işleme hattına her bir köşe (bir köşe sadece uzayda bir koordinattır) hakkında anlattığını varsayalım.
Ancak , herhangi bir şey çizmeden önce, ilk önce bir iskele kullanmalıyız. Neden sonra göreceğiz :
// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset The Current Modelview Matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Drawing Using Triangles
glBegin(GL_TRIANGLES);
// Red
glColor3f(1.0f,0.0f,0.0f);
// Top Of Triangle (Front)
glVertex3f( 0.0f, 1.0f, 0.0f);
// Green
glColor3f(0.0f,1.0f,0.0f);
// Left Of Triangle (Front)
glVertex3f(-1.0f,-1.0f, 1.0f);
// Blue
glColor3f(0.0f,0.0f,1.0f);
// Right Of Triangle (Front)
glVertex3f( 1.0f,-1.0f, 1.0f);
// Done Drawing
glEnd();
Peki bu ne yaptı?
Grafik kartını kullanmak isteyen bir program yazdığınızda, genellikle sürücüye bir çeşit arayüz seçersiniz. Sürücünün iyi bilinen bazı arayüzleri:
Bu örnek için OpenGL'ye bağlı kalacağız. Şimdi, sürücüye olan arayüzünüz , programınızın grafik kartıyla (veya daha sonra kartla konuşan sürücüyle) konuşmasını sağlamak için ihtiyaç duyduğunuz tüm araçları sağlayan şeydir .
Bu arayüz size belirli araçlar verecek şekildedir . Bu araçlar programınızdan çağırabileceğiniz bir API şeklini alır .
Bu API, yukarıdaki örnekte kullanıldığını görüyoruz. Hadi daha yakından bakalım.
İskele
Gerçek bir çizim yapmadan önce, bir kurulum yapmanız gerekecektir . Görüntü alanınızı (gerçekte oluşturulacak alan), bakış açınızı ( dünyanızdaki kamera ), kullanacağınız kenar yumuşatma özelliğini (çgenizin kenarını düzeltmek için) tanımlamanız gerekir ...
Ama hiçbirine bakmayacağız. Her karede yapmanız gerekenlere bir göz atacağız . Sevmek:
Ekranı temizlemek
Grafik hattı sizin için her karede ekranı temizlemeyecek. Bunu söylemen gerekecek. Neden? Bu nedenle:
Ekranı temizlemezseniz, sadece her karenin üzerine çizersiniz. Dediğimiz bu yüzden glClear
birlikte GL_COLOR_BUFFER_BIT
sette. Diğer bit ( GL_DEPTH_BUFFER_BIT
), OpenGL'ye derinlik tamponunu temizlemesini söyler . Bu tampon, hangi piksellerin diğer piksellerin önünde (veya arkasında) olduğunu belirlemek için kullanılır.
dönüşüm
Görüntü kaynağı
Dönüşüm, tüm girdi koordinatlarını (üçgenimizin köşeleri) aldığımız ve ModelView matrisimizi uyguladığımız kısımdır. Bu matristir açıklar bizim nasıl modeli (köşe), döndürülmüş ölçekli ve (taşınır) çevrilir.
Ardından, Projection matrisimizi uyguladık. Bu, tüm koordinatları hareket ettirerek kameralarımıza doğru bakmalarını sağlar.
Şimdi, Viewport matrisimizle bir kez daha dönüşüyoruz. Bunu, modelimizi monitörümüzün boyutuna ölçeklendirmek için yapıyoruz . Şimdi işlenmeye hazır bir dizi köşemiz var!
Biraz sonra dönüşüme döneceğiz.
Çizim
Bir üçgen çizmek için, OpenGL'ye sabit ile çağırarak yeni bir üçgenler listesi başlatmasını söyleyebiliriz . Çizebileceğiniz başka formlar da var. Bir gibi üçgen şerit veya üçgen fan . Bunlar, CPU ve GPU arasında aynı miktarda üçgen çizebilmek için daha az iletişime ihtiyaç duydukları için öncelikli olarak optimizasyonlardır.glBegin
GL_TRIANGLES
Bundan sonra, her üçgeni oluşturması gereken 3 köşe kümesinin bir listesini sağlayabiliriz. Her üçgen 3 koordinat kullanır (3B alanda olduğumuz gibi). Ek olarak, çağırmadan önce arayarak her köşe için bir renk de veriyorum .glColor3f
glVertex3f
3 köşe (üçgenin 3 köşesi) arasındaki gölge OpenGL tarafından otomatik olarak hesaplanır . Çokgenin tüm yüzündeki rengi enterpolasyon yapar.
etkileşim
Şimdi, pencereye tıkladığınızda. Uygulamanın yalnızca tıklamayı gösteren pencere mesajını yakalaması gerekir . Ardından, programınızda istediğiniz herhangi bir işlemi gerçekleştirebilirsiniz.
3D sahnenizle etkileşime geçmek istediğinizde bu çok daha zorlaşıyor.
Öncelikle, kullanıcının pencereyi hangi pikselde tıklattığını net bir şekilde bilmek zorundasınız. Ardından, bakış açınızı dikkate alarak , farenin tıklaması noktasından sahnenize kadar bir ışın yönünü hesaplayabilirsiniz. Ardından, sahnedeki herhangi bir nesnenin o ışınla kesiştiğini hesaplayabilirsiniz . Artık kullanıcının bir nesneyi tıklayıp tıklamadığını biliyorsunuz.
Peki onu nasıl döndürürsün?
dönüşüm
Genelde uygulanan iki dönüşüm türünün farkındayım:
- Matris tabanlı dönüşüm
- Kemik bazlı dönüşüm
Aradaki fark, kemiklerin tek köşeleri etkilemesidir . Matrisler her zaman tüm çizilmiş köşeleri aynı şekilde etkiler. Bir örneğe bakalım.
Örnek
Daha önce, üçgeni çizmeden önce kimlik matrisimizi yükledik . Kimlik matrisi hiçbir şekilde dönüşüm sağlamayandır . Yani, ne çizersem çizeyim sadece bakış açımdan etkilenir. Böylece, üçgen hiç döndürülmeyecek.
Şimdi döndürmek istiyorsanız, ben (CPU üzerine) matematik kendim yapmak ve basitçe diyebiliriz ya glVertex3f
ile diğer (döndürülür) koordinatlarında. Veya glRotatef
çizmeden önce arayarak GPU'nun tüm işi yapmasına izin verebilirim :
// Rotate The Triangle On The Y axis
glRotatef(amount,0.0f,1.0f,0.0f);
amount
Tabii ki, sadece sabit bir değerdir. Canlandırmak istiyorsanız , amount
her kareyi izlemeniz ve arttırmanız gerekir.
Peki, bekle, daha önce tüm matris konuşmalarına ne oldu?
Bu basit örnekte, matrislerle ilgilenmek zorunda değiliz. Biz sadece ararız glRotatef
ve bizim için herşeyi halleder.
glRotate
angle
xyz vektörü etrafında derece dönüşü üretir . Geçerli matris (bkz. GlMatrixMode ), mevcut matrisi değiştiren ürünle birlikte bir döndürme matrisi ile çarpılır, sanki glMultMatrix , argümanı olarak aşağıdaki matris ile çağrıldı:
x 2 1 - c + cx y 1 - c - z sx z 1 - c + y s 0 y x 1 - c + z sy 2 1 - c + cy z 1 - c - x s 0 x z 1 - c - y sy z 1 - c + x sz 2 1 - c + c 0 0 0 0 1
Bunun için teşekkürler!
Sonuç
Ne belirginleşmektedir konuşma çok yok demek için OpenGL. Ama bize bir şey anlatmıyor. İletişim nerede
OpenGL’in bize bu örnekte söylediği tek şey, bittiği zaman . Her işlem belirli bir zaman alacaktır. Bazı operasyonlar inanılmaz derecede uzun sürüyor, bazıları ise inanılmaz derecede hızlı.
GPU’ya bir köşe göndermek çok hızlı olacak, nasıl ifade edeceğimi bile bilemedim. İşlemciden GPU'ya binlerce köşe gönderme, her bir kare, büyük olasılıkla, hiç sorun değil.
Ekranı temizlemek, görünüm alanınızın büyüklüğüne bağlı olarak, her kareyi çizmek için genellikle yalnızca yaklaşık 16 milisaniyeniz vardır, aklınızda bulundurun. Bunu temizlemek için, OpenGL'nin temizlemek istediğiniz renkteki her bir pikseli çizmesi gerekir; bu da milyonlarca piksel olabilir.
Bunun dışında OpenGL’ye grafik adaptörümüzün yeteneklerini (maksimum çözünürlük, maksimum kenar yumuşatma, maksimum renk derinliği,…) hakkında sorabiliriz.
Ancak bir dokuyu, her biri belirli bir renge sahip piksellerle doldurabiliriz. Böylece her piksel bir değer tutar ve doku, verilerle dolu dev bir "dosyadır". Bunu grafik kartına yükleyebiliriz (bir doku tamponu oluşturarak), sonra bir gölgelendirici yükleyebilir , bu gölgelendiriciye dokumamızı bir girdi olarak kullanmasını ve "dosyamızda" çok ağır hesaplamalar yapmalarını söyleriz.
Daha sonra, hesaplamanın sonucunu (yeni renkler biçiminde) yeni bir dokuya dönüştürebiliriz.
GPU'nun sizin için başka şekillerde çalışmasını sağlayabilirsiniz. CUDA'nın bu yönüyle benzer performans sergilediğini varsayıyorum, ancak bununla çalışma fırsatım olmadı.
Tüm konuya gerçekten sadece hafifçe dokunduk. 3D grafik programlama bir canavarı cehennem.
Görüntü Kaynağı