1 puan yazan GN⁺ 2 시간 전 | 1 yorum | WhatsApp'ta paylaş
  • Tarayıcı shader’ı, mavi gökyüzünü ve gün batımı/gün doğumunu gerçek zamanlı render etmek için Rayleigh saçılması, Mie saçılması ve ozon soğurmasını birleştirir
  • Kamera ışınının optik derinliği ile Beer's Law geçirgenliği biriktirilir ve saçılım dağılımı, güneş yönüne göre faz fonksiyonu ile hesaplanır
  • Gün batımı efekti, her örnekte güneş yönünde ayrı bir light-march çalıştırarak güneş ışığının atmosferden geçerken ne kadar kaybettiğini yansıtır
  • Düzlemsel gökyüzü shader’ı, depth buffer ve dünya koordinatı yeniden oluşturma ile bir post-processing efekti haline gelir; böylece sahne nesneleri arasındaki atmosferik sis de işlenir
  • Gezegen ölçeğinde bu yapı, logarithmic depth buffer, ray-sphere intersection ve LUT tabanlı Transmittance, Sky-view, Aerial Perspective ile genişletilir

Atmosferik saçılım shader’ının hedefi ve başvuru kaynakları

  • Amaç, uzay mekiği Endeavour’un alçak yörüngeden çekilmiş gün batımı fotoğraflarındaki gibi Dünya’nın üst atmosferinde koyu turuncu, mavi ve uzay arka planının siyahına uzanan katmanları tarayıcı shader’ı ile yeniden üretmektir
  • Uygulama kapsamı, raymarching, Rayleigh saçılması, Mie saçılması ve ozon soğurmasını birleştiren gerçekçi bir sky dome ile başlar; ardından gezegen çevresindeki atmosfer kabuğu ve LUT tabanlı optimizasyonlarla genişler
  • Başlıca kaynaklar Three Geospatial, Sébastien Hillaire’in A Scalable and Production Ready Sky and Atmosphere Rendering Technique makalesi ve Atmospheric Scattering (and also just faking it) sunumudur

Gökyüzü render etmenin temel modeli

  • Basit gradyanın neden yetersiz olduğu

    • Gökyüzü rengi, yalnızca mavi bir arka plan olarak değil, ışığın hava ve onun bileşenleriyle etkileşiminin sonucu olarak ele alınmalıdır
    • Gözlemcinin irtifası, toz miktarı ve günün saati gibi değişkenler dikkate alınmalıdır; hesaplamalar hacim (volume) içinde yapılır
  • Atmosfer yoğunluğunu örnekleme

    • Atmosfer, volumetric clouds veya volumetric light örneklerinde olduğu gibi raymarching ile örneklenir
    • Kamera konumundan bir ışın gönderilir ve saydam ortam boyunca ilerletilir; bu sırada atmosferden geçip hayatta kalan ışık olan geçirgenlik (transmittance) ile her örnekte kamera yönüne yeniden yönlendirilen saçılım (scattering) hesaplanır
    • Raymarching’e tekrar bakmak için Painting with Math: A Gentle Study of Raymarching kaynağına başvurulabilir
  • Rayleigh yoğunluğu ve optik derinlik

    • Geçirgenliği hesaplamak için, ışının yol boyunca karşılaştığı atmosfer yoğunluğu biriktirilerek optik derinlik (optical depth) hesaplanmalıdır
    • Rayleigh yoğunluk fonksiyonu, h yüksekliğinde ne kadar “hava” bulunduğunu gösterir ve irtifa arttıkça atmosferin seyrekleşmesi etkisini yansıtır
    • Örnek uygulama RAYLEIGH_SCALE_HEIGHT = 8.0km, ATMOSPHERE_HEIGHT = 100.0km, VIEW_DISTANCE = 200.0km, PRIMARY_STEPS = 24 kullanır
    • rayleighDensity(h), exp(-max(h, 0.0) / RAYLEIGH_SCALE_HEIGHT) şeklindedir ve döngü içinde viewOpticalDepth += dR * stepSize ile biriktirilir
  • Beer's Law ve gündüz göğünün maviliği

    • Optik derinlikten belirli bir noktadaki geçirgenlik T hesaplanır; T=1.0 ışık kaybı olmadığı, T=0.0 ise ışığın tamamen yok olduğu anlamına gelir
    • Geçirgenlik Beer's Law ile hesaplanır; örnek kod vec3 transmittance = exp(-rayleighBeta * viewOpticalDepth) kullanır
    • rayleighBeta, Rayleigh saçılım katsayısıdır ve shader’da vec3(0.0058, 0.0135, 0.0331) olarak tutulur
    • Güneş ışığı yönü ile bakış ışını arasındaki açı, 3.0 / (16.0 * PI) * (1.0 + mu * mu) biçimindeki Rayleigh phase function ile modellenir
    • Rayleigh saçılım katsayıları nedeniyle kırmızı neredeyse hiç saçılmaz, yeşil biraz daha fazla saçılır ve mavi en çok saçıldığı için gündüz gökyüzü mavi görünür
    • Bu yaklaşım her piksel için tek bir ışına genişletildiğinde, ufka doğru daha fazla atmosferden geçildiği için parlak beyaz bir pus gibi görünür; irtifa arttıkça ise daha derin ve daha koyu bir maviye dönüşür

