COM337 Bilgisayar Grafiği OpenGL ile Grafik Programlama Dr. Erkan Bostancı İçerik • Işık • Resim ve Metin Görüntüleme • Texture-mapping Işık (1/3) • OpenGL’de bir sahne 8 farklı ışık kaynağı kullanabilir. • İlk ışık kaynağı için specular ve diffuse parametreleri öntanımlıdır. • Işığın çalışması için glShadeModel ve glEnable(GL_LIGHTING) çağrılarının yapılması gerekir. • Işık kaynakları her yönde (omnidirectional) ışık saçar ama spot ışık olarak da kullanılabilir. • Renk değerlerindeki 4. parametre alpha ya da opaklık değeridir. Bu sayede transparan veya ışığı geçiren materyaller oluşturulabilir. • Örnek 9 Işık (2/3) • RGBA modunda her pikselin bir opaklık değeri vardır. • Opaklık değerinin 0 olması o pikseli transparan yapar. • Opaklık anti-aliasing’de kullanılır. Kenar (edge) içeren bir piksel’in bir kısmı alpha değerinde tutulur. Işık (3/3) • Örnek 11 Pikseller, imgeler ve metin • OpenGL’de bir pencerede bir imge göstermek için şu anki çizim yapılacak konumu ilgili dörtgenin sol alt tarafına getirip pikselleri çizeriz. • Metin çizmek için, yine ilgili konuma gidip, tek tek karakterleri çizeriz. • OpenGL hem bitmap fontları, hem de stroked fontları destekler. • Stroke fontlar çizgilerden oluşur ve bunlara dönüşümler (scale, vs.) uygulanabilir. • Metin çizerken, ışıkları kapatmak önemlidir, aksi takdirde OpenGL metinlere de gölgelendirme vermeye çalışır. • Bir nedenden dolayı 3B koordinat sisteminizi pencere koordinatlarıyla eşleştirmek isterseniz, örnekteki reshape callback’i bunu yapar. • Örnek 12 Görüntüleme pipeline’ını ters çevirmek • Bazı uygulamalarda ekrandaki bir noktaya tıkladığınızda o noktanın 3B uzayda karşılığını bulmak istersiniz. • Bu aslında projeksiyondan dolayı eksik tanımlı (ill-defined) bir problemdir ve ters projeksiyon net değildir. • Fakat penceredeki (x,y) değerleriyle birlikte bir z değeri de belirtirsek, modelview ve projection matrislerinin tersinin alınmasını sağlayabiliriz. Bu z değeri yakın ve uzak kırpma düzlemleri arasında olmalıdır. gluUnProject (winx, winy, winz // window position + z-value modelmatrix, // 16-element modelview matrix projmatrix, // 16-element projection matrix objx, objy, objz) // pointers for object-space position Texture-mapping (1/7) • Bir nesneye yapılan doku ataması (texture-mapping) o nesneyi görsel anlamda zenginleştirir. • OpenGL 1, 2, 3 boyutlu texture’ları destekler. Texture-mapping yalnızca RGBA modunda çalışır. • Bu modda her pikselin bir opaklık değeri vardı. • Örnek 13 Texture-mapping (2/7) • OpenGL’de doku ataması yaparken 3 adım vardır: 1. Öncelikle texture olarak kullanılacak imgeyi belirlememiz gerekli. Örnekte, init fonksiyonun içindeki 2 for döngüsü bir satranç tahtası texture’ını oluşturuyor. 2. Ardından, OpenGL texture’ı nasıl uygulayacağını belirten parametreleri tanımlıyoruz. 3. Son olarak da, noktalar için texture koordinatlarını tanımlıyoruz. Bu poligonların oluşturulduğu display callback’i içinde yapılır ve texture koordinatları poligon’un köşe koordinatları ile ilişkilendirilir. Texture-mapping (3/7) • Texture’ın kendisini oluşturmanın yanı sıra, bütün parametre ayarlamaları init’in içinde yapılıyor. • glGenTextures ve glBindTexture bir imge için texture nesnesi oluşturur. • Önemli olan çağrı glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA,GL_UNSIGNED_BYTE, image); • İmgeyi texture map’a dönüştürür. Texture-mapping (4/7) • Fonksiyonun parametreleri: 1. GL_TEXTURE_2D: 2 boyutlu texture kullandığımızı belirtir. 2. 0: texture map’in derecesin en üst derece yapar. Bu mip-mapping’de kullanılır. 3. GL_RGBA: imge verisi hem RGB kanallarını hem de alpha kanalını içerir. 4. WIDTH ve HEIGHT: imgedeki column ve row sayısı. • 2’nin bir üstü olmalıdır. 5. 0: Texture map’in hiç kenarının olmadığını belirtir. 6. GL_RGBA: kullanılacak texel türünü belirtir. 7. GL_UNSIGNED_BYTE: piksellerin veri türünü belirtir. 8. image: asıl imge verisini içeren pointer. Texture-mapping (5/7) • display callback’inde texture mapping açılıyor (enable) ve glTextEnvf yüzeydeki herhangi renk bilgisinin yerine texture olacağını belirtiyor. • display‘in içinde 2 tane dörtgen çiziliyor ve her köşe için tanımlanacak texel köşe noktasından önce tanımlanıyor. glBegin (GL_QUADS); glTexCoord2f (0.0, 0.0); glVertex3f (-2.0, -1.0, 0.0); glTexCoord2f (0.0, 1.0); glVertex3f (-2.0, 1.0, 0.0); ... • Texture mapping nasıl yapılacağını söyleyen parametreleri de anlatacak olursak, init’in içindeki glTexParameteri fonksiyonu bu işi yapıyor. Texture-mapping (6/7) • OpenGL’de texture map’in indeksleri s ve t olarak adlandırılır. Aşağıdaki çağrılar bu indekslerin 0-1 aralığından çıktığında ne yapılması gerektiğini söyler: • glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT); • glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); • Burada texture’ı tekrarlatmasını söylüyoruz. • Bir texel’in boyutunun oluşan görüntüdeki bir piksel ile tam olarak eşleşmesi her zaman olmaz. • Geometriye göre bazen bir texel birden çok pikseli kaplar (magnification), bazen de bir piksel birden çok texel’i kaplar (minification). Texture-mapping (7/7) • OpenGL texture-mapping’i her pikseli, texture uzayındaki bir noktaya atarken her köşe ile ilgili değerleri interpolate eder. • Bu performans açısından hızlıdır ama görüntü açısından sorunlar yaratabilir. Bu nedenden dolayı OpenGL bize filtreleme imkanı sunar. • Nearest-neighbour • Two-by-two average • Programın hızlı çalışmasını istediğimizden nearest-neighbour kullandık: glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); Aliasing (1/2) • Texture-mapping nasıl çalışır? • Yüzey render edilirken, frame buffer’a yazılacak olan yüzey pikselleri texture map’in indekslerine çevrilir. • Scaling ve perspektif etkilerin kullanıldığı yüzeyler, orijinal texture map’in scale’inden farklı görünür. Bu da aliasing oluşturur. • Bu sorun hareketli yüzeylerde daha fazla göze çarpar. Aliasing (2/2) • Çözüm: • Farklı scale’lerde kullanılacak farklı texture’lar kullanmak. • Mip-mapping • Daha düşük çözünürlüklü texture’lar kullanmak. Herbiri bir üst seviyenin yarı boyutunda. • 32x32, 16x16, 8x8, 4x4, 2x2, 1x1 piksel boyutlarında.