Bir fragman gölgesinde rastgele sayıda ışık kullanmanın bir yolu var mı?


19

Parça gölgelendirici için rasgele sayıda ışık konumunu (ve renkleri) geçirmenin ve gölgelendiricinin üzerinde döngü yapmanın bir yolu var mı?

Değilse, o zaman birden fazla ışığın nasıl simüle edilmesi gerekir? Örneğin, dağınık yönlü aydınlatma ile ilgili olarak, gölgelendiricinin ışık ağırlıklarının toplamını geçemezsiniz.


WebGL ile çalışmıyorum, ancak OpenGL'de en fazla 8 ışık kaynağınız var. Bence, bundan daha fazlasını geçmek istiyorsanız, örneğin tekdüze değişkenleri kullanmalısınız.
zacharmarz

Eski yöntem her zaman tüm ışıklardan geçmekti, kullanılmayan ışıklar 0 parlaklığa ayarlandı ve bu nedenle sahneyi etkilemezdi. Muhtemelen artık çok kullanılmıyor ;-)
Patrick Hughes

7
Google gibi bir şey yaptığınızda, 'WebGL' terimini kullanmayın; teknoloji, bu sorunlara yaklaşırken bile insanların sahip olamayacağı kadar genç. Örneğin bu aramayı ele alalım, 'Kendimi şanslı hissediyorum' işe yarardı. Bir WebGL sorununun tam olarak aynı OpenGL problemine dönüşmesi gerektiğini unutmayın.
Jonathan Dickinson

İleri işlemede 8'den fazla ışık için genellikle çok geçişli bir gölgelendirici kullanıyorum ve her geçişe katkı harmanlaması kullanarak işlemek için farklı bir 8 ışık grubu veriyorum.
ChrisC

Yanıtlar:


29

Bununla başa çıkmak için genellikle iki yöntem vardır. Günümüzde bunlara ileri işleme ve ertelenmiş işleme denir. Bu iki konuda aşağıda tartışacağım bir varyasyon var.

İleri işleme

Etkileyen her ışık için her nesneyi bir kez oluşturun. Buna ortam ışığı da dahildir. Ek bir karışım modu ( glBlendFunc(GL_ONE, GL_ONE)) kullanırsınız, böylece her ışığın katkıları birbirine eklenir. Farklı ışıkların katkısı katkı maddesi olduğundan, çerçeve tamponu sonunda değeri alır

Kayan noktalı bir çerçeve arabelleğine görüntü oluşturarak HDR alabilirsiniz. Daha sonra, HDR aydınlatma değerlerini görünür bir aralığa indirmek için sahnenin son geçişini yapın; bu ayrıca çiçeklenme ve diğer post-efektleri uyguladığınız yer olacaktır.

Bu teknik için ortak bir performans geliştirmesi (sahnede çok fazla nesne varsa), renk çerçevesine herhangi bir şey çizmeden tüm nesneleri oluşturduğunuz ( glColorMaskrenk yazmalarını kapatmak için kullanın) bir "ön geçiş" kullanmaktır . Bu sadece derinlik tamponunu doldurur. Bu şekilde, başka bir nesnenin arkasındaki bir nesneyi oluşturursanız, GPU bu parçaları hızlı bir şekilde atlayabilir. Köşe gölgelendiricisini çalıştırması gerekir, ancak tipik olarak daha pahalı fragman gölgelendirici hesaplamalarını atlayabilir.