Mie saçılması ve ozon soğurması

  • Yalnızca Rayleigh’in yetmediği etkiler

    • Yalnızca Rayleigh saçılmasıyla da makul sonuçlar alınabilir, ancak daha gerçekçi bir gökyüzü için ek atmosfer etkileri gerekir
    • Mie saçılması, toz veya aerosol gibi daha büyük parçacıklarla ışığın etkileşimini ifade eder; bir yoğunluk fonksiyonuna ve yönlere göre yeniden dağılımı gösteren bir faz fonksiyonuna sahiptir
    • Ozon soğurması, üst atmosferden geçen ışığın bazı dalga boylarını saçmadan yolundan çıkarır
    • Ozon soğurması özellikle ufukta, gün batımında, gün doğumunda ve alacakaranlıkta gökyüzü rengini daha derin hale getirir ve renkleri kaydırır
  • Mie ve ozonun biriktirilmesi

    • Rayleigh, Mie ve ozonu birlikte kullanan uygulama, ilgili optik derinlikleri viewODR, viewODM, viewODO ile ayrı ayrı biriktirir
    • Her örnekte dR = rayleighDensity(h), dM = mieDensity(h), dO = ozoneDensity(h) hesaplanır ve tau, BETA_R * viewODR, BETA_M_EXT * viewODM, BETA_OZONE_ABS * viewODO toplamından oluşturulur
    • Geçirgenlik exp(-tau) ile hesaplanır; her yoğunluk, geçirgenlik ve stepSize değeri sumR, sumM, sumO içine biriktirilir
    • Nihai saçılım SUN_INTENSITY * (phaseR * BETA_R * sumR + phaseM * BETA_M_SCATTER * sumM + BETA_OZONE_SCATTER * sumO) biçiminde hesaplanır
  • Başlıca sabitler ve etkileri

    • MIE_SCALE_HEIGHT, aerosoller için RAYLEIGH_SCALE_HEIGHT karşılığıdır; parçacıklar genelde ufka yakın yoğunlaştığı için daha küçük bir değer olan 1.2km seçilir
    • MIE_BETA_SCATTER, parçacıkların ışığı kameraya doğru ne kadar saçacağını kontrol eder; çoğunlukla dalga boyundan bağımsız olduğu için vec3(0.003) olarak ayarlanır
    • MIE_BETA_EXT, yoldan ne kadar ışık çıkarıldığını gösteren Mie sönümleme katsayısıdır ve uzak atmosferin daha puslu görünmesini sağlar
    • MIE_G, anizotropiyi kontrol eder; 0.0 düzgün saçılma, 1.0 ise daha güçlü ileri yönlü saçılma eğilimi anlamına gelir
    • OZONE_BETA_ABS, vec3(0.00065, 0.00188, 0.00008) değerine sahiptir; yeşil ile sarı-turuncu tonları daha fazla soğurarak gökyüzü rengini mavi, kırmızı ve mora doğru kaydırır
    • Mie ve ozon birlikte ele alındığında daha doğal bir “sky blue” tonu ve güneş çevresinde puslu bir ışık halesi oluşur; güneş ufka yaklaştığında Mie saçılması etkisi daha belirgin hale gelir

