1 पॉइंट द्वारा GN⁺ 2 시간 전 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • ब्राउज़र shader Rayleigh scattering, Mie scattering और ozone absorption को मिलाकर नीला आसमान और सूर्यास्त·सूर्योदय को real time में render करता है
  • कैमरा किरण की optical depth और Beer's Law transmittance को accumulate किया जाता है, और phase function से सूर्य की दिशा के अनुसार scattering distribution की गणना की जाती है
  • सूर्यास्त effect के लिए हर sample पर सूर्य की दिशा में अलग light-march चलाया जाता है, ताकि वातावरण से गुजरते समय सूर्यप्रकाश में होने वाले नुकसान को दर्शाया जा सके
  • planar sky shader, depth buffer और world coordinates reconstruction के साथ post-processing effect बन जाता है, जिससे scene objects के बीच का atmospheric fog भी संभाला जाता है
  • ग्रह-स्तर पर इसे logarithmic depth buffer, ray-sphere intersection, और LUT-आधारित Transmittance·Sky-view·Aerial Perspective तक विस्तारित किया जाता है

atmospheric scattering shader के लक्ष्य और संदर्भ सामग्री

  • लक्ष्य यह है कि Space Shuttle Endeavour की low-earth orbit sunset तस्वीरों की तरह, पृथ्वी के ऊपरी वातावरण की गहरा नारंगी·नीली·और अंतरिक्ष पृष्ठभूमि की काली परतों को ब्राउज़र shader में पुनर्निर्मित किया जाए
  • implementation का दायरा raymarching, Rayleigh scattering, Mie scattering, और ozone absorption को मिलाकर एक realistic sky dome से शुरू होता है, और आगे ग्रह के आसपास के atmospheric shell तथा LUT-आधारित optimization तक बढ़ता है
  • मुख्य संदर्भ सामग्री हैं Three Geospatial, Sébastien Hillaire का A Scalable and Production Ready Sky and Atmosphere Rendering Technique, और Atmospheric Scattering (and also just faking it)

sky rendering का मूल मॉडल

  • simple gradient क्यों काफ़ी नहीं है

    • आसमान का रंग सिर्फ़ एक साधारण नीली background नहीं है, बल्कि इसे प्रकाश और हवा तथा उसके घटकों के interaction के परिणाम के रूप में देखना चाहिए
    • इसमें observer की ऊँचाई, धूल की मात्रा, और दिन का समय जैसे variables को ध्यान में रखना होता है, और गणना volume के भीतर की जाती है
  • atmospheric density sampling

    • वातावरण को volumetric clouds या volumetric light की तरह raymarching से sample किया जाता है
    • कैमरा position से किरण छोड़ी जाती है और transparent medium के साथ आगे बढ़ते हुए, वातावरण से गुजरकर बची रहने वाली रोशनी यानी transmittance और हर sample पर कैमरा की ओर फिर से निर्देशित होने वाली scattering की गणना की जाती है
    • raymarching की पुनरावृत्ति के लिए Painting with Math: A Gentle Study of Raymarching देखा जा सकता है
  • Rayleigh density और optical depth

    • transmittance निकालने के लिए किरण के रास्ते में मिलने वाली atmospheric density को accumulate करके optical depth की गणना करनी होती है
    • Rayleigh density function ऊँचाई h पर यह दिखाता है कि “हवा” कितनी है, और ऊँचाई बढ़ने पर वातावरण के पतला होने के प्रभाव को दर्शाता है
    • उदाहरण implementation में RAYLEIGH_SCALE_HEIGHT = 8.0km, ATMOSPHERE_HEIGHT = 100.0km, VIEW_DISTANCE = 200.0km, PRIMARY_STEPS = 24 का उपयोग किया गया है
    • rayleighDensity(h) है exp(-max(h, 0.0) / RAYLEIGH_SCALE_HEIGHT), और loop में viewOpticalDepth += dR * stepSize के रूप में accumulate होता है
  • Beer's Law और दिन के आसमान का नीला रंग

    • optical depth से किसी विशेष बिंदु पर transmittance T निकाला जाता है, जहाँ T=1.0 का मतलब है रोशनी का कोई नुकसान नहीं, और T=0.0 का मतलब है रोशनी पूरी तरह गायब हो गई
    • transmittance की गणना Beer's Law से होती है, और उदाहरण code vec3 transmittance = exp(-rayleighBeta * viewOpticalDepth) का उपयोग करता है
    • rayleighBeta Rayleigh scattering coefficient है, जिसे shader में vec3(0.0058, 0.0135, 0.0331) के रूप में रखा गया है
    • सूर्यप्रकाश की दिशा और view ray के बीच के कोण को 3.0 / (16.0 * PI) * (1.0 + mu * mu) रूप वाले Rayleigh phase function से model किया जाता है
    • Rayleigh scattering coefficient के कारण लाल रंग लगभग scatter नहीं होता, हरा थोड़ा अधिक scatter होता है, और नीला सबसे अधिक scatter होता है, इसलिए दिन का आसमान नीला दिखता है
    • जब इसे हर pixel के लिए एक किरण तक बढ़ाया जाता है, तो horizon की दिशा में ज़्यादा वातावरण पार होने के कारण वह चमकीले सफ़ेद haze जैसा दिखता है, जबकि ऊँचाई बढ़ने पर रंग और गहरा, अधिक dark blue हो जाता है

