Minecraft'taki gibi suyun derinlikte daha koyu görünmesini nasıl sağlayabilirim?


24

Minecraft'ta suya baktığınızda daha koyu olana bakarsınız. Böyle bir şeyi nasıl kodlayacağını bilen var mı?

Etkili Minecraft etkisi ile minecraft

etkisi olmadan benzer oyun etkisi olmadan benzer oyun


18
Su küpünün malzemesi yarı saydam olduğundan bu otomatik olarak yapılmaz mı?
pek,

Sanmıyorum Karşılaştırma için etkisi olmayan bir resim ekledim.
Xavier

2
Belki de sadece su küplerine uygulanan katkı maddesi karışımı etkisidir? Yine, malzeme yarı saydam olduğundan bu kolay olmalıdır.
pek,

1
ayrıca kutuların rengini derinliğe göre de değiştirebilirsiniz.
Ali1S232

Yanıtlar:


51

Suyu aydınlatmak için derinliğe dayalı olarak temelde iki farklı yaklaşım vardır:

Voksel Aydınlatma

Minecraft voksel esaslı aydınlatmayı kullanır; bu, bitişik küplere ışık yayılarak çalışır ve blok tipine bağlı olarak parlaklığı azaltır. Karanlık okyanuslar bu sistemin bir yan etkisidir.

Su güneş ışığını bloke eder ve ışığı blok başına 3 seviye azaltır (varsayılan 1 seviye yerine), bir okyanustaki parlaklık, yüzeyden her mesafeye göre:

0 (surface): 15 (direct sunlight)
1:           12
2:            9
3:            6
4:            3
5 and below:  0 (darkness)

Kaynak: Minecraft Wiki - Işık

Mesafeye Dayalı Gölgeleme

Geleneksel aydınlatma modeline sahip oyunlarda, bu etki ışık kaynağı ile okyanus tabanı arasındaki su miktarı ölçülerek yaratılabilir. Işık daha sonra bu mesafeye bağlı olarak kaybolur. Bunu yapmanın birkaç yöntemi vardır:

Doğrudan hesaplama

Düz bir yüzeye sahipseniz, yüzeyi normal olarak su kütlesinden uzağa \ Vec {n}ve bu normalin nokta ürününe ve bir yüzey pozisyonunu sgeometri gölgelendiricisine geçirirseniz ışığın suya kat ettiği mesafeyi kolayca hesaplayabilirsiniz .

Etkili su mesafesi

\ max (\ left (s - \ vec {n} \ cdot \ vec {p} \ right), 0) \ cdot \ left (1 + \ tan (\ alpha) \ right)

burada \ Vec {s}tepe pozisyonu ve alfasu gövdesine doğru, normal ışık yüzeyinin altında yönü ve su yüzeyinin arasındaki açıdır.

Gün batımında, alfasuya girerken ışık kırıldığı için sadece 50 ° 'nin biraz altına ulaşır.
İşte iyi bir açıklama ile bir blog yazısı: Dijital Kamera: Toplam İç Yansıma
Daha fazla ayrıntı içeren başka bir yazı: Dijital Kamera: Snell'in Kırılma Yasası

Suya paralel bir yüzeyde bir yükseklik haritası kullanıyorsanız, \ left (s - \ vec {n} \ cdot \ vec {p} \ sağ)olur \ left (s - s \ sağ). Güneş doğrudan su yüzeyinin üzerinde ise doğru faktör 1'e eşittir.
Bir nokta ışığıyla, alfaışık kaynağının göreceli konumuna bağlı olarak her köşe için hesaplamanız gerekir .

Sabit bir su seviyesi veya sabit bir ışık yönü ile denklemin parçaları sabittir ve performans nedenleriyle gölgelendiricide hesaplanmamalıdır.

Artıları:

  • Hızlı ve doğru

Eksileri:

  • Yalnızca düz su yüzeyleri için veya doğrudan yukarıdan gelen ışık için çalışır, çünkü yalnızca bir yüzey normal olarak dikkate alınır. (Pürüzlü bir yüzeyin ve yatırılmış ışığın kombinasyonu, paralaks haritalaması ile biraz uzayabilir.)
  • Caustics yok

Gölge Eşleme

Su yüzeyini ayrı bir derinlik haritasına getirirseniz (ışık kaynağından görüldüğü gibi), o derinlik dokusunu, ışığın yüzeye çarpmadan önce su içinde kat ettiği mesafeyi hesaplamak için kullanabilirsiniz.
Bunu yapmak için, her bir noktayı ışık kaynağının tepe noktası gölgelendiricisindeki görünüm projeksiyonuna yansıtır ve doku gölgesini piksel gölgelendiricisinde ararsınız.

Yüzey nispeten düz ise, daha iyi sonuçlar için kırılmış bir ışık orijini kullanmalısınız.

Artıları:

  • Kendini tıkamadığı sürece nispeten karmaşık su geometrisi ile çalışır. *
  • Hemen hemen her türlü kısmen saydam cilt için tekrar kullanılabilir.