Işık yolları ve gün batımı·gün doğumu

  • Mevcut uygulamanın sınırları

    • sky fragment shader, farklı irtifalarda doğal renkleri render edebilir ve Mie, Rayleigh, ozon geçirgenliği modellerini yansıtabilir
    • Ancak güneş ufka yaklaştırılsa bile ışık zayıflaması ya da gün batımı·gün doğumu etkisi olmadan yalnızca beyaz, puslu bir ışık kümesi görünür
    • Bunun nedeni, mevcut raymarching döngüsünün ışık zayıflamasını yalnızca kameradan her örneğe giden görüş ışını üzerinde hesaplamasıdır
    • Örnek noktasına ulaşmadan önce, güneş ışığının atmosferden geçerken ne kadar kayba uğradığını da hesaplamak gerekir
  • light-march iç içe döngüsü

    • Her örnek noktasında, ışık kaynağı yönünde ayrı bir iç içe döngü çalıştırılarak bu yolun geçirgenliği örneklenir
    • İlgili yaklaşım real-time cloudscapes ve volumetric lighting içinde de kullanılır
    • lightMarch(float start, float sunY), LIGHTMARCH_STEPS kadar yinelenirken odR, odM, odO değerlerini biriktirir
    • Mevcut uygulamadaki optik derinlik viewODR, viewODM, viewODO üzerine güneş yönündeki optik derinlik sunOD eklenir
    • Nihai tau, BETA_R * (viewODR + sunOD.x), BETA_M_EXT * (viewODM + sunOD.y), BETA_OZONE_ABS * (viewODO + sunOD.z) değerlerinin toplamından oluşur
    • Bu uygulama ile gün batımı, gün doğumu, tepedeki güneş ve aradaki aydınlatma koşullarındaki gökyüzü render edilebilir
    • sun angle uniform'u ile gün boyunca gökyüzünün mavi tonundaki değişim oluşturulur ve Mie saçılması, gün batımı ile gün doğumunda ışığı ufukla doğal biçimde karıştırır
    • Güneş alçaktayken ozon, gökyüzüne mor tonlar katar

Gezegen atmosferine genişletme

  • Düz arka plandan post-processing efektine

    • Daha önce oluşturulan shader iyi bir gökyüzü arka planı sağlar, ancak React Three Fiber sahnesinde düz bir arka plana yakındır
    • Sonraki adım, bunu post-processing effect'e dönüştürerek sahne derinliğini hesaba katan bir hacim ve gezegen mesh'ini saran bir atmosfer kabuğu olarak render etmektir
    • Bunun için screenUV koordinatlarından dünya uzayı koordinatları yeniden oluşturulur ve sahnenin depth buffer'ı raymarching'e yansıtılır
  • Dünya uzayı yeniden oluşturma ve 3D ışınlar

    • Atmosfer saçılmasını sahneye uygulamak için yalnızca gökyüzünü çizmek değil, kamera ile ekranda render edilen nesneler arasındaki alanı doldurmak gerekir
    • Gerekli veriler sahnenin depth buffer'ı, kameranın projectionMatrixInverse, matrixWorld, position değerleridir ve bunlar post-processing efektinin uniform'ları olarak aktarılır
    • getWorldPosition(vec2 uv, float depth), depth * 2.0 - 1.0 ile clipZ oluşturur, uv * 2.0 - 1.0 ile NDC koordinatlarını üretir, ardından projectionMatrixInverse ve viewMatrixInverse uygular
    • Aynı süreç, On Shaping Light içindeki volumetric lighting post-processing efektinde de kullanılır
    • Mevcut pikselin worldPosition değeri alındıktan sonra rayOrigin kamera konumu olarak, rayDir ise normalize(worldPosition - rayOrigin) ile hesaplanır ve ekrandaki her piksel için 3D ışın boyunca ilerlenir
  • Depth buffer ile raymarch aralığını ayarlama

    • Sahne geometrisini hesaba katmak için sabit stepSize yerine, mevcut ışının raymarch aralığı depth buffer ile belirlenmelidir
    • sceneDepth = depthToRayDistance(uv, depth) ile ışın üzerindeki sahne derinliği alınır
    • Arka plan pikselleri depth >= 1.0 - 1e-7 ile ayırt edilir ve “sky pixels” için sceneDepth = atmosphereHeight * SKY_MARCH_DISTANCE_MULTIPLIER uygulanır
    • Işın aşağı yöneliyorsa, tGround = observerAltitude / max(-rayDir.y, 1e-4) ile zemin kesişimi hesaplanır ve rayEnd = min(rayEnd, tGround) ile sınırlandırılır
    • Nihai stepSize, (rayEnd - rayStart) / float(PRIMARY_STEPS) olarak hesaplanır
    • Yakın nesnelere ya da zemine çarpan ışınlar daha küçük stepSize ile daha hassas örneklenir; uzağa giden ışınlarda ise aynı örnek sayısı daha uzun bir mesafeye dağıtılır
  • Sahne içi atmosferik sis

    • Post-processing efekti olarak uygulanan shader, sahnenin tüm hacmine atmosfer saçılması uygular ve sahne geometrisini hesaba katarken sky shader'ı arka plan olarak kullanabilir
    • Kameraya yakın nesneler daha net görünürken uzaktaki nesneler daha fazla bulanıklaşır
    • Raycaster ile sürüklenebilir gök cisimleri eklenmiş etkileşimli örnek MaximeHeckel'in tweet'inde görülebilir

