Göze yakın klips düzleminden daha yakın olan kırpma köşelerini nasıl kullanmalıyım?


13

Kendi 3D motorumu JavaScript'te yuvarlıyorum ve sadece tuval çizimi kullanıyorum, WebGL kullanmıyorum. Bu başka bir Minecraft klonu; Kutuları seviyorum, beni yargılama.

Şimdiye kadar, tek bir şey hariç her şey harika çalışıyor: 3D'de, bazı köşeler yakın kırpma düzleminin arkasına geçtiğinde, ekrandaki yansımaları garip çıkıyor (bir uçağı izlemek için kullanılan diğer köşelerin önünde olduğu varsayılarak).

Bu noktaları kırpmayı denedim ama sonra bu köşeleri kullanan yüzeylerde görüyorum. WebGL / OpenGL'de grafik kartı bu noktalarla ilgilenir ve uçak doğru bir şekilde oluşturulur, ancak donanıma erişimim yok, bu yüzden bunu kendim kodlamalıyım.

Ne yapacağımdan tam olarak emin değilim, şu anda akla gelen son şey, oyuncunun yakın kırpma düzleminin arkasındaki noktaların projeksiyonunu tersine çevirmek. tepe noktası.

İşte düşüncelerim:

resim açıklamasını buraya girin

Ne olduğunu gösteren bazı resimler:

resim açıklamasını buraya girin

Uzaktan mavi kutu mükemmel bir şekilde işliyor.

resim açıklamasını buraya girin

Bazı köşeler oyuncunun yakın kırpma düzleminin arkasına geçtiğinde ters projeksiyon yaparım, ancak doğru görünmüyor:

focalLength *= -1;
2d.x = x*focalLength/z;
2d.y = y*focalLength/z;

Yüzlerini çizmek için kullanılan tüm köşeler oynatıcının arkasında olduğundan arkadaki gri kutunun tamamen kaldırıldığını unutmayın.

resim açıklamasını buraya girin

Yukarı veya aşağı baktığında olan şey budur.

Bunun arkasındaki matematiği ne yapacağımı bilmiyorum, birisinin aynı problemle zaten karşılaştığını ve bana yardımcı olabileceğini umuyorum.


1
Noktaları daha yakın yakın klip düzlemine göre gözle varsa, bunlar gerektiği kırpılır - ve bu gerçekten bir nesnenin "aracılığıyla" bakalım olabilir. Bu tipik davranıştır; çarpışma normalde bu görsel artefaktı önler. Kırpma çözümünüzde yanlış olan tek şey bu muydu?

@JoshPetrie: Noktaların kırpılması gerektiğini anlıyorum, ancak bunu yaparsam tüm çizim çizim rutininin geçmesi gereken köşelerden biri veya ikisi kaybolacak ve oyuncu 2d'de görebilecektir. o kare boyunca. Onların karenin hala çizilebilmesi için tuvalin dışında (projeksiyonda) olmalarını istiyorum. Yeterince açık olup olmadığımdan emin değilim.
Solenoid

Sen edilir - O normal bir davranıştır söylüyorum ve gelen oyuncuyu engelleyerek Bunu engellemek isteyen alma küpleri birine bu kadar yakın. Bunu gerçekten yapmak istiyorsanız, üçgenleri kırpmanız gerekir ancak yeniden yapılandırmalısınız (muhtemelen). Bu, özellikle de dokularınız varsa, olağandışı görünecektir. Söylediğim şey mantıklı değilse, sohbette bize katılabilirsiniz, böylece gerçekten konuşkan bir yorum dizisi oluşturmayız.

Söylediğiniz şey mantıklı, yeniden yapılandırmak çok zaman alıyor, bu yüzden çözüm değil. Oyuncunun arkasındaki 2d düzleminde hala bu tepe noktasını çizmenin bir yolu olduğunu umuyordum, böylece lineTo(x,y)işlev hala çağrılabilirdi, sadece nasıl davrandığını bilmiyorum ... bu tuhaf bir boyut, katılıyorum.
Solenoid