Eksileri:

  • Doğrudan hesaplamadan daha yavaş.
  • Derinlik haritası için ek VRAM gerekir.
  • % 100 doğru değil.

* Işığın POV'sundaki derinliği aşağıdaki gibi sayarak en yakın katı yüzeyin önündeki su miktarını belirleyebilirsiniz:

  1. Sahnedeki katı geometriyi normal olarak göster. Her parça için derinlik değerini sonuç dokusuna eklersiniz.
  2. Derinlik tamponunu güncellemeden suyun ön yüzlerini işleyin ve parçaların derinliklerini sonuçtan çıkarın.
  3. Arka yüzleri de aynı şekilde oluşturun, ancak sonuca parça derinliğini ekleyin.

Sonuç dokusu şimdi ışık-görüş alanında ışığın önündeki su miktarını içerir, bu yüzden kullanmadan önce değerin geri dönüştürülmesi gerekir. Bu yöntem, yönlü ışığı (eksi kırılma) hesaplamak için çalışır, ancak yüzeyler çok düzensizse ve aynı parçaları etkileyen su kütleleri arasında çok miktarda hava varsa, hatalı ortam ışığına yol açar.
Artıları ve eksileri, normal gölge haritalama ile aynıdır, ancak derinlik hesaplanırken bir tampona daha ihtiyacınız vardır ve performans daha kötüdür çünkü daha fazla geometri çizmeniz gerekir.

Işın izleme

Işın takibi, şeffaf hacimleri oluşturmak için bugüne kadar en doğru fakat aynı zamanda en pahalı çözümdür. Bunu yapmanın iki yolu vardır: 1. Okyanus tabanından yüzeye doğru ve 2. Işık kaynağından suya doğru. Parlaklığı hesaplamak için zemindeki her nokta için birden fazla ışın gerekir.

Artıları:

  • Her geometri ile doğru çalışır.
  • Doğru kostikler!

Eksileri:

  • Yavaş!

Ek etkiler

Su arıtırken dikkate alınması gereken birkaç şey var:

Sis

Gözlemciye seyahat ederken sudaki ışık tekrar dağılır, bu nedenle onu düz bir renge karıştırmalısınız.

Gözlemci suya batırılmışsa , derinlik tamponunun son sonucuna göre sis oluşturabilirsiniz. Sis rengi, ancak yoğunluğu değil, gözlemcinin yüzeyden olan uzaklığı ile değişmelidir! (Minecraft, efektin yalnızca bu bölümünü kullanır.)

Gözlemci suya yukarıdan bakarsa, suyla yüzey ve su altındaki geometri arasındaki derinlik farkını temel alarak hesaplamanız gerekir. Sis rengi daha büyük derinlik farklılıklarıyla biraz daha koyulaşmalı, ancak sisin tamamen opak olduğu noktaya geçmelidir.

Sis rengi ayrıca her piksel için görüş yönüne de bağlı olmalıdır, bu nedenle her iki durumda da bakarken biraz daha koyu olur.

Sahte Caustics

Sahte kostikler için bir çıkartma yerine sorunsuz bir döşeme 3D-Texture kullanıyorsanız, dikey yüzeylerde gerilmekten kaçınabilirsiniz. Yüzeye yakın saçılan ışığın gücü üç boyutta değişir, bu nedenle 2D-Doku kullanmak genellikle sahnenin herhangi bir yerinde gerilmesini sağlar. Değişen ışık açılarını, zeminin tepe konumlarını farklı bir koordinat sistemine yansıtarak modelleyebilirsiniz.

Başka bir olasılık, ışığın koordinat sistemindeki yüzey pozisyonuna göre ışık yoğunluğunu hesaplamaktır, ancak bu muhtemelen bir performansa mal olacaktır.

Kostikler, artan derinliğe sahip dağınık ışıktan daha hızlı solmalıdır.

Renk gradyanı

Renkler farklı şekilde dağılmıştır, bu nedenle ışık rengi artan derinlikle değişmelidir. Bu ayrıca, örneğin bir plajın su yüzeyiyle kesiştiği ani kenarları da önler.

Geliş açısı

Kırılma nedeniyle, ışık okyanus tabanına normalde olduğundan daha dik vurur. Snell kanunu hakkında Wikipedia makalesi açıları ve vektörler için formüller vardır.


6

Minecraft'taki gökyüzü ışıklandırma etkisinin dümdüz olduğuna inanıyorum - güneş nerede olursa olsun, üstlerindeki şeylerin gölgesi altında. Daha sonra, fenerler vb. Gibi yerel aydınlatma, düşürme etkisi ile uygulanır - ışık kaynağından uzaklaştıkça, küp ne kadar az ışık alırsa.

Bu şekilde yapılırsa, her su tabakası, altındaki tabakayı kümülatif olarak gölgeleyecek, böylece her biri giderek koyulaşacaktır. Ağaç yaprakları bu şekilde gölge sağlar, ancak kümülatif değildir. Bir ağacın altında aynı gölgeyi 1 veya 100 yeşillik küp olsun.

