2B oluşturma için derinlik arabelleğinin tam çözünürlüğünü kullanma


9

Ortografik bir projeksiyon kullanarak bir 2D motor için önden arkaya oluşturucu üzerinde çalışıyorum. Aşırı çekilmeyi önlemek için derinlik tamponunu kullanmak istiyorum. 16 bit derinlik arabelleğe sahibim, Z = 100'de Z = 0, zNear 1 ve zFar 1000 olan bir kamera var. altında olan herhangi bir şey.

Ancak Z pozisyonlarının Z tampon değerleri ile sonuçlanma biçiminin doğrusal olmadığını biliyorum. 16 bit derinlik arabelleğinin tam çözünürlüğünü kullanmak, yani 65536 benzersiz değerlere izin vermek istiyorum. Bu nedenle, oluşturulan her hareketli grafik için, Z konumunu bir sonraki benzersiz derinlik tampon değeri ile ilişkilendirmek için bir sonraki konuma yükseltmek istiyorum.

Diğer bir deyişle, her hareketli grafiğin benzersiz bir derinlik tampon değeri olması için hareketli grafiğin artan bir indeksini (0, 1, 2, 3 ...) uygun Z konumuna çevirmek istiyorum. Bunun arkasındaki matematikten emin değilim. Bunu yapmak için hesaplama nedir?

Not WebGL'de çalışıyorum (temelde OpenGL ES 2) ve geniş bir donanım yelpazesini desteklemem gerekiyor, bu nedenle gl_FragDepth gibi uzantılar bunu daha kolay hale getirebilse de, uyumluluk nedenleriyle kullanamıyorum.


Herhangi bir alfa saydamlık / harmanlama bahsetmiyorum, z tampon yazma, hesaplamalar ve karşılaştırmalar doku önden kopyalamaya karşı tüm ekledikten sonra z tamponu (varsa) size bir performans kazancı sunacak hayal edemiyorum sıkıntıların.
Matt Esch

@MattEsch: Fikir, tüm bu hesaplamaların GPU'da inanılmaz yüksek hızlarda yapılması, bu yüzden bunu yapmak mantıklı.
Panda Pijama

@MattEsch: FWIW bu, özel GPU bellek yerine sistem belleği kullanan Intel tümleşik GPU'lara yöneliktir. Bu, onları oldukça yavaş ve çok sayıda sprite çekilirse doluluk oranı sınırlarına ulaşmaya yatkın hale getirir. Intel bana bu yaklaşımı bir çözüm yolu olarak önerdi. Muhtemelen derinlik testi uygulamaları iyi optimize edilmiştir ve çok sayıda doluluk oranından tasarruf edebilir. Yine de görülmeye devam ediyor, henüz profilli değilim!
AshleysBrain

@PandaPajama blok kopyalama belleği aslında gerçekten hızlıdır, bu yüzden dokuları bir yüzeye örttüyseniz gerçekten çok hızlı olurdu. İlk büyük yük, GPU'ya ilk etapta veri almaktır, bu da Ashley'in işaret ettiği gibi entegre GPU'larda daha pahalı olabilir. Birçok 3d oyunun bile CPU üzerinde önemsiz bir iş yaptığını görüyorsunuz (kemik animasyonu gibi), çünkü bu matris hesaplamalarını yapmak için gereken verileri yüklemek çok pahalı.
Matt Esch

@MattEsch: Sadece blitting ile yapabileceğiniz çok şey var. Rotasyonlar, ölçeklendirme ve deformasyonlar akla geliyor, ancak piksel / tepe noktası gölgelendiricilere sahip olduğunuzdan, donanımla yapabileceklerinizin sınırı, sadece blitting ile yapabileceğinizden çok daha yüksek.
Panda Pijama

Yanıtlar:


5

Gerçekten de, z-buffer'da depolanan değerler, nesnelerinizin gerçek z koordinatlarına değil, arka düzlemine daha yakın olandan daha fazla çözünürlük vermek için nesnelerin gerçek z koordinatlarına doğrusaldır.

Ne yapmak sen senin haritasına olmasıdır zNearetmek 0ve sizin zFariçin 1. İçin zNear=1ve zFar=2bu gibi görünmelidir

Zbuffer

Bunu hesaplamanın yolu şu şekilde tanımlanır:

z_buffer_value = k * (a + (b / z))

Nerede

 k = (1 << N), maximum value the Z buffer can store
 N = number of bits of Z precision
 a = zFar / ( zFar - zNear )
 b = zFar * zNear / ( zNear - zFar )
 z = distance from the eye to the object

... ve z_buffer_value bir tamsayıdır.

Yukarıdaki denklem, z-tamponları gerçekten iyi bir şekilde açıklayan bu harika sayfanın izniyle size getirilmiştir .

Yani, gerekli bulmak için zbelirli bir için z_buffer_value, biz sadece temizlemek z:

z = (k * b) / (z_buffer_value - (k * a))

Cevap için teşekkürler! Yine de son formülünüzü nasıl aldığınız konusunda biraz kafam karıştı. z_buffer_value = k * (a + (b / z))Çözmek için alıp basitçe yeniden düzenlersem z, o zaman şunu elde ederim: z = b / ((z_buffer_value / k) - a)- farklı son formüle nasıl geldiniz?
AshleysBrain

@AshleysBrain: paydayı alıp (v / k) - a => (v - k * a) / kdaraltırsın (k * b) / (v - (k * a)). Aynı sonuç.
Panda Pijama

Ah, anlıyorum. Cevabınız için teşekkürler, güzel çalışıyor!
AshleysBrain

0

Belki daha basit bir şeye yaklaşımınızı değiştirmelisiniz. Ne yaparım; Z derinliğinizi koruyun, ancak oluşturduğunuz şeyin bir listesini tutun. Bu listeyi z Derinlik değerine göre sıralayın ve nesneleri liste sırasına göre oluşturun.

Umarım bu yardımcı olabilir. İnsanlar her zaman işleri basit tutmamı söylüyor.


1
Üzgünüm, bu pek yardımcı değil. Bunu zaten yapıyorum. Soru, Z'nin hangi pozisyonları seçeceğiyle ilgilidir.
AshleysBrain

0

Oluşturulacak şeylerin sıralı bir listesine (önden arkaya) zaten sahip olduğunuzdan Z dizinini artırmanız gerekiyor mu? "Kontrol fonksiyonu" için "daha az veya eşit" kullanamaz mısınız? Bu şekilde, aslında belirli bir pikselin çizilip çizilmediğini kontrol eder.


"daha az ya da eşit" yine de kesinlikle her şeyin abartılmasına neden olacaktır, çünkü her şey her zaman eşit bir Z indeksine sahip olacaktır ve bu nedenle geçiş derinlik testi yapılacaktır.
AshleysBrain
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.