Browser में open world बनाना, भाग 27: noise से बना एक island, ऐसी ज़मीन जो ज़मीन जैसी दिखे
लेखक Oleg Sidorkin, Cinevva के CTO और सह-संस्थापक
यहां नए हैं? series guide का इस्तेमाल करें। यह बताती है कि spike क्या होता है और सभी भागों को जोड़ती है।
भाग 26 ने world पर पानी रखा। यह भाग उसके नीचे की ज़मीन बनाता है, दो चरणों में जो इस बात का अक्स हैं कि कोई असली जगह कैसे बनती है। Spike 54 खुद terrain है: हाथ से नहीं गढ़ा गया बल्कि noise से उगाया गया, फिर तब तक मौसम और कटाव झेलता रहा जब तक उसमें वैसी drainage और coastline न आ गई जैसी किसी ऐसी जगह की होती है जहां सचमुच पानी बहा हो। Spike 55 उस terrain की त्वचा है: उस समस्या को हल करना जो लगभग हर procedural ज़मीन को हरा देती है, यानी कि एक tiled texture tiled ही दिखती है। दोनों मिलकर एक सवाल का जवाब देते हैं, क्या कोई creator बिना किसी artist के छुए एक भरोसेमंद island और ऐसी ज़मीन पा सकता है जो ज़मीन जैसी पढ़ी जाए, और जवाब है हां, बशर्ते आप सही recipes की नकल करें।
एक coastline जो अकेला noise आपको नहीं देगा
Spike 54 को नए tab में खोलें ↗ · Source देखें
Heightmap, Red Blob Games की recipes का अनुसरण करता है, जो छोटे-छोटे transforms का एक ढेर हैं और हर एक raw noise की किसी खास खामी को ठीक करता है। Fractional Brownian motion, Perlin noise के कई octaves को जोड़ता है ताकि terrain में चौड़ी पहाड़ियां और बारीक detail दोनों हों, लेकिन सादा FBM नरम और grid के साथ संरेखित दिखता है, इसलिए sample point को पहले domain-warp किया जाता है: आप हर coordinate को एक और noise field से खिसकाते हैं,
इससे आपको एक shape मिल जाता है, लेकिन वह noise का shape है। इसमें कोई नदियां नहीं हैं, पानी से कटी कोई घाटियां नहीं, कोई sediment fans नहीं, क्योंकि इस पर कभी कुछ बहा ही नहीं। इसका हल है hydraulic erosion, जो Sebastian Lague के MIT-licensed implementation से port किया गया है। हज़ारों पानी की बूंदें यादृच्छिक जगहों पर पैदा होती हैं और ढलान से नीचे लुढ़कती हैं, हर एक के पास inertia होता है ताकि वह तीखे समकोण मोड़ न ले, तेज़ होने पर sediment उठाती है और धीमी होने या जमा होने पर उसे जमा करती है, साथ ही एक पहले से गणना किया गया circular brush हर erosion घटना को एक छोटे radius में फैला देता है ताकि कटाव एक pixel की खरोंच के बजाय smooth रहे, और evaporation जो बूंद को उसके जीवनकाल में retire कर देता है। पर्याप्त बूंदें चलाओ और terrain वह चीज़ उगा लेता है जिसे noise नकली नहीं बना सकता: ऐसी drainage networks जो मिलती हैं, घाटियां जो नीचे की ओर चौड़ी होती जाती हैं, और सपाट जगहें जहां sediment बैठ गया।
GPU पर erosion, और नदियां जो जानती हैं कि वे कहां हैं
CPU erosion सही है मगर धीमा, इसलिए spike इसे एक WebGPU compute shader में भी port करता है, और दिलचस्प हिस्सा यह है कि GPU atomics आप पर क्या मजबूर कर देते हैं। Heights को fixed-point i32 के रूप में दस लाख के scale पर store किया जाता है, क्योंकि WGSL में floats पर atomic add नहीं है, और हज़ारों बूंदों के लिए एक ही cell से बिना races के समानांतर sediment जमा करने और हटाने का इकलौता तरीका integers पर atomicAdd और atomicSub है। Fixed-point round-trip का मतलब है कि भारी समानांतर drag के तहत कोई cell कभी-कभार थोड़ा negative हो सकता है, जो हानिरहित है और readback पर clamp कर दिया जाता है। CPU version हर cell के लिए एक brush table पहले से गणना करता है, मगर
दो और passes मौसम-कटाव झेले terrain को एक पढ़ने योग्य map में बदल देते हैं। Drainage, Red Blob D8 flow-accumulation method इस्तेमाल करता है: हर cell पर बारिश की एक इकाई डालो, सभी cells को elevation के घटते क्रम में sort करो, और हर cell का जमा पानी उसके इकलौते सबसे नीचे वाले पड़ोसी को पास कर दो, ताकि पानी प्राकृतिक घाटियों के साथ ढेर हो जाए, और जिस भी cell का accumulation एक threshold पार करता है उसे river चिह्नित कर दिया जाता है। पेच यह है कि एक eroded heightmap में pits होते हैं, यानी ऐसी स्थानीय गहराइयां जिनसे नीचे की ओर कोई निकास नहीं, और pit में घुसता पानी बस रुक जाता है, जिससे accumulation टूट जाता है। इसलिए drainage चलने से पहले Planchon-Darboux pit filling हर pit को उसके सबसे नीचे वाले पड़ोसी से ज़रा ऊपर तक उठा देता है,
वह tile जो दोहराना बंद नहीं करता
Spike 55 को नए tab में खोलें ↗ · Source देखें
एक terrain को ऐसे material की ज़रूरत होती है जो एक ऐसी texture से किलोमीटरों को ढके जो कुछ ही मीटर चौड़ी है, और जिस पल आप एक tile को ज़मीन ढकने के लिए बड़ा करते हैं, आंख दोहराव पर अटक जाती है। Spike 55 एक ही geometry और lighting पर चार sampling modes का एक A/B bench है, ताकि इकलौता चर यही रहे कि texture कैसे पढ़ी जाती है। Baseline है plain: scaled UV पर एक sample, जो हर कुछ मीटर पर साफ़ tile करता है और सिर्फ़ इसलिए मौजूद है ताकि उसे हराया जा सके। मुफ़्त PBR layers Poly Haven से उनके CDN के ज़रिए आती हैं, diffuse के साथ packed ARM map (ambient occlusion, roughness, metalness) के साथ एक GL normal, सब CC0, anisotropy 8 और mipmaps के साथ load किए गए।
दिलचस्प तीन, repeat पर अलग-अलग हमले हैं। hex-linear mode, Heitz-Neyret triangle grid है: surface पर एक तिरछी triangular lattice बिछाओ, और हर fragment एक triangle के अंदर बैठता है जिसके तीनों vertices एक-एक यादृच्छिक रूप से खिसका हुआ tap लेते हैं, barycentric weights से blend किया जाता है ताकि पड़ोसी क्षेत्र texture के अलग-अलग हिस्सों को sample करें और बड़े पैमाने की tiling घुल जाए। मगर तीन taps का सादा linear blend triangle के किनारों पर उनके रंगों का औसत निकाल देता है, जिससे एक दिखाई देने वाला triangular pattern बच जाता है, ठीक वही artifact जिससे spike 48 टकराया था। hex-vp mode उसी 2018 के paper से प्रकाशित fix है: barycentric sum के बाद, texture के mean color को घटाओ, squared weights के sum के inverse square root से rescale करो ताकि variance स्थिर रहे, फिर mean को वापस जोड़ दो। इससे blend भर में contrast स्थिर रहता है ताकि triangles गायब हो जाएं, यही वजह है कि material हर load की गई texture का 1-by-1 readback करता है ताकि पहले से उसके mean color का अंदाज़ा लगा सके। चौथा mode, iq-untiled, Inigo Quilez की Texture Repetition technique 3 है: एक low-frequency variation pattern से blend किए गए दो offset taps, तीन के बजाय बस दो samples और शुरू से कोई triangle structure नहीं, सस्ता विकल्प जो टिका रहता है।
किसी भी mode के ऊपर एक वैकल्पिक triplanar projection बैठता है, यही वह चीज़ है जो उसी material को बिना खींचे एक cliff पर लपेटने देती है। एक UV के बजाय, shader तीन world-axis projections को sample करता है, X की ओर वाली surfaces YZ plane पढ़ती हैं, Y, ZX पढ़ता है, Z, XY पढ़ता है, और इन्हें abs(normalWorld) से blend करता है जिसे चार और आठ के बीच एक sharpening power तक उठाया जाता है ताकि 45-डिग्री की ढलान तीनों projections को घोलकर लुगदी न बना दे। Bench इस अदला-बदली को साफ़ कर देता है: variance-preserving hex blending गुणवत्ता का विजेता है और Quilez का two-tap performance के लिहाज़ से सजग वाला, और दोनों plain को इतने बड़े अंतर से हराते हैं कि किसी creator को कभी plain tile ship नहीं करनी चाहिए।
इस अध्याय में बताई गई technology
Recipe-stacked heightmap generation. Red Blob Games की recipes raw noise को terrain में बुनती हैं: organic ridges के लिए domain-warped FBM (
Hydraulic erosion, CPU और GPU. Sebastian Lague का droplet model (inertia, carrying capacity, एक पहले से गणना किया गया circular deposit brush, evaporation) असली drainage काटता है जिसे noise नकली नहीं बना सकता। WebGPU compute port heights को दस लाख के scale पर fixed-point i32 के रूप में store करता है ताकि बूंदें एक ही cell को समानांतर रूप से atomicAdd/atomicSub कर सकें,
Pit filling के साथ D8 drainage. Red Blob D8 flow accumulation हर cell पर बारिश की एक इकाई डालता है, cells को घटते elevation के क्रम में sort करता है, और हर cell का पानी उसके सबसे नीचे वाले पड़ोसी को पास करता है, एक threshold से ऊपर वाली नदियों को चिह्नित करते हुए। Planchon-Darboux pit filling पहले हर स्थानीय गहराई को
Texture tiling को चार तरीकों से तोड़ना. एक जैसी geometry और lighting पर: plain (एक tap, साफ़ tile करता है), hex-linear (Heitz-Neyret triangle grid, linear blend एक triangle pattern छोड़ देता है), hex-vp (EGSR 2018 §3.3 variance-preserving fix जो mean घटाता है, squared weights के inverse-sqrt से rescale करता है, और mean को फिर से जोड़ता है, हर texture के लिए एक 1×1 mean readback चाहिए), और iq-untiled (Inigo Quilez two-tap technique 3)। Triplanar projection तीन world-axis planes को sample करता है जिन्हें abs(normalWorld) से 4-8 की power तक blend किया जाता है ताकि cliffs न खिंचें। variance-preserving गुणवत्ता पर जीतता है, two-tap लागत पर। देखें terrain materials।
29 में से भाग 27। पिछला: भाग 26 - पानी बनाने के तीन तरीके अगला: भाग 28 - क्षितिज तक घास, और ऐसी ज़मीन जो खुद को छुपा लेती है Series guide: /hi/blog/2026-02-25-open-world-browser-series-guide