Bunun kullanılan metot olduğuna dair bir ipucu, izleyiciden uzaklaştıkça suyun kararmayacağı - sadece aşağı indiğiniz zaman. Evet, sis efekti belli aralıklarla devreye giriyor ancak suyun karanlık efekti yok.

Bu yüzden aydınlatmayı hesaplamanın temel formülü sözde kodda böyle bir şey olurdu ...

light_on_cube = 1.0
for each cube above target cube, from lowest to highest {
   if cube being examined is tree foliage
      light_on_cube = 0.5
   else if cube being examined is water
      light_on_cube = light_on_cube - 0.1
   else if cube being examined is solid 
      light_on_cube = 0
}

Bu, bu yöntemi kullanarak bir çıkıntının altında zifiri karanlık olacağından, çıkıntıların altındaki veya mağaralardaki aydınlatmanın hesaplanması için mükemmel değildir. Ancak, hem yerel ışık kaynaklarına (fenerler, yangınlar vb.) Hem de güneşten yanmış blokları ışık kaynakları olarak muamele etmek eklenebilir. Böyle bir şey yapabilir ...

  1. Her küp için doğrudan yukarıdan (yukarıdaki sahte kodla) güneşten gelen ışığı hesaplayın.
  2. Bir küpün yanında bir ışık kaynağı varsa, tamamen yandığını düşünün (1.0)
  3. Bir küp doğrudan yukarıdan güneş almıyorsa, tamamen aydınlatılmış bir küpten ne kadar uzakta olduğuna bağlı olarak biraz ışık verin. Daha yakın, daha fazla ışık demektir, daha uzakta daha uzak demektir (sıfıra kadar).

Buradaki fikir, eğer bir küp güneş veya bir fener tarafından aydınlatılıyorsa, yanındaki küpün de bir şekilde yanacağıdır. Ve o uzaktaki küpten uzaklaştıkça, o kadar az ışık olacak. Dağınık aydınlatmayı tahmin etmek için bir çeşit çamur yolu ama bence işe yarayacak mı?


1
Evet, bilet olduğuna eminim. Oyunumda benzer bir şey yaptım.
MichaelHouse

Bu arada, blogunuzu Google Reader listeme ekledim Byte56 - geliştirici blogları FTW!
Tim Holt,

Oh, neden teşekkür ederim? Hala bu konunun dışında, ama ben sadece Profesör Bailey'nin sınıfı hakkında blogunu okudum. Geçen sene o sınıftaydım! Geçen yıl da o sunumu yaptığına eminim. Adının tanıdık olduğunu düşündüm. Küçük dünya :)
MichaelHouse

3

Belki de soruyu yanlış anlıyorum ama neden derinliklerine bağlı olarak blokların rengini değiştiremiyorsunuz?

Derinlik d'ye sahipseniz (bloklar halinde, 0'dan başlayarak) o zaman parlaklık için makul bir denklem şöyle olacaktır:

L = (1- m ) e - kd + m

Kod: L = (1.0 - m) * exp(-k * d) + m;

k ne kadar hızlı kararır (yüksek = daha hızlı). Makul bir değer 0,5 olacaktır.
m istediğiniz minimum parlaklıktır.
L 0 ila 1 arasında değişir.

Kullanmakta olduğunuz grafik API'sindeki blokların rengini nasıl değiştireceğinizi bilmiyorsanız, lütfen ayrı bir soru olarak (hangi API'yi kullandığınızı ve gölgelendiricileri kullanıp kullanmadığınızı belirterek) sorunuzu sorun.


Ben sadece bunu yapmayı düşünmedim. Sadece meraktan bu denklemi nereden aldın?
Xavier

1
@ Xavier: Daha yeni yaptım. e^-kdBiraz yavaş yavaş bazı değere (derinlik) üzerinden sıfıra doğru eğilimi şeyler için standart bir fonksiyondur sadece bir üstel bozunma vardır. Çarpma (1-m)ve ilavesi m, çürümeyi en aza mindirecek ve hala başlangıçta olacak şekilde ölçeklendirmek ve dengelemek içindir 1. en.wikipedia.org/wiki/Exponential_decay
Peter Alexander

Durum şu ki, daha derin bir renk tonunun blokları sadece blokların alfa renkleri varsa görülecektir; Bu durumda, blok rengini değiştirmeye gerek yoktur, alfa efekti otomatik olarak oluşturur.
Jonathan Connell,

@Jonathan: Su bloklarını yapmazsın, blokları deniz yatağında rengin koyulaşmasıyla ve sonra da su yüzeyinde tek bir alfa tabakasına sahip olursun.
Peter Alexander

@Peter Alexander Tamam, bu tip blok oyunlarında suyun bile bloklardan yapıldığını varsaydım.
Jonathan Connell,
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.