Gezegen render etme

  • Gerekli iki adım

    • Gezegenin etrafında gerçekçi bir atmosfer render etmek için, büyük ölçeği işleyebilen bir logarithmic depth buffer ve ışının atmosferde nerede başlayıp bittiğini tanımlayan küresel bir atmosfer kabuğu gerekir
  • logarithmic depth buffer

    • Gezegen ölçeğinde uzaktan bakıldığında, shader atmosfer ile gezegen kabuğu arasındaki derinlik farkını ayırt etmekte zorlanabilir ve bu da depth fighting sorununa yol açabilir
    • Atmosfer yüksekliği yalnızca birkaç km olduğu için, hem sahnenin depth buffer tanımı hem de post-processing efektlerinde bunun okunma biçimi birlikte ayarlanmalıdır
    • React Three Fiber'da Canvası saran gl prop içinde logarithmicDepthBuffer: true ayarlanır
    • Örnek yapılandırma <Canvas shadows gl={{ alpha: true, logarithmicDepthBuffer: true }}> biçimindedir
    • Shader tarafında, logarithmic depth buffer'ı ışın üzerindeki mesafeye geri çevirmek için sceneDepth hesabı yeniden tanımlanır
    • logDepthToViewZ(depth) fonksiyonu pow(2.0, depth * log2(cameraFar + 1.0)) - 1.0 kullanır ve -d döndürür
  • ray-sphere intersection ile atmosfer aralığını bulma

    • Görüş ışınının atmosfer küresine (atmospheric sphere) girip çıktığı noktaları bulmak için ray-sphere intersection testi kullanılır
    • İki kesişim noktası elde edildiğinde, atmosfer dışında örnekleme israf edilmez ve raymarching döngüsü yalnızca bu aralıkla sınırlandırılabilir
    • Gezegen küresel bir mesh olduğundan ve onu biraz daha büyük bir atmosfer küresi çevrelediğinden, aynı kesişim testi gezegenin kendisi için de uygulanır
    • Işın atmosferden çıkmadan önce zemine çarpıyorsa, zemin kesişim noktası raymarching aralığının sonu olarak kullanılır
    • Kullanılan raySphereIntersect implementasyonu, Inigo Quilez'in Ray-Surface intersection functions içeriğini referans alır
  • Sahne nesneleri ve atmosferin bitiş koşulları

    • Atmosfer, gezegen yüzeyine ulaştığında ya da zemine ulaşmadan önce başka bir sahne nesnesiyle karşılaştığında sonlanmalıdır
    • Gezegene çarpma durumunda varsayılan olarak atmosphereFar = min(atmosphereFar, planetHit.x) ile zeminde durur
    • Başka bir mesh zeminin önünde render ediliyorsa, bu durum sceneDepth < planetHit.x - 2.0 koşuluyla belirlenir ve atmosphereFar = min(atmosphereFar, sceneDepth) uygulanır
    • Bu mantık olmazsa, gezegen yüzeyinin nesneden daha önde görünmesi sorunu ortaya çıkar
  • React Three Fiber demosu ve kalan glitch'ler

    • Bu iki düzenleme koda yansıtıldığında, atmosfer saçılımı bir post-processing efekti olarak uygulanabilir ve gezegen çevresindeki atmosfer render edilebilir
    • Demo sahnesi React Three Fiber içinde basit bir “Sun - Earth system” render eder ve özel efekti uygular
    • Güneş konumunu değiştirip uzaklaştığınızda, yer seviyesinden yörüngeye kadar farklı açılardan shader'ın ürettiği gökyüzü rengini görebilirsiniz
    • Aynı efekt, nisan başındaki yazı duyurusu için hazırlanan poster görselinde de kullanıldı; render görseli bir tweet olarak paylaşıldı
    • Sahnedeki torus, güneş battıktan sonra bile hâlâ “lit-up” durumda görünebilir
    • Bunun nedeni, ana directional light'ın shadow-map veya shadow-camera ölçeğinin küçük kalması ve çok uzaktaki torus'u kapsayamamasıdır
    • Geçici çözüm olarak, volumetric lighting article içeriğindeki shadow-mapping yaklaşımı yeniden kullanılabilir; ancak bu pratikte denenmedi