Bu eğiticiye bir göz atın , tek tek üçgenlerin ve nesnelerin bir bütün olarak kırpılmasının nasıl hesaplanacağını açıklar
ѕняєє ѕιиgнι

Yanıtlar:


1

Yakın kırpma düzleminin amacı, bir kırpma düzlemi olmasıdır . Kırpma düzleminin dışındaki üçgenler kırpılır : kalan parçalar her zaman kırpma bölgesi içinde olacak şekilde parçalara ayrılır.

İsterseniz yakın klibi görmezden gelmeyi deneyebilirsiniz. Gerçekten de OpenGL ve D3D, yakın düzlem kırpmayı tamamen kapatma yollarına sahiptir (derinlik tamponunun hala minimum bir yakın değere sahip olmasına rağmen). Sorun yakın klip değil.

Sorun, kameranın arkasındaki köşelerde .

Kameranın arkasında bulunan üçgenleri oluşturamazsınız. Perspektif izdüşümüyle değil. Bu üçgenler perspektif projeksiyonlarının ardındaki matematik altında mantıklı değil. Dahası, onlar da frustum dışında.

Kırpmanın yakınında kapatmak bir frustumu bir piramide dönüştürür. Piramidin noktada durmasının nedeni, piramidin üzerindeki noktaların piramidin dört kenarının da arkasında olmasıdır. Böylece kameranın arkasındaki herhangi bir nokta (piramidin ucu), ekranın görünür bölgesinin üstünde, altında, solunda ve sağındadır. Hepsi aynı anda.

Söylediğim gibi: kameranın arkasındaki perspektif projeksiyonu altındaki köşeler anlamlı değil.

Kırpmayı uygulamalısınız. Klips boşluğunda ( perspektif bölünmesinden önce ) bir üçgenin tepe noktasının kameranın arkasında olduğunu tespit etmelisiniz . Öyleyse, yalnızca kameranın önünde bulunan üçgenler oluşturacak şekilde bu üçgeni kırpmanız gerekir.

Bu basit bir süreç değil. Sadece homojen koordinat sistemleri hakkında tam bir anlayışa sahipseniz mantıklı olan matematik içerir. Alternatif olarak, herhangi bir tepe noktası kameranın arkasındaysa, herhangi bir üçgeni düzeltebilirsiniz.


Şimdiye kadar tüm üçgeni söktüm, ama sonra uçağı gördüm (yukarıdaki resimlere bakın). Neden geometrik olarak anlamlı olmadığını anlamak için bir resme ihtiyacım vardı. Tek çözüm, köşelerden biri kırpma düzleminin arkasındayken düzlem çizgisi kesişimini hesaplamak ve çizgiyi öndeki tepe noktasından izlemek için kullanmaktır, ne yazık ki bu pahalıdır.
Solenoid

0

Yakın düzlemin arkasındaki üçgenin bir kısmı piksel konumunun kırpma düzleminin arkasında olup olmadığını görmek için piksel başına kontrol yapabilir misiniz?

Yakın uçağa herhangi bir kırpma uçağı gibi davranabilirsiniz. Örneğin, kırpma düzlemleri su düzlemleri (yansımalar ve kırılmalar için) gibi şeyler için kullanılır. Bu kırpma düzleminin, yakın kırpma düzlemi gibi çalışacağını ve piksel başına klip alacağını düşünürdüm.

DirectX ile HLSL'de kırpma düzlemlerini nasıl kullanacağımı biliyorum, ancak bunların uygulanması özel olabilir. Bunun için bilgi tutabiliyorsanız yardımcı olabilir.

Ayrıca, size yardımcı olabilecek bir bağlantı: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter42.html


Piksel testi Javascript gibi yorumlanmış bir dilde son derece pahalı, şimdi olduğu gibi zar zor kabul edilebilir fps alıyorum.
Solenoid
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.