Mie scattering और ozone absorption

  • Rayleigh alone से छूट जाने वाले प्रभाव

    • सिर्फ़ Rayleigh scattering से भी ठीक-ठाक परिणाम मिल सकते हैं, लेकिन अधिक realistic आसमान के लिए अतिरिक्त atmospheric effects चाहिए
    • Mie scattering धूल या aerosol जैसे बड़े particles और प्रकाश के interaction को दर्शाता है, और इसमें density function तथा दिशा-आधारित redistribution दिखाने वाला phase function होता है
    • ozone absorption ऊपरी वातावरण से गुजरने वाली रोशनी की कुछ wavelengths को scatter किए बिना ही path से हटा देता है
    • ozone absorption खासकर horizon, sunset, sunrise, और इनके आसपास की twilight में आसमान के रंग को और गहरा बनाता है तथा रंगों को shift करता है
  • Mie और ozone का accumulation

    • Rayleigh, Mie, और ozone को साथ इस्तेमाल करने वाले implementation में viewODR, viewODM, viewODO में क्रमशः उनकी optical depth accumulate की जाती है
    • हर sample पर dR = rayleighDensity(h), dM = mieDensity(h), dO = ozoneDensity(h) की गणना होती है, और tau को BETA_R * viewODR, BETA_M_EXT * viewODM, BETA_OZONE_ABS * viewODO के योग से बनाया जाता है
    • transmittance exp(-tau) से निकाला जाता है, और sumR, sumM, sumO में संबंधित density, transmittance, और stepSize accumulate होते हैं
    • अंतिम scattering की गणना SUN_INTENSITY * (phaseR * BETA_R * sumR + phaseM * BETA_M_SCATTER * sumM + BETA_OZONE_SCATTER * sumO) के रूप में की जाती है
  • प्रमुख constants और प्रभाव

    • MIE_SCALE_HEIGHT, aerosol के लिए RAYLEIGH_SCALE_HEIGHT के बराबर है, और क्योंकि particles आम तौर पर horizon के पास केंद्रित होते हैं, इसे 1.2km जैसे छोटे मान पर सेट किया जाता है
    • MIE_BETA_SCATTER नियंत्रित करता है कि particles रोशनी को कैमरा की ओर कितना scatter करें, और क्योंकि यह अधिकतर wavelength-independent होता है, इसे vec3(0.003) पर सेट किया जाता है
    • MIE_BETA_EXT Mie extinction coefficient है, जो दिखाता है कि path से कितनी रोशनी हटती है, और इससे दूर का वातावरण अधिक hazy दिखता है
    • MIE_G anisotropy को नियंत्रित करता है, जहाँ 0.0 uniform scattering और 1.0 अधिक मजबूत forward-scattering bias को दर्शाता है
    • OZONE_BETA_ABS का मान vec3(0.00065, 0.00188, 0.00008) है, जो हरे और yellow-orange spectrum को अधिक absorb करके आसमान के रंग को नीले·लाल·बैंगनी की ओर shift करता है
    • Mie और ozone को साथ मिलाने पर अधिक प्राकृतिक “sky blue” रंग और सूर्य के आसपास hazy glow बनती है, और जब सूर्य horizon के क़रीब होता है तब Mie scattering effect और अधिक स्पष्ट हो जाता है