Güneş tutulmasını işleme

  • Büyük bir gökcisminin Güneş'i kapattığı durumlar, lightMarch sonrasında sunVisibility fonksiyonu çağrılıp dönen [0, 1] değerinin geçirgenlikle çarpılmasıyla eklenebilir
  • Temel fikir, mevcut örnek noktasında Ay yönü ile Güneş yönü arasındaki skaler çarpımı karşılaştırmaktır
  • İki yön neredeyse aynıysa ve skaler çarpım 1.0 değerine yakınsa, Ay Güneş'i kapatıyor demektir; yönler dikse ve 0.0 değerine yakınsa kapatma yoktur
  • Yalnızca skaler çarpım kullanmak, sahnedeki nesnelerin boyutunu ve ölçeğini yansıtamaz; bu yüzden implementasyon, Güneş ile Ay'ın açısal uzaklığını ve her birinin açısal yarıçapını karşılaştırır
  • sunVisibility, Ay'ın Güneş'i kapatmadığı durumu, kameradan bakıldığında Ay'ın Güneş'ten daha büyük ya da benzer boyutta göründüğü halde kapattığı durumu ve Ay'ın kameradan bakıldığında Güneş yarıçapı içine girerek kapattığı durumu ele alır
  • Demo, mevcut atmosfer saçılımı örneğine sunVisibility ve bir Ay mesh'i ekleyerek, Ay Güneş'le hizalandığında düşük ışık koşullarını Atmospheric Scattering shader'ının işlemesini sağlar
  • Daha gelişmiş güneş tutulması ve korona simülasyonu, Physically Based Real-Time Rendering of Eclipses makalesinde ele alınır; ancak bu makaledeki implementasyon WebGL'e taşınmadı

Diğer gezegenlerin atmosferleri

  • Kullanılan atmosfer yoğunluğu ve saçılım modeli büyük ölçüde gezegen ile atmosfer yarıçapları ve RayleighScaleHeight, RayleighBeta, MieScaleHeight, MieBeta, mieBetaExt, mieG, OzoneHeight, OzoneWidth gibi birkaç sabitle belirlenir
  • Bu değerler ayarlanarak Mars atmosferine ya da başka gezegenlerin atmosferlerine yakın sonuçlar elde edilebilir
  • Mars için kullanılan değerler yaklaşık değerlerdir
    • planetRadius: 3390
    • atmosphereRadius: 3500, yaklaşık 110 km kalınlık
    • rayleighScaleHeight: 11.1
    • rayleighBeta: new THREE.Vector3(0.019, 0.013, 0.0057)
    • mieScaleHeight: 1.5
    • mieBeta: 0.04
    • mieBetaExt: 0.044
    • mieG: 0.65
    • ozoneCenterHeight: 0.0
    • ozoneWidth: 1.0
    • ozoneBetaAbs: new THREE.Vector3(0.0, 0.0, 0.0)
    • sunIntensity: 15.0
    • planetSurfaceColor: '#8B4513'
  • Mevcut sabitler bu değerlerle değiştirildiğinde daha tozlu ve turuncu tonlu bir atmosfer elde edilir; ayrıca Mars'a özgü gün batımındaki mavi ton da yakalanabilir
  • İlgili çalışmalardan biri Physically Based Rendering of the Martian Atmosphere makalesidir