Bu kodlanması daha basit ve görselleştirilmesi daha kolaydır. Ve bazı donanımlarda (esas olarak mobil ve gömülü GPU'lar), alternatiften daha verimli olabilir. Ancak üst düzey donanımda, alternatif genellikle çok fazla ışık içeren sahneler için kazanır.

Ertelenmiş oluşturma

Ertelenmiş oluşturma işlemi biraz daha karmaşıktır.

Bir yüzeydeki bir nokta için ışığı hesaplamak için kullandığınız aydınlatma denklemi aşağıdaki yüzey parametrelerini kullanır:

  • Yüzey konumu
  • Yüzey normalleri
  • Yüzey dağınık rengi
  • Yüzey aynasal rengi
  • Yüzey spekülerliği
  • Muhtemelen diğer yüzey parametreleri (aydınlatma denkleminizin ne kadar karmaşık olduğuna bağlı olarak)

İleri işleme sırasında, bu parametreler, doğrudan tepe gölgelendiricisinden geçirilerek, dokulardan çekilerek (genellikle köşe gölgelendiricisinden geçirilen doku koordinatları aracılığıyla) veya diğer parametreler. Dağınık renk, köşe başı rengi bir doku ile birleştirerek, birden fazla dokuyu birleştirerek hesaplanabilir.

Ertelenmiş görselleştirmede, bunu açıkça ortaya koyuyoruz. İlk geçişte tüm nesneleri yaratıyoruz. Ancak renkleri oluşturmayız . Bunun yerine, yüzey parametrelerini oluşturuyoruz . Böylece ekrandaki her pikselin bir dizi yüzey parametresi vardır. Bu, ekran dışı dokulara renderleme yoluyla yapılır. Bir doku, dağınık rengi RGB'si olarak ve muhtemelen aynasal parlaklığı alfa olarak depolardı. Başka bir doku aynasal rengi depolardı. Üçte biri normali depolar. Ve bunun gibi.

Konum genellikle kaydedilmez. Bunun yerine, buraya girmek için çok karmaşık olan matematik tarafından ikinci geçişte yeniden oluşturulur. Bir yüzeydeki noktanın kamera-boşluk konumunu anlamak için girdi olarak derinlik tamponunu ve ekran-boşluk parçası konumunu kullandığımızı söylemek yeterlidir.

Şimdi, bu dokular sahnedeki her görünür piksel için tüm yüzey bilgilerini esas aldığından, tam ekran dörtlü oluşturmaya başlıyoruz. Her ışık tam ekran dörtlü render alır. Yüzey parametre dokularından örnek alıyoruz (ve konumu yeniden oluşturuyoruz), sonra sadece bu ışığın katkısını hesaplamak için kullanıyoruz. Bu (tekrar glBlendFunc(GL_ONE, GL_ONE)) görüntüye eklenir . Işıklar bitene kadar bunu yapmaya devam ediyoruz.

HDR yine süreç sonrası bir adımdır.

Ertelenmiş oluşturma işleminin en büyük dezavantajı, kenar yumuşatmadır. Kenar yumuşatma için biraz daha fazla çalışma gerektirir.

GPU'nuzda çok fazla bellek bant genişliği varsa, en büyük artış performanstır. Gerçek geometriyi yalnızca bir kez (veya gölge eşleme yapıyorsak gölgeli ışık başına 1 + 1) oluştururuz. Biz asla bundan sonra görünmüyorsa gizli piksel veya geometri herhangi bir zaman harcamak. Tüm aydınlatma geçiş süresi gerçekte görünen şeylere harcanmaktadır.

GPU'nuzda çok fazla bellek bant genişliği yoksa, ışık geçişi gerçekten acımaya başlayabilir. Ekran pikseli başına 3-5 dokudan çekmek eğlenceli değildir.

Hafif Geçiş

Bu, ilginç ödünleşmelere sahip ertelenmiş görselleştirmedeki bir çeşitlemedir.

Ertelenmiş oluşturma işleminde olduğu gibi, yüzey parametrelerinizi bir dizi arabellek haline getirirsiniz. Ancak, kısaltılmış yüzey verileriniz var; bu kez önemsediğiniz tek yüzey verisi, derinlik tampon değeri (pozisyonun yeniden yapılandırılması için), normal ve aynasal parlaklıktır.

Sonra her ışık için sadece aydınlatma sonuçlarını hesaplarsınız. Yüzey renkleri ile çarpma yok, hiçbir şey. Tamamen yüzey renkleri olmadan sadece nokta (N, L) ve aynasal terim. Aynasal ve yaygın terimler ayrı tamponlarda tutulmalıdır. Her ışık için speküler ve dağınık terimler iki tampon içinde toplanır.

Ardından, yüzey rengiyle son kombinasyonu yapmak için toplam speküler ve dağınık aydınlatma hesaplamalarını kullanarak geometriyi yeniden oluşturursunuz, böylece genel yansıma üretilir.

Buradaki artışlar, çoklu örneklemeyi geri almanızdır (en azından ertelenenlerden daha kolay). Nesne başına oluşturmayı ileri oluşturmaya göre daha az yaparsınız. Ancak bunun ertelenmesi gereken ana şey, farklı yüzeyler için farklı aydınlatma denklemlerine sahip olmak için daha kolay bir zamandır.

Ertelenmiş oluşturma ile, tüm sahneyi ışık başına aynı gölgelendiriciyle çizersiniz. Bu yüzden her nesne aynı malzeme parametrelerini kullanmalıdır. Işık ön geçişi ile her nesneye farklı bir gölgelendirici verebilirsiniz, böylece son aydınlatma adımını kendi başına yapabilir.

Bu, ileri işleme durumu kadar özgürlük sağlamaz. Ancak, yedeklenecek doku bant genişliğiniz varsa hala daha hızlıdır.


-1: LPP / PPL'den bahsedilmemesi. -1 ertelendi: oluşturma, 2009 yılı için temel gereksinimler olan herhangi bir DX9.0 donanımında (evet, 'iş' dizüstü bilgisayarımda bile) anlık bir kazançtır. Ertelenmiş / LPP varsayılan değerdir . Son olarak 'çok fazla bellek bant genişliği' delilik - genellikle PCI-X x4'ü bile doyurmuyoruz, ayrıca LPP bellek bant genişliğini önemli ölçüde düşürüyor. Son olarak, yorumunuz için -1; Bunun gibi döngüler tamam mı? Bu döngülerin çerçeve başına 2073600 kez gerçekleştiğini biliyorsunuz, değil mi? Grafik kartının parlamentosunda bile kötü.
Jonathan Dickinson

1
@JonathanDickinson Sanırım onun anlamı, ertelenmiş / hafif ön geçiş için bellek bant genişliğinin tipik olarak ileri işleme için birkaç kat daha büyük olmasıdır. Bu ertelenmiş yaklaşımı geçersiz kılmaz; sadece seçerken dikkate alınması gereken bir şey. BTW: ertelenen arabellekleriniz video belleğinde olmalıdır, bu nedenle PCI-X bant genişliği önemsizdir; önemli olan GPU'nun dahili bant genişliği. Uzun piksel gölgelendiricileri, örneğin bir açılmamış döngü ile, yararlı bir iş yaptıklarında endişelenecek bir şey değildir. Ve z-buffer prepass hile ile ilgili yanlış bir şey yok; iyi çalışıyor.
Nathan Reed

3
@JonathanDickinson: Bu WebGL hakkında konuşuyor, bu nedenle "gölgelendirici modelleri" ile ilgili herhangi bir tartışma önemsiz. Ve hangi tür renderleme kullanımı "dini bir konu" değildir: sadece hangi donanım üzerinde çalıştığınızla ilgilidir. "Video belleği" nin sadece normal CPU RAM olduğu gömülü GPU, ertelenmiş oluşturma ile çok kötü çalışır. Mobil karo tabanlı bir oluşturucuda, daha da kötüdür . Ertelenmiş oluşturma, donanıma bakılmaksızın "anında kazanç" değildir; her donanımda olduğu gibi, değiş tokuşları da vardır.
Nicol Bolas

2
@JonathanDickinson: "Ayrıca, z-buffer geçiş öncesi hilesi ile çizilmesi gereken nesnelerle z-dövüşünü ortadan kaldırmak için mücadele edeceksiniz." Bu tamamen saçmalık. Aynı nesneleri aynı dönüşüm matrisleri ve aynı köşe gölgeleyici ile oluşturuyorsunuz. Çok geçişli oluşturma 1 gün Voodoo'da yapıldı ; bu çözülmüş bir sorundur. Biriken aydınlatma bunu değiştirmek için hiçbir şey yapmaz.
Nicol Bolas

8
@JonathanDickinson: Ama tel kafes oluşturmaktan bahsetmiyoruz, değil mi? Daha önce olduğu gibi aynı üçgenleri oluşturmaktan bahsediyoruz . OpenGL , aynı nesne için değişmezliği garanti eder (elbette aynı köşe gölgelendiricisini kullandığınız sürece ve hatta o zaman, invariantdiğer durumlarda bunu garanti edecek anahtar kelime vardır ).
Nicol Bolas

4

Ertelenmiş oluşturma veya geçiş öncesi aydınlatma kullanmanız gerekir . Daha eski sabit işlevli boru hatlarından bazıları (okuma: gölgelendirici yok) 16 veya 24 ışığa kadar destekledi - ama hepsi bu . Ertelenmiş oluşturma ışık sınırını ortadan kaldırır; ancak çok daha karmaşık bir oluşturma sistemi pahasına.

Görünüşe göre WebGL, herhangi bir ertelenmiş oluşturma biçimi için kesinlikle gerekli olan MRT'yi destekler - bu nedenle yapılabilir; Ne kadar akla yatkın olduğundan emin değilim.

Alternatif olarak, kutudan çıkar çıkmaz ertelenmiş olan Unity 5'i araştırabilirsiniz .

Bununla başa çıkmanın bir başka basit yolu, ışıkları (belki de, oynatıcıdan uzaklığa ve kamera frustumunda olup olmadıklarına bağlı olarak) önceliklendirmek ve sadece ilk 8'i etkinleştirmektir. çıktı kalitesi hakkında (örneğin, Far Cry 1).

Önceden hesaplanmış ışık haritalarına da bakabilirsiniz . Quake 1 gibi oyunlar bunlardan çok kilometre aldı - ve oldukça küçük olabilirler (bilinear filtreleme gerilmiş ışık haritalarını oldukça güzel bir şekilde yumuşatır). Ne yazık ki önceden hesaplanan% 100 dinamik ışık kavramını hariç tutar, ancak gerçekten harika görünüyor . Bunu 8 ışık sınırınızla birleştirebilirsiniz, örneğin sadece roketler veya benzeri gerçek bir ışık olur - ancak duvardaki ışıklar veya benzeri ışık haritaları olacaktır.

Yan not: Bir gölgelendiricinin üzerinde dolaşmak istemiyor musunuz? Performansınıza veda edin. GPU bir CPU değildir ve örneğin JavaScript'in yaptığı gibi çalışacak şekilde tasarlanmamıştır. Oluşturduğunuz her pikselin (üzerine yazılsa bile) döngüyü gerçekleştirmesi gerektiğini unutmayın; böylece 1920x1080'de ve 16 kez çalışan basit bir döngü alırsanız, bu döngü içindeki her şeyi etkili bir şekilde 33177600 kez çalıştırırsınız. Grafik kartınız bu parçaların çoğunu paralel olarak çalıştıracaktır, ancak bu döngüler hala eski donanımları yiyecektir.


-1: "Ertelenmiş oluşturma kullanmanız gerekiyor" Bu hiç doğru değil. Ertelenmiş oluşturma kesinlikle bunu yapmanın bir yoludur, ancak tek yol bu değildir . Ayrıca, döngüler, özellikle tekdüze değerlere dayanıyorsa, performans açısından o kadar da kötü değildir (yani: her parçanın farklı bir döngü uzunluğu yoktur).
Nicol Bolas

1
Lütfen 4. paragrafı okuyun.
Jonathan Dickinson

2

N ışığı destekleyen bir piksel gölgelendirici (burada n, 4 veya 8 gibi ufacık bir sayıdır) kullanabilir ve sahneyi birden çok kez yeniden çizebilir, her seferinde yeni bir ışık kümesi geçirebilir ve hepsini bir araya getirmek için katkı harmanlamasını kullanabilirsiniz.

Temel fikir budur. Tabii ki bunu makul büyüklükte bir sahne için yeterince hızlı hale getirmek için birçok optimizasyon gerekiyor. Tüm ışıkları, sadece görünür olanları (frustum ve oklüzyon ayıklama) çizmeyin; aslında her geçişte tüm sahneyi yeniden çizmeyin, sadece o geçişteki ışıkların menzilindeki nesneler; gölgelendiricinin farklı sayıda ışığı (1, 2, 3, ...) destekleyen birden fazla sürümüne sahip olmanız gerekir, böylece ihtiyacınız olandan daha fazla ışığı değerlendirmek için zaman kaybetmezsiniz.

Diğer cevapta belirtildiği gibi ertelenmiş oluşturma, çok sayıda küçük ışığa sahip olduğunuzda iyi bir seçimdir, ancak tek yol bu değildir.

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.