प्रकाश पथ और सूर्यास्त·सूर्योदय

  • मौजूदा implementation की सीमाएँ

    • sky fragment shader अलग-अलग ऊँचाइयों पर प्राकृतिक रंग render कर सकता है और Mie, Rayleigh, ओज़ोन transmittance model को reflect कर सकता है
    • लेकिन सूर्य को क्षितिज के पास ले जाने पर भी light attenuation या सूर्यास्त·सूर्योदय effect के बिना सिर्फ सफेद धुंधला प्रकाश-घेरा ही दिखाई देता है
    • ऐसा इसलिए था क्योंकि मौजूदा raymarching loop सिर्फ कैमरे से हर sample तक जाने वाली view ray पर ही light attenuation की गणना करता था
    • sample बिंदु तक पहुँचने से पहले, सूर्य का प्रकाश वायुमंडल से गुजरते हुए कितना loss होता है, इसकी भी गणना करनी होती है
  • light-march nested loop

    • हर sample बिंदु पर light source की दिशा में अलग nested loop चलाकर उस path की transmittance को sample किया जाता है
    • यह approach real-time cloudscapes और volumetric lighting में भी इस्तेमाल होती है
    • lightMarch(float start, float sunY) LIGHTMARCH_STEPS जितनी बार दोहराते हुए odR, odM, odO को accumulate करता है
    • मौजूदा implementation की optical depth viewODR, viewODM, viewODO में सूर्य दिशा की optical depth sunOD जोड़ी जाती है
    • अंतिम tau को BETA_R * (viewODR + sunOD.x), BETA_M_EXT * (viewODM + sunOD.y), BETA_OZONE_ABS * (viewODO + sunOD.z) को जोड़कर बनाया जाता है
    • इस implementation से सूर्यास्त, सूर्योदय, सिर के ऊपर सूर्य, और इनके बीच की lighting conditions वाला आकाश render किया जा सकता है
    • sun angle uniform से पूरे दिन आकाश के नीले रंग में बदलाव बनाया जाता है, और Mie scattering सूर्यास्त और सूर्योदय के समय प्रकाश को क्षितिज के साथ प्राकृतिक ढंग से blend करती है
    • जब सूर्य नीचे होता है, तो ओज़ोन आकाश में बैंगनी टोन जोड़ता है

ग्रहों के वायुमंडल तक विस्तार

  • समतल background से post-processing effect तक

    • पहले बनाया गया shader अच्छा sky background देता है, लेकिन यह React Three Fiber scene के समतल background के काफ़ी करीब है
    • अगला चरण इसे post-processing effect में बदलना है, ताकि scene depth को ध्यान में रखने वाले volume और planetary mesh को घेरे हुए atmospheric shell के रूप में इसे render किया जा सके
    • इसके लिए screenUV निर्देशांक से world space निर्देशांक को reconstruct किया जाता है और scene के depth buffer को raymarching में शामिल किया जाता है
  • world space reconstruction और 3D ray

    • scene पर atmospheric scattering लागू करने के लिए सिर्फ आकाश draw करना काफ़ी नहीं है, बल्कि कैमरे और स्क्रीन पर render हुए objects के बीच की जगह भी भरनी होती है
    • ज़रूरी data है scene का depth buffer, कैमरे का projectionMatrixInverse, matrixWorld, position; और इन values को post-processing effect के uniform के रूप में pass किया जाता है
    • getWorldPosition(vec2 uv, float depth) depth * 2.0 - 1.0 से clipZ बनाता है, uv * 2.0 - 1.0 से NDC coordinates बनाता है, और फिर projectionMatrixInverse तथा viewMatrixInverse लागू करता है
    • यही प्रक्रिया On Shaping Light के volumetric lighting post-processing effect में भी इस्तेमाल होती है
    • मौजूदा pixel का worldPosition मिलने के बाद rayOrigin को कैमरे की position और rayDir को normalize(worldPosition - rayOrigin) से calculate किया जाता है, ताकि स्क्रीन के हर pixel के लिए 3D ray के साथ आगे बढ़ा जा सके
  • depth buffer से raymarch range समायोजन

    • scene geometry को ध्यान में रखने के लिए fixed stepSize की जगह depth buffer से मौजूदा ray की raymarch range तय करनी होती है
    • sceneDepth = depthToRayDistance(uv, depth) से ray पर scene depth निकाली जाती है
    • background pixel की पहचान depth >= 1.0 - 1e-7 से की जाती है, और “sky pixels” पर sceneDepth = atmosphereHeight * SKY_MARCH_DISTANCE_MULTIPLIER लागू किया जाता है
    • अगर ray नीचे की ओर जा रही हो, तो tGround = observerAltitude / max(-rayDir.y, 1e-4) से ground intersection निकाला जाता है और rayEnd = min(rayEnd, tGround) से उसे सीमित किया जाता है
    • अंतिम stepSize को (rayEnd - rayStart) / float(PRIMARY_STEPS) से calculate किया जाता है
    • पास के objects या ज़मीन से टकराने वाली rays को छोटे stepSize के साथ ज़्यादा सटीक sample किया जाता है, जबकि दूर तक जाने वाली rays पर उतने ही samples लंबी दूरी में distribute किए जाते हैं
  • scene के अंदर atmospheric fog

    • post-processing effect के रूप में implement किया गया shader scene के पूरे volume पर atmospheric scattering लागू करता है, और scene geometry को ध्यान में रखते हुए sky shader को background की तरह इस्तेमाल कर सकता है
    • कैमरे के पास के objects ज़्यादा साफ़ दिखाई देते हैं, जबकि दूर के objects ज़्यादा धुंधले हो जाते हैं
    • Raycaster से drag किए जा सकने वाले खगोलीय objects वाला interactive example MaximeHeckel की tweet में देखा जा सकता है

ग्रह rendering

  • ज़रूरी दो चरण

    • ग्रह के आसपास यथार्थवादी atmosphere render करने के लिए बड़े scale को संभालने वाला logarithmic depth buffer और एक गोलाकार atmospheric shell चाहिए, जो यह परिभाषित करे कि light ray atmosphere में कहाँ से शुरू होती है और कहाँ खत्म होती है
  • logarithmic depth buffer

    • ग्रह-स्तर के scale पर दूर से देखने पर shader के लिए atmosphere और planet shell के depth difference को अलग करना मुश्किल हो सकता है, जिससे depth fighting हो सकता है
    • atmosphere की ऊँचाई सिर्फ कुछ km होती है, इसलिए scene के depth buffer की definition और post-processing effects में उसे पढ़ने के तरीके, दोनों को adjust करना पड़ता है
    • React Three Fiber के Canvas को wrap करने वाले gl prop में logarithmicDepthBuffer: true सेट किया जाता है
    • example setting का रूप <Canvas shadows gl={{ alpha: true, logarithmicDepthBuffer: true }}> है
    • shader में logarithmic depth buffer को ray पर distance में वापस बदलने के लिए sceneDepth calculation को फिर से define किया जाता है
    • logDepthToViewZ(depth) में pow(2.0, depth * log2(cameraFar + 1.0)) - 1.0 का उपयोग होता है और यह -d return करता है
  • ray-sphere intersection से atmospheric interval ढूँढना

    • view ray atmospheric sphere में कहाँ प्रवेश करती है और कहाँ बाहर निकलती है, यह पता करने के लिए ray-sphere intersection test का उपयोग किया जाता है
    • दो intersection points मिलने पर atmosphere के बाहर samples बेकार नहीं होते, और raymarching loop को सिर्फ उसी interval तक सीमित किया जा सकता है
    • ग्रह एक spherical mesh है और उसके चारों ओर उससे थोड़ा बड़ा atmospheric sphere होता है, इसलिए वही intersection test ग्रह पर भी लागू किया जाता है
    • अगर ray atmosphere से बाहर निकलने से पहले ground से टकराती है, तो ground intersection point को raymarching interval के end के रूप में इस्तेमाल किया जाता है
    • इस्तेमाल किया गया raySphereIntersect implementation Inigo Quilez के Ray-Surface intersection functions से संदर्भित है
  • scene objects और atmosphere termination condition

    • atmosphere को planet surface से टकराने पर, या ground तक पहुँचने से पहले किसी दूसरे scene object से मिलने पर समाप्त हो जाना चाहिए
    • planet से टकराने के मामले में डिफ़ॉल्ट रूप से atmosphereFar = min(atmosphereFar, planetHit.x) के साथ ground पर रुकता है
    • अगर कोई दूसरा mesh ground के सामने render हो रहा हो, तो sceneDepth < planetHit.x - 2.0 condition से उसे पहचाना जाता है और atmosphereFar = min(atmosphereFar, sceneDepth) लागू किया जाता है
    • यह logic न हो तो planet surface object के सामने दिखाई देने लगती है
  • React Three Fiber demo और बाकी glitches

    • इन दो adjustments को code में लागू करने पर atmosphere scattering को post-processing effect के रूप में implement किया जा सकता है और ग्रह के आसपास का atmosphere render किया जा सकता है
    • demo scene React Three Fiber में एक साधारण “Sun - Earth system” render करता है और custom effect apply करता है
    • सूरज की position adjust करके और zoom out करने पर जमीन से orbit तक अलग-अलग angles पर shader द्वारा बनाया गया sky color देखा जा सकता है
    • यही effect अप्रैल की शुरुआत में आने वाले लेख के teaser poster image में भी इस्तेमाल हुआ था, और render image tweet के रूप में share की गई थी
    • scene का torus सूर्यास्त के बाद भी “lit-up” state में दिख सकता है
    • इसकी वजह यह है कि main directional light का shadow-map या shadow-camera scale छोटा है, इसलिए वह बहुत दूर मौजूद torus को cover नहीं कर पाता
    • workaround के तौर पर volumetric lighting article वाले shadow-mapping approach को फिर से इस्तेमाल किया जा सकता है, लेकिन वास्तव में ऐसा किया नहीं गया

ग्रहण को handle करना

  • जब कोई बड़ा खगोलीय पिंड सूरज को ढकता है, तो lightMarch के बाद sunVisibility function को call करके और उसके return value [0, 1] को transmittance से multiply करके इसे जोड़ा जा सकता है
  • मूल विचार यह है कि current sample point से चाँद की दिशा और सूरज की दिशा के dot product की तुलना की जाए
  • अगर दोनों दिशाएँ लगभग एक जैसी हों और dot product 1.0 के करीब हो, तो चाँद सूरज को ढक रहा है; अगर वे orthogonal हों और 0.0 के करीब हों, तो ढकाव नहीं है
  • सिर्फ dot product से scene के objects के size और scale को reflect नहीं किया जा सकता, इसलिए implementation सूरज और चाँद की angular distance और उनके angular radius की तुलना करता है
  • sunVisibility उन स्थितियों को handle करता है जहाँ चाँद सूरज को नहीं ढकता, जहाँ चाँद camera view से सूरज से बड़ा या लगभग बराबर दिखते हुए उसे ढकता है, और जहाँ चाँद camera view से सूरज की radius के अंदर आकर उसे ढकता है
  • demo में मौजूदा atmosphere scattering example के ऊपर sunVisibility और moon mesh जोड़ा गया है, ताकि चाँद को सूरज के साथ align करने पर कम रोशनी वाली स्थिति को Atmospheric Scattering shader संभाल सके
  • ज़्यादा परिष्कृत eclipse और corona simulation पर Physically Based Real-Time Rendering of Eclipses paper में चर्चा की गई है, लेकिन उस paper के implementation को WebGL में port नहीं किया गया

दूसरे ग्रहों के atmosphere

  • इस्तेमाल किया गया atmosphere density और scattering model मुख्य रूप से ग्रह और atmosphere के radius, RayleighScaleHeight, RayleighBeta, MieScaleHeight, MieBeta, mieBetaExt, mieG, OzoneHeight, OzoneWidth जैसे कुछ constants से तय होता है
  • इन values को adjust करके Mars atmosphere या दूसरे ग्रहों के atmosphere के करीब results बनाए जा सकते हैं
  • Mars के लिए इस्तेमाल की गई values approximate हैं
    • planetRadius: 3390
    • atmosphereRadius: 3500, लगभग 110 km thickness
    • 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'
  • मौजूदा constants को इन values से बदलने पर ज़्यादा धूलभरा और नारंगी-आभा वाला atmosphere मिलता है, और Mars की खास सूर्यास्त के समय की नीली आभा भी हासिल की जा सकती है
  • संबंधित paper है Physically Based Rendering of the Martian Atmosphere

LUT-आधारित atmospheric scattering

  • अप्रोच और संक्षिप्त किए गए हिस्से

    • मौजूदा shader छोटे scale और बड़े scale के atmosphere को सहज रूप से render कर सकता है, लेकिन PRIMARY_STEPS वाले raymarching loop, nested lightmarching loop, और full-screen resolution calculation की वजह से इसकी execution cost बहुत अधिक है
    • Sebastian Hillaire का A Scalable and Production Ready Sky and Atmosphere Rendering Technique महंगे scattering calculation को texture में store करके, final render में पहले से compute किए गए texture को sample और composite करने वाला Look Up Tables(LUTs) आधारित तरीका प्रस्तावित करता है
    • यहाँ जिन LUT का उपयोग किया गया है, वे हैं: atmosphere से गुजरते समय बची हुई रोशनी की मात्रा store करने वाला Transmittance LUT, किसी खास camera position से sky color store करने वाला Sky-view LUT, और camera तथा दिखने वाली scene geometry के बीच का atmospheric haze और scattered light store करने वाला Aerial Perspective LUT
    • पूरे paper के implementation को ज्यों का त्यों नहीं अपनाया गया; LUT, WebGPU के compute shader के लिए उपयुक्त हैं, लेकिन समय की कमी और लेख की निरंतरता के कारण WebGL को बनाए रखा गया
    • paper में Aerial Perspective LUT एक 3D texture है, लेकिन इस implementation में 2D render target का उपयोग किया गया है
    • इस तरीके में camera के हिलने पर सही pixel values पाने के लिए texture को हर बार फिर से generate करना पड़ता है, इसलिए इसे पहले से precompute करना कठिन है
    • Multi-Scattering को समय की कमी के कारण छोड़ा गया है
  • Transmittance LUT

    • मौजूदा shader में हर sample point lightmarch को call करके यह गणना करता था कि सूर्य का प्रकाश कितना पहुँचता है, और यह प्रक्रिया महंगी थी
    • Transmittance LUT इस data को कम resolution पर पहले से store करता है, ताकि बाद के LUT जब light data चाहें तो उसे पढ़कर उपयोग कर सकें
    • implementation 250 x 64 resolution वाला एक dedicated Frame Buffer Object define करता है, custom shader material को dedicated scene transmittanceLUTScene के full-screen quad पर apply करता है, और render result texture को downstream LUT के uniform के रूप में pass करता है
    • हर pixel पर vec3(0.0, radius, 0.0) से raymarching शुरू होती है, जहाँ radius, vUv.y coordinate के साथ planetRadius से atmosphereRadius तक बढ़ता है
    • LUT का x-अक्ष प्रकाश के angle को और y-अक्ष altitude को दर्शाता है; शुद्ध सफेद 100% transmittance है, जबकि काले या रंग वाले क्षेत्र जमीन या हवा के सबसे घने हिस्सों को दिखाते हैं
    • बाद के LUT अब “दिए गए angle और altitude पर atmosphere से गुजरकर बची हुई रोशनी की मात्रा” सिर्फ texture lookup से प्राप्त कर सकते हैं
  • Sky-view LUT

    • Sky-view LUT यह गणना करता है कि जमीन से किसी विशेष दिशा में ऊपर देखने पर आसमान का रंग कैसा दिखेगा
    • getSkyViewRayDir, vUv.x को azimuth [-PI, PI] और vUv.y को elevation [-PI/2, PI/2] में map करके raymarching direction define करता है
    • elevation के लिए (vUv.y * vUv.y - 0.5) * PI वाली quadratic mapping का उपयोग किया गया है; यह दूर की दूरी पर Sky View के बहुत अधिक flicker होने से बचने के लिए एक workaround है
    • अगर ray atmosphere में प्रवेश नहीं करती, तो काला रंग return किया जाता है; और जो ray ग्रह से टकराती है, उसके लिए केवल दिखने वाले atmospheric segment तक raymarching की जाती है और ग्रह से टकराते ही पहले रोक दिया जाता है
    • scattering loop पहले जैसा ही है, लेकिन यह Sky View direction के साथ आगे बढ़ता है और सूर्य के प्रकाश के लिए Transmittance LUT का उपयोग करता है
  • Aerial Perspective LUT

    • Hillaire के paper के विपरीत, implementation का परिणाम 2D texture है, और हर pixel स्क्रीन पर दिखने वाले एक pixel के अनुरूप है
    • scene depth buffer का उपयोग यह तय करने के लिए किया जाता है कि उस ray के साथ कितनी दूर तक march करना है और scattering को कितना accumulate करना है
    • मौजूदा scattering code का लगभग पुन: उपयोग किया जाता है, लेकिन हर sample सूर्य-प्रकाश की visibility Transmittance LUT से लेता है
    • output में RGB में accumulated atmospheric scattering store होती है, और alpha में compositing के समय उपयोग होने वाला packed view transmittance value store होता है
    • implementation flow depthBuffer से depth पढ़ता है, getWorldPosition(vUv, depth) से स्क्रीन pixel की world-space position reconstruct करता है, और फिर camera position से world position तक का rayDir calculate करता है
    • इसके बाद logDepthToRayDistance(vUv, depth) से scene depth को ray distance में convert किया जाता है, atmosphere और ग्रह के intersection की गणना की जाती है, और फिर केवल दिखने वाले atmospheric segment को march किया जाता है
  • Compositing

    • Sky-view LUT और Aerial Perspective LUT generate करने के बाद, अंतिम post-processing pass में दोनों को combine किया जाता है
    • मुख्य काम वर्तमान rayDir को Sky View UV coordinates में convert करना है
    • scene geometry पर Aerial Perspective LUT apply किया जाता है, जहाँ alpha channel को view transmittance और RGB channel को scattered light के रूप में उपयोग करके color = color * aerialPerspective.a + aerialPerspective.rgb calculate किया जाता है
    • background pixels के लिए Sky View LUT को sample किया जाता है, और depth >= 1.0 - 1e-7 होने पर उसे background माना जाता है तथा color = inputColor.rgb + sampleSkyViewLUT(rayDir, planetCenter) apply किया जाता है
    • अंत में ACESFilm(color) और pow(color, vec3(1.0 / 2.2)) apply किए जाते हैं
    • पूरा LUT-आधारित atmosphere implementation code Github link में देखा जा सकता है

समापन

  • LUT-आधारित atmospheric scattering का परिणाम पहले वाले पूर्ण raymarching version जैसा लगभग दिख सकता है, लेकिन इसकी अंदरूनी प्रक्रिया अलग है
  • काम को छोटे LUTs में बाँटकर अंतिम effect में composite किया जाता है, और हर sample पर सूर्य की दिशा में बार-बार raymarching करके पहुँचने वाली रोशनी की गणना नहीं की जाती
  • क्योंकि lighting information सीधे Transmittance LUT से ली जाती है, इसलिए महंगे nested loop को साधारण texture lookup से बदला जा सकता है, और अंतिम scene में नज़रअंदाज़ न की जा सकने वाली performance improvement मिलती है
  • यह implementation Sébastian Hillaire और अन्य क्षेत्रों के implementation की तुलना में सीमित है; खासकर Sky View में banding और flickering है, और संक्षिप्त किए गए हिस्सों की वजह से यह optimal नहीं है
  • संभव है कि शुरुआत से WebGPU का उपयोग करना चाहिए था
  • वास्तविक production-grade implementation के रूप में Shoda Matsuda(@shotamatsuda) के three-geospatial की सिफारिश की गई है
  • इसके अलावा volumetric clouds जोड़ने का काम भी किया गया, लेकिन परिणाम अभी भी mixed bag है, और उसे लेख में दिखाने लायक संतोषजनक बनाने के लिए अभी और काम चाहिए

1 टिप्पणियां

 
GN⁺ 2 시간 전
Hacker News की राय
  • यह मैंने पहले देखा है, इसलिए हो सकता है पूरी तरह संबंधित न हो, लेकिन Sebastian Lague का ग्रह निर्माण प्रयोगों में atmospheric rendering पर वीडियो भी वाकई बहुत दिलचस्प था https://www.youtube.com/watch?v=DxfEbulyFcY
    visual effects को विकसित होते और धीरे-धीरे वास्तविक जैसा बनते देखना अपने-आप में खास मजेदार है, और कभी न कभी मैं भी इस क्षेत्र में खुद प्रयोग करना चाहूंगा
    • Sebastian Lague के बारे में सबसे चौंकाने वाली बात यह है कि YouTube algorithm किसी इंसान के साथ कितना बुरा कर सकता है
      पहले उनके वीडियो पर लाखों views आते थे, अब 5 लाख पार करना भी मुश्किल से होता है। हो सकता है COVID के दौरान सब लोग घर पर थे और random चीजों में दिलचस्पी ले रहे थे
    • Sebastian Lague को लेकर मेरी एकमात्र शिकायत यही है कि उनके वीडियो पर्याप्त नहीं हैं
      मैं आमतौर पर उन्हें सोते समय चला देता हूँ; ऐसा शांत लेकिन गहराई से technical topics में उतरने वाला content और होता तो अच्छा लगता, यहाँ तक कि मैंने खुद ऐसा कुछ बनाने का भी सोचा है
  • पता नहीं इसे जानबूझकर छोड़ा गया है या नहीं, लेकिन sunset model में यह ध्यान देने लायक है कि सूरज के क्षितिज के नीचे जाते ही आसमान काला नहीं हो जाना चाहिए
    सूर्यास्त के बाद भी कुछ समय तक सिर के ऊपर का atmosphere और क्षितिज के ऊपर का क्षेत्र अब भी सूर्यप्रकाश पाता रहता है, और पृथ्वी के atmosphere में सूरज के क्षितिज से 18 degrees नीचे जाने तक noticeable twilight बना रहता है। ray tracing से इसे लागू करना व्यावहारिक न हो, लेकिन इसे model करने के लिए सामान्य algorithms मौजूद हैं
  • अच्छे graphics लेख हमेशा स्वागतयोग्य होते हैं। मैं भी procedural universe/planet generator में कुछ ऐसा ही काम कर चुका हूँ, और atmospheric scattering की खास बात यह है कि volumetric cloud rendering के साथ मिलकर यह शानदार sunset और sky scenes बना सकता है
    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...
  • आजकल mobile phones और browsers जो कुछ कर सकते हैं, वह सचमुच हैरान करने वाला है
    मुझे 1993 के उस paper को लागू करने की याद है, जो इस विषय का लगभग मूल काम है और काफी आसानी से पढ़ा जा सकता है, Nishita आदि का “Display of The Earth Taking into Account Atmospheric Scattering”: https://www.researchgate.net/publication/2933032_Display_of_...
    • पहले जब मैंने Rayleigh scattering और Mie scattering लागू किए थे, तब जो paper पढ़ा था वह मुझे दूसरे comment में याद आया, और यही वही है
      जब यह काम करने लगा, तब एक ऐसा पल आया कि “इतनी जटिल वास्तविक-world phenomenon को कुछ अपेक्षाकृत सरल calculations से काफी अच्छी तरह model किया जा सकता है।” एक static blue skybox से मैं तुरंत पूरे day-night cycle तक पहुँच गया
  • यह सचमुच शानदार है
    मैंने पहले कभी सोचा था कि वेब पर आसमान को कई gradients एक-दूसरे पर चढ़ाकर render करने की कोशिश की जाए। शायद कुछ हद तक सफल होकर ठीक-ठाक नतीजा मिल भी जाता, लेकिन यहाँ जो बनाया गया है उसकी तुलना ही नहीं। परिणाम प्रभावशाली है और प्रेरित करता है
    • मैंने कभी शौकिया बनाए गए game engine में Rayleigh scattering और Mie scattering लागू किए थे
      सिर्फ उससे ही काफ़ी भरोसेमंद sunset/sunrise cycle बनता देख मैं हैरान रह गया था, और अगर सही याद है तो सूरज भी किसी तरह उसी से स्वाभाविक रूप से निकलकर आ गया था। मैंने Microsoft के C# game development platform XNA का इस्तेमाल करते हुए Riemer की शानदार tutorial series को follow किया था, और उसका archive यहाँ है https://github.com/SimonDarksideJ/XNAGameStudio/wiki/Riemers...
      हालांकि scattering वाला हिस्सा वहाँ दिख नहीं रहा, इसलिए संभव है वह भाग मैंने कहीं और से लिया हो। बस इतना याद है कि मैंने equations वाले papers पढ़े थे
  • SpaceEngine भी इस क्षेत्र में काफी मेहनत के लिए जाना जाता है, इसलिए इसे ज़रूर recommend करूँगा: https://www.youtube.com/watch?v=_4TjdVAbXks
    https://spaceengine.org/
    • ऐसी चीज़ों के FAQ मुझे इसलिए पसंद हैं क्योंकि वे scale और सवालों की विविधता दोनों दिखाते हैं
      “SpaceEngine में कितने objects हैं?” के जवाब में पूरा Hipparcos star catalog, सभी ज्ञात exoplanets, 10 हज़ार से ज़्यादा galaxies, सौरमंडल की अधिकांश वस्तुएँ मिलाकर 1.3 लाख objects बताए जाते हैं। इसके ऊपर observable universe में वास्तव में मौजूद संख्या से भी ज़्यादा galaxies और stellar systems जोड़े जाते हैं। “water planet गर्म कैसे हो सकता है?” के जवाब में कहा गया है कि ऊपरी atmosphere का पानी गर्म water vapor होता है, लेकिन नीचे जाते हुए वह high pressure पर धीरे-धीरे liquid में बदलता है, और उससे भी गहराई में ice VII जैसी solid state बन जाती है। “कैसे move करें?” का जवाब है WASD keys
    • एक टैब में Wikipedia और दूसरे टैब में SpaceEngine खुला रखना मेरे पसंदीदा semi-educational gaming experiences में से एक है
      यह शानदार game है, और काफ़ी पुराना होने के बावजूद अभी तक मुझे इतना अच्छा कुछ और नहीं मिला
    • यह कई सालों से मौजूद एक शानदार software है, और सिर्फ इस विषय में ही नहीं बल्कि कई पहलुओं में detail के प्रति जुनून कमाल का है
      यह पोस्ट देखते ही मुझे भी SpaceEngine याद आ गया
  • scattering बहुत पहले से realistic rendered images बनाने की कुंजी रहा है
    मेरे पसंदीदा papers में से एक: http://www.graphics.stanford.edu/papers/bssrdf/bssrdf.pdf
    शायद पहली बार मुझे यहीं से पता चला था कि दूध को render करना एक मुश्किल समस्या है
  • वाह, यह तो काफ़ी जबरदस्त यात्रा थी
    शायद मैं इसका सिर्फ 5% ही समझ पाया, लेकिन फिर भी सचमुच दंग रह गया
    • मेरा भी वही हाल है। सिर्फ visuals के लिए भी इसे पढ़ना worthwhile था
  • ओह, यह सचमुच सुंदर और पढ़ने में आसान लेख है
    और अगर यह MIT license के तहत है, तो मेरे game की skybox समस्या मानो हल हो गई। perspective fixed रहेगा, इसलिए बस सूरज के आसमान में चलने वाला render चाहिए, और इसमें sine-wave period के साथ साल भर के solar angle बदलाव भी जोड़े जा सकते हैं