LUT tabanlı atmosferik saçılım

  • Yaklaşım ve kısaltılan kısımlar

    • Mevcut shader, küçük ve büyük ölçekli atmosferi sezgisel biçimde render edebiliyor, ancak çok sayıda PRIMARY_STEPS içeren raymarching döngüsü, iç içe lightmarching döngüsü ve tam ekran çözünürlükte yapılan hesaplamalar nedeniyle çalıştırma maliyeti yüksek
    • Sebastian Hillaire'in A Scalable and Production Ready Sky and Atmosphere Rendering Technique çalışması, maliyetli saçılım hesaplarını texture içinde saklayıp son render aşamasında önceden hesaplanmış texture'ları örnekleyip birleştiren Look Up Tables (LUTs) tabanlı bir yaklaşım öneriyor
    • Ele alınan LUT'ler, ışığın atmosferden geçerken ne kadarının hayatta kaldığını saklayan Transmittance LUT, belirli bir kamera konumundaki gökyüzü rengini saklayan Sky-view LUT ve kamera ile görünen sahne geometrisi arasındaki atmosferik haze ile saçılan ışığı saklayan Aerial Perspective LUT
    • Tüm makalenin implementasyonu birebir aktarılmadı; LUT'ler WebGPU compute shader için uygun olsa da zaman kısıtı ve yazının sürekliliği nedeniyle WebGL korunmuş
    • Makalede Aerial Perspective LUT bir 3D texture, ancak bu implementasyonda 2D render target kullanılıyor
    • Bu yaklaşımda kamera her hareket ettiğinde doğru piksel değerleri için texture'ların yeniden üretilmesi gerekiyor; bunları önceden hesaplayıp hazır tutmak zor
    • Multi-Scattering zaman yetersizliği nedeniyle atlanmış
  • Transmittance LUT

    • Mevcut shader'da tüm örnekleme noktaları, güneş ışığının ne kadar ulaştığını hesaplamak için lightmarch çağırıyordu ve bu süreç pahalıydı
    • Transmittance LUT, bu veriyi düşük çözünürlükte önceden saklayarak daha sonra diğer LUT'lerin ışık verisine ihtiyaç duyduğunda okuyabilmesini sağlıyor
    • Implementasyonda 250 x 64 çözünürlüklü özel bir Frame Buffer Object tanımlanıyor, özel shader material özel transmittanceLUTScene sahnesindeki full-screen quad'a uygulanıyor ve render sonucu texture downstream LUT'lere uniform olarak aktarılıyor
    • Her pikselde vec3(0.0, radius, 0.0) noktasından itibaren raymarching yapılıyor; burada radius, vUv.y koordinatı boyunca planetRadius'tan atmosphereRadius'a kadar artıyor
    • LUT'nin x ekseni ışık açısını, y ekseni ise irtifayı temsil ediyor; saf beyaz 100% geçirgenlik anlamına gelirken siyah veya renkli alanlar zemini ya da havanın en kalın olduğu bölgeleri gösteriyor
    • Sonraki LUT'ler artık “verilen açı ve irtifada atmosferden geçip hayatta kalan ışık miktarı”nı yalnızca texture sorgusuyla alabiliyor
  • Sky-view LUT

    • Sky-view LUT, yerden belirli bir yöne bakıldığında gökyüzünün hangi renkte görüneceğini hesaplıyor
    • getSkyViewRayDir, vUv.x değerini azimuth [-PI, PI] aralığına, vUv.y değerini ise elevation [-PI/2, PI/2] aralığına eşleyerek raymarching yönünü tanımlıyor
    • Elevation için (vUv.y * vUv.y - 0.5) * PI biçiminde quadratic mapping kullanılıyor; bu, uzak mesafelerde Sky View'un aşırı titreşmesini önlemek için bir geçici çözüm
    • Işın atmosfere girmiyorsa siyah döndürülüyor; gezegene çarpan ışınlar ise yalnızca görünür atmosfer aralığı boyunca raymarching yapıyor ve gezegene ulaştığında daha erken duruyor
    • Saçılım döngüsü öncekiyle aynı, ancak Sky View yönü boyunca ilerliyor ve güneş ışığı için Transmittance LUT kullanılıyor
  • Aerial Perspective LUT

    • Hillaire'in makalesinden farklı olarak bu implementasyonun sonucu bir 2D texture ve her piksel görünen ekrandaki tek bir piksele karşılık geliyor
    • Sahnenin depth buffer'ı kullanılarak ilgili ışın boyunca ne kadar ilerlenip saçılımın ne kadar biriktirileceği belirleniyor
    • Mevcut saçılım kodu neredeyse olduğu gibi yeniden kullanılıyor, ancak her örnek güneş ışığı görünürlüğünü Transmittance LUT'den alıyor
    • Çıktıda RGB'ye birikmiş atmosferik saçılım yazılıyor, alfada ise compositing sırasında kullanılacak packed view transmittance değeri saklanıyor
    • Implementasyon akışı, depthBuffer içinden derinliği okuyup getWorldPosition(vUv, depth) ile ekran pikselinin world space konumunu geri oluşturduktan sonra kamera konumundan bu world konumuna giden rayDir'i hesaplama şeklinde ilerliyor
    • Ardından logDepthToRayDistance(vUv, depth) ile sahne derinliği ışın mesafesine dönüştürülüyor, atmosfer ve gezegen kesişimleri hesaplanıyor ve yalnızca görünür atmosfer aralığında march yapılıyor
  • Birleştirme

    • Sky-view LUT ve Aerial Perspective LUT oluşturulduktan sonra son post-processing pass'te ikisi birleştiriliyor
    • Buradaki temel iş, mevcut rayDir değerini Sky View UV koordinatlarına dönüştürmek
    • Sahne geometrisine Aerial Perspective LUT uygulanıyor; alfa kanalı view transmittance, RGB kanalları ise saçılan ışık olarak kullanılıyor ve color = color * aerialPerspective.a + aerialPerspective.rgb hesaplanıyor
    • Arka plan piksellerinde Sky View LUT örnekleniyor; depth >= 1.0 - 1e-7 ise bunun arka plan olduğu kabul edilip color = inputColor.rgb + sampleSkyViewLUT(rayDir, planetCenter) uygulanıyor
    • Son olarak ACESFilm(color) ve pow(color, vec3(1.0 / 2.2)) uygulanıyor
    • LUT tabanlı atmosfer implementasyonunun tamamı Github link üzerinden görülebilir

Kapanış

  • LUT tabanlı atmosferik saçılımın sonucu, önceki tam raymarching sürümüyle neredeyse aynı görünebilir, ancak iç süreç farklıdır
  • İş daha küçük LUT'lere bölünüp son efektte birleştirilir ve her örnekte güneşe doğru tekrar tekrar raymarching yaparak ulaşan ışık hesaplanmaz
  • Aydınlatma bilgisi doğrudan Transmittance LUT'den alındığı için maliyetli iç içe döngüler basit texture sorgularıyla değiştirilir ve son sahnede göz ardı edilemeyecek bir performans artışı elde edilir
  • Bu implementasyon, Sébastian Hillaire ve başka alanlardaki implementasyonlarla kıyaslandığında eksik kalıyor; özellikle Sky View tarafında banding ve flickering var ve kısaltılan kısımlar nedeniyle optimum değil
  • Muhtemelen en baştan WebGPU kullanmak gerekirdi
  • Gerçek bir production-grade implementasyon olarak Shoda Matsuda'nın (@shotamatsuda) three-geospatial projesi öneriliyor
  • Ek olarak volumetric clouds ekleme çalışması da yapılmış, ancak sonuç hâlâ mixed bag; yazıda gösterilecek kadar tatmin edici olmadığından daha fazla çalışma gerekiyor

1 yorum

 
GN⁺ 2 시간 전
Hacker News yorumları
  • Bunu daha önce görmüştüm, o yüzden tamamen ilgili olmayabilir ama Sebastian Lague'ın gezegen üretimi denemesinde atmosfer render etme konusunu ele aldığı video da gerçekten çok eğlenceliydi https://www.youtube.com/watch?v=DxfEbulyFcY
    Görsel efektler geliştirip bunların giderek daha gerçekçi hale geldiğini izlemenin ayrı bir keyfi var; bir gün ben de bu alanda bizzat denemeler yapmak istiyorum
    • Sebastian Lague ile ilgili en şaşırtıcı şey, YouTube algoritmasının insanı ne kadar mahvedebildiği
      Eskiden videoları milyonlarca izlenme alıyordu, şimdi ise 500 bini bile zar zor geçiyor. Bunun nedeni, pandemi döneminde herkes evdeyken rastgele şeylere ilgi göstermesi de olabilir
    • Sebastian Lague hakkında tek şikayetim, yeterince çok videosunun olmaması
      Genelde uyurken açıyorum; sakin ama derinlemesine teknik konulara inen böyle içeriklerden daha fazla olsa keşke diye düşünüyorum, hatta bazen kendim üretmeyi bile düşündüm
  • Bunu bilerek dışarıda mı bıraktı bilmiyorum ama gün batımı modeli için, güneş ufkun altına iner inmez gökyüzünün siyaha dönmemesi gerektiğini belirtmekte fayda var
    Güneş battıktan sonra da bir süre başımızın üzerindeki atmosfer ve ufkun üstündeki bölge hâlâ güneş ışığı almaya devam eder; Dünya atmosferinde Güneş ufkun altında 18 dereceye inene kadar belirgin alacakaranlık sürer. Bunu ray tracing ile uygulamak pratik olmayabilir ama bunun için kullanılan yaygın algoritmalar var
  • İyi grafik yazıları her zaman memnuniyet verici. Ben de prosedürel uzay/gezegen üreticisinde benzer bir şey üzerinde çalışıyordum; atmosferik saçılımın, volumetrik bulut render etme ile birleşince harika gün batımı ve gökyüzü sahneleri üretebilmesi çok hoş
    https://www.threads.com/@mrsharpoblunto/post/DVS4wfYiG8f?xmt...
    https://www.threads.com/@mrsharpoblunto/post/C6Vc-S1O9mX?xmt...
    https://www.threads.com/@mrsharpoblunto/post/C6apksDRa8q?xmt...
  • Bugünlerde telefonların ve tarayıcıların yapabildikleri gerçekten inanılmaz
    1993 tarihli, bu konudaki öncü çalışmalardan sayılabilecek ve okunması çok kolay olan Nishita ve diğerlerinin “Display of The Earth Taking into Account Atmospheric Scattering” makalesini uyguladığımı hatırlıyorum: https://www.researchgate.net/publication/2933032_Display_of_...
    • Daha önce Rayleigh saçılımı ve Mie saçılımı uygularken okuduğum makaleyi başka bir yorumda anımsamıştım; aradığım şey kesinlikle buydu
      Çalışır hale getirdiğimde, “Bu kadar karmaşık bir gerçek dünya olgusunu birkaç nispeten basit hesaplamayla oldukça iyi modelleyebiliyormuşum” dediğim bir an olmuştu. Statik mavi bir skybox'tan bir anda tam bir gece-gündüz döngüsüne geçmiştim
  • Gerçekten harika
    Bir zamanlar web'de gökyüzünü birkaç gradyanı üst üste bindirerek render etmeyi denesem nasıl olur diye düşünmüştüm. Bir noktaya kadar başarılı olup fena olmayan sonuçlar almış olabilirim ama burada yapılanla kıyaslanmaz. Ortaya çıkan şey etkileyici ve ilham verici
    • Eskiden hobi olarak yaptığım oyun motorunda Rayleigh saçılımı ve Mie saçılımı uygulamıştım
      Sadece bununla bile oldukça ikna edici bir gün batımı/gün doğumu döngüsü çıktığını görünce şaşırmıştım; yanlış hatırlamıyorsam güneşin kendisi de bir şekilde bunun içinden doğal biçimde ortaya çıkıyordu. Microsoft'un C# oyun geliştirme platformu XNA'i kullanırken Riemer'in harika eğitim serisini takip etmiştim; arşivlenmiş kopyası burada https://github.com/SimonDarksideJ/XNAGameStudio/wiki/Riemers...
      Yalnız saçılımla ilgili kısmı göremiyorum; o bölümü başka bir yerden almış olabilirim. Formüller içeren makaleler okuduğumu hatırlıyorum
  • SpaceEngine de bu alana epey emek vermesiyle biliniyor, o yüzden şiddetle tavsiye ederim: https://www.youtube.com/watch?v=_4TjdVAbXks
    https://spaceengine.org/
    • Bunun gibi şeylerin SSS'leri, ölçeği ve soruların çeşitliliğini göstermesi açısından hoşuma gidiyor
      “SpaceEngine'de kaç nesne var?” sorusuna verilen yanıt; Hipparcos yıldız kataloğunun tamamı, bilinen tüm ötegezegenler, on binden fazla galaksi ve Güneş Sistemi'ndeki nesnelerin çoğu dahil olmak üzere 130 bin nesne olduğu, buna ek olarak gözlemlenebilir evrende gerçekte var olandan bile fazla galaksi ve yıldız sisteminin eklendiği yönünde. “Su gezegeni nasıl sıcak olabilir?” sorusuna ise üst atmosferdeki suyun sıcak su buharı olduğu, aşağı indikçe yüksek basınç altında sıvıya yumuşak biçimde geçtiği ve daha derinlerde ice VII denilen katı bir hâle dönüştüğü cevabı veriliyor. “Nasıl hareket edilir?” sorusunun cevabı ise WASD tuşları
    • Bir sekmede Wikipedia, diğerinde SpaceEngine açık tutmak, benim en sevdiğim yarı eğitici oyun deneyimlerinden biri
      Harika bir oyun ve epey eski olmasına rağmen hâlâ bu kadar iyi başka bir şey görmedim
    • Bu, yıllardır var olan müthiş bir yazılım; sadece bu konuda değil, birçok alanda da detay takıntısı inanılmaz düzeyde
      Bu yazıyı görünce benim de aklıma SpaceEngine geldi
  • Saçılım, uzun zamandır gerçekçi render edilmiş görüntüler üretmenin kilit unsurlarından biri
    En sevdiğim makalelerden biri: http://www.graphics.stanford.edu/papers/bssrdf/bssrdf.pdf
    Sütü render etmenin zor bir problem olduğunu sanırım ilk kez o zaman öğrenmiştim
  • Vay, epey inanılmaz bir yolculuktu
    Sanırım ancak %5'ini anlayabildim ama yine de çok etkilendim
    • Ben de aynı durumdayım. Sırf görseller için bile okumaya değerdi
  • Ah, bu gerçekten çok güzel ve okuması keyifli bir yazı
    Üstelik MIT lisansı ise oyunumdaki skybox sorunu çözülmüş sayılır. Perspektif sabit kalacağından, yalnızca güneşin gökyüzü boyunca hareketini render etmem gerekir; buna bir sinüs dalgası periyoduyla yıl içindeki güneş açısı değişimini de ekleyebilirim