OpenGL: Görüntüyü Yeniden Boyutlandırma ve glOrtho / glViewport


16

Bu soruyu çeşitli kaynaklardan araştırdım ve henüz "evet bu doğru düşünme" ya da "hayır, işte böyle yapılıyor" diyen kesin bir cevap bulamadım.

OpenGL oluşturma ile çözünürlük bağımsızlığını sağlamaya çalışıyorum. Bunun hakkında düşünmem gerektiğini düşündüğüm yol glOrtho, dünya koordinatlarının olmasını istediğim her şeyi kullanarak bir projeksiyon oluşturmak . Örneğin glOrtho(-50.0, 50.0, -50.0, 50.0, 1.0, -1.0),. Ardından, görüntü alanını ekran çözünürlüğüne ayarlayın , yani - glViewport(0, 0, 800, 600). Son olarak, pencere yeniden boyutlandırıldığında, glViewportgüncellenen ekran çözünürlüğü ile bir çağrı yapın . Bu rakamlarınızı ölçeklendirir.

Modellerin farklı çözünürlüklerde aynı oranda ekran alanı almasını sağlamanın doğru yolu var mı? Çözünürlüğe eşit bir projeksiyon da kullanmalı mıyım? Bazı yanıtlar glOrthopencerenizin çözünürlüğünü kullanması gerektiğini söylerken, diğerleri farklı olması gerektiğini / farklı olabileceğini söyledi.

Düşünceler?

Yanıtlar:


20

Açıkladığınız şey, çözüm bağımsızlığı sağlamak için tamamen yeterli ve uygundur . Çizdiğiniz her şey gerçekten her zaman pencerenizin aynı oranını kaplar.

Ancak, bundan başka bir şey yapmazsanız, en boy oranı sorunlarınız olacaktır. Örneğin, yazdığınız sayılar göz önüne alındığında, bir daire çizerseniz, uzunlamasına göre daha geniş olacak, çünkü yatay ölçeğiniz 800 / (50 + 50) = 8 ve dikey ölçeğiniz 600 / (50+) 50) = 6.

Bu sorunun otomatik çözümü olamaz ; istediğiniz grafik sonucunu seçmeniz ve bunun oyun üzerindeki etkisini göz önünde bulundurmanız gerekir. Bazı yaygın örnekler:

  • HUD içermeyen perspektif projeksiyonlu bir 3D oyunda, her zamanki basit çözüm (parçası olarak OpenGL'de mevcuttur gluPerspective) projeksiyonun görüş alanını dikey boyuta göre düzeltmektir . Bu, böyle bir oyunda, pencereyi yatay olarak yeniden boyutlandırırsanız, sahnenin daha fazla veya daha azını göreceğiniz ve görüntünün orta kısmının hiç değişmeyeceği anlamına gelir.

    Aynı fikir bir 2D / 2.5D görünümüne de uygulanabilir.

    (Bunun, geniş ama uzun olmayan bir pencere yaparak oyuncunun görüş alanını yatay olarak büyütmesine izin verdiğini unutmayın. Bu, rekabetçi çok oyunculu bir oyunda istenmeyen olabilir.)

  • Sabit bir en boy oranına (örneğin, kaydırılmamış bir 2B harita veya dekoratif bir kenarlık) sahip görüntü alanı doldurma grafikleriniz varsa veya düzeni başka türlü değiştiremiyorsanız, ikisinde siyah çubuklar gibi bir şey yapmanız gerekir kullanılmayan alanı doldurmak için.

    Ya da, oyunun zarar görmesine gerek kalmadan ekrana sığacak şekilde kırpılabilecek , kenarları etrafında tematik olarak tutarlı dolgu malzemesi olan grafikler yapabilirsiniz .

  • Diğer grafiklerin üstünde bir HUD'niz varsa, her HUD öğesinin pencerenin bir bölümüne (sol üst, alt orta, vb.) Sabitlenmesine ve koordinatlarını hesaplamaya karar verebilirsiniz; görünüş oranlarını değiştirmenin 'gerilmesi', HUD elemanları arasındaki 'beyaz boşluk' tarafından emilir.

Maddenin belirli matematik olarak, işe başlamak için gereken tüm boy oranı, tek sayıdır, sen çözünürlük bağımsızlığı yaptığını verilen: width / height. Örneğin, pencere kare ise 1 olacaktır; 800 x 600 ise, 800/600 = 4/3 = 1.333̅ olacaktır.

Örneğin , pencere genişletilmişse, yazdığınız yazım projeksiyonunun sol ve sağ taraflarda ek alan kazanmasını istediğinizi varsayalım . Bunu şöyle yapabilirsiniz:

float aspect = width / height;
glViewport(0, 0, width, height);
glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);

Bu, en az boyları kadar geniş olan pencereler için, -50 ile 50 arasındaki x ve y koordinatlarıyla çizdiğiniz her şeyin görünür olacağını garanti eder.

Öte yandan, pencere uzunluğundan daha darsa -50 ila 50 aralığı kesilecektir. Diyelim ki her zaman görünür olduğundan emin olmak istediniz (böylece pencere kare ise içeriğiniz maksimum boyutundadır, ancak aksi takdirde daha küçüktür); bu durumda, aynı şeyi genişlik yerine yüksekliğe yapabilirsiniz.

float aspect = width / height;
glViewport(0, 0, width, height);
if (aspect >= 1.0)
  glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);
else
  glOrtho(-50.0, 50.0, -50.0 / aspect, 50.0 / aspect, 1.0, -1.0);

İkinci durumda çarpmak yerine bölündüğümüze dikkat edin. Bunun nedeni, en boy oranını width / heightdeğil height / width; bu şekilde daha kolay anlaşılır bulursanız karşılık alın.

Yine, en-boy oranını yönetmenin tek yolu bu değildir; bu, içeriğinizin ne sıkıştırıldığından ne de kesildiğinden emin olmak için çok basittir. Şekil dışarı ne olmasını istediğini pencerenizdir, geniş boyunda, ya da her ne zaman; sonra matematiğini hesaplayın.


ÇOK anlayışlı yanıt için teşekkür ederiz. Sorumu yeterince ötesinde yanıtladı.
Chris Henderson
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.