प्रोसीजरल गेम डेवलपमेंट के लिए पसंदीदा टूल और तकनीकें
(cprimozic.net)- ब्राउज़र में चलने वाले 3D scene और level project बड़े होते गए, तो पूरे world generation के बजाय level के खास हिस्सों पर procedural·generative techniques लागू करने वाले reusable tools जमा होते गए
- texture work का केंद्र Triplanar Mapping और Hex Tiling है, जिनका उपयोग UV के बिना texture लगाने या दोहराए जाने वाले pattern छिपाने में होता है
- दोनों तकनीकों में interpolation weights पर
pow()लागू करके प्रमुख axis या lookup result का वज़न बढ़ाया जाता है, और कुछ texture lookup skip करके performance का बोझ कम किया जाता है - महंगे fragment shader को Depth Pre-Pass से हल्का किया जा सकता है, और जिन scene में overdraw ज़्यादा हो वहाँ performance 30% से अधिक बेहतर हो सकती है
- mesh·geometry की तरफ LoD terrain, runtime mesh processing pipeline, और आगे Constructive Solid Geometry के जरिए decoration, background और damage expression को विस्तार देने की दिशा दिखती है
ब्राउज़र 3D scene में जमा हुए procedural tools
- कई सालों तक ब्राउज़र में चलने वाले 3D scenes and levels बनाते-बनाते, custom shader पर केंद्रित standalone demo आपस में जुड़कर game जैसे रूप में बढ़ते गए
- साझा तरीका यह रहा कि पूरी तरह procedural world बनाने के बजाय level के कुछ खास हिस्सों पर procedural·generative techniques लागू की जाएँ
- कई level में बार-बार इस्तेमाल होने वाले procedural और semi-procedural tools व effects स्वाभाविक रूप से जमा होते गए
Shader और texture
- ज़्यादातर texture दोनों अक्षों में बिना seam के tile होने वाली seamless texture हैं, लेकिन बड़े क्षेत्र में फैलाने पर दोहराव वाले pattern साफ़ दिख सकते हैं
- Three.JS के
MeshPhysicalMaterialको extend करने वाले custom shader में कई feature जोड़कर seamless texturing support को बेहतर बनाया गया -
Triplanar Mapping
- Triplanar Mapping लगभग हर level में इस्तेमाल होने वाला core texturing tool है
- predefined UV map के बिना seamless texture से mesh को texture किया जा सकता है, इसलिए procedural terrain जैसे मामलों में यह उपयोगी है जहाँ modeler को UV mapping परिभाषित करने का मौका नहीं मिलता
- यह generated mesh और hand-modeled mesh दोनों पर अच्छी तरह काम करता है
- इसका implementation हल्का और सरल है, और reference implementation triplanarMapping.ts में है
-
Triplanar Mapping में सुधार
- सामान्य Triplanar Mapping fragment normal के आधार पर तीन axes की texture lookup को linear blend करता है
- जहाँ normal किसी एक axis के बहुत करीब नहीं होता, वहाँ texture परतों जैसी दिख सकती है
- weights पर high-exponent
pow()लागू करके फिर normalize करने से dominant axis का योगदान बढ़ता है और transition area छोटा हो जाता है - इस बदलाव से mesh के अधिकांश हिस्सों में एक axis का weight 1 के करीब और बाकी दो axes के weights 0 के करीब हो जाते हैं
- threshold से छोटे weight वाली texture lookup skip करके, Triplanar Mapping का performance overhead सामान्य UV-based texturing से थोड़ा ही अधिक रखा जा सकता है
- normal map processing के लिए shader code में अलग ध्यान देना पड़ता है, और इसके लिए GPU Gems method का उपयोग किया जाता है
- implementation details Normal Mapping for a Triplanar Shader में देखे जा सकते हैं
-
Hex Tiling
- Hex Tiling seamless texture में दिखने वाली tiling और repetition को छिपाने वाला algorithm है
- material में सिर्फ़ एक setting option जोड़ने से scene का look कम-गुणवत्ता वाले mockup जैसा होने से semi-realistic के करीब पहुँच सकता है
- शुरुआती implementation Fabrice Neyret के Shadertoy पर आधारित था, जिसे Three.JS material system के हिसाब से बदलकर project के main material shader में integrate किया गया
- बाद में अनुमति लेकर इसे एक standalone library three-hex-tiling के रूप में port किया गया, जो Three.JS project के built-in material में Hex Tiling जोड़ सकती है
- Triplanar Mapping के विपरीत, इसमें predefined UV mapping चाहिए
- दोनों तकनीकों को साथ इस्तेमाल करने पर हर map के लिए प्रति fragment texture fetch की संख्या 27 तक पहुँच सकती है, इसलिए यह व्यावहारिक नहीं है
- Hex Tiling भी हर fragment पर तीन lookup result को linear interpolate करता है, इसलिए Triplanar Mapping में इस्तेमाल की गई
pow()weighting technique से performance और result quality दोनों सुधारी जा सकती हैं
-
Depth Pre-Pass
- उन्नत texturing techniques बड़े scene में महंगे fragment shader बना सकती हैं
- Depth Pre-Pass में पूरे scene को पहले बहुत simple और सस्ते material से render किया जाता है ताकि हर pixel की depth दर्ज हो जाए
- scene को दो बार render करने का overhead होता है, लेकिन जिन scene में overdraw ज़्यादा हो वहाँ आमतौर पर इसका लाभ लागत से बड़ा होता है
- overdraw ज़्यादा होने पर Depth Pre-Pass जोड़ने से performance 30% से अधिक सुधर सकती है
- pre-pass settings बदलकर सिर्फ़ occluded fragment render किए जा सकते हैं, जिससे यह visualize किया जा सकता है कि pre-pass इस्तेमाल करने पर कौन से fragment skip हो जाते हैं
- Three.JS implementation और settings details dedicated article में देखे जा सकते हैं
-
AI-आधारित PBR texture synthesis
- AI-generated texture लगभग हर scene में इस्तेमाल होती हैं
- संयम से उपयोग करने पर नतीजे काफ़ी अच्छे दिख सकते हैं, और उदाहरण वाले scene की सभी texture AI-generated हैं
- texture generation, PBR map generation, और बिना upscaling के seamless 4K texture में मिलाने की प्रक्रिया अलग लेख में दी गई है
- उस लेख में PBR map generation के लिए जिस website का ज़िक्र है, वह अब उपलब्ध नहीं है
- अभी normal map generation के लिए DeepBump का उपयोग होता है, और ज़रूरत पड़ने पर दूसरे map के लिए Materialize जैसे non-AI tool इस्तेमाल होते हैं
-
Volumetric Fog/Clouds
- volumetric rendering ऐसा क्षेत्र रहा है जिसमें रुचि बनी रही, क्योंकि यह scene को अलग तरह के effects दे सकता है
- एक अपेक्षाकृत generic shader बनाया गया जो किसी भी Three.JS scene में cloud या fog जोड़ सकता है
- Inigo Quilez के Shadertoy से प्रेरित होकर similar LoD noise lookup वाला basic volumetric clouds shader बनाया गया, और बाद में उसे अधिक general तथा configurable रूप में बढ़ाया गया
- यह shader sparse level के खाली स्थान भरने और चलती हुई cloud या fog के जरिए static level में dynamic feel जोड़ने में उपयोगी है
three-good-godraysproject में n8programs द्वारा विकसित code और approach का कुछ उपयोग भी किया गयाthree-good-godraysभी अक्सर इस्तेमाल होता है, और level में बहुत अलग atmosphere जोड़ता है
Mesh और geometry
- runtime mesh generation अब धीरे-धीरे अधिक महत्वपूर्ण क्षेत्र बनता जा रहा है
- software seed से world के उगने का विचार पसंद है, लेकिन procedural generation पर ज़ोर देने वाले कुछ game में दिखने वाली “अनंत लेकिन खाली” स्थिति से बचना चाहा गया है
- इसलिए पूरे core experience को procedural बनाने के बजाय मुख्य ध्यान level में decoration, background, procedural flourish जोड़ने पर है
-
LoD Terrain
- terrain generation procedural game development का एक प्रतिनिधि क्षेत्र है, और इसका implementation अपने आप में असाधारण नहीं है
- अधिकांश तरीकों की तरह, noise function से terrain heightmap बनाया जाता है और फिर उसे triangle में tessellate करके render किया जाता है
- texturing के लिए Triplanar Mapping या Hex Tiling का उपयोग होता है
- असली कुंजी LoD system है, जिसमें terrain को tile units में बनाया जाता है और हर tile को कई resolutions में generate किया जाता है
- tile और camera के बीच की दूरी के आधार पर अलग-अलग resolution को dynamic रूप से swap किया जाता है
- यह terrain generation system बार-बार reuse होता है, और इसकी flexible व efficient संरचना की वजह से कम मेहनत में कई level पर लागू किया जा सकता है
-
Procedural mesh processing·manipulation pipeline
- हाल में सबसे ज़्यादा काम procedural mesh processing pipeline पर किया गया है
- शुरुआती लक्ष्य low-poly mesh को, dynamically generated mesh सहित, procedural तरीके से subdivide और deform करना था
- मकसद यह था कि platform, boulder और बड़े structure जैसे simple mesh को level में रखने पर वे अधिक realistic या interesting दिखें
- यह काम ब्राउज़र runtime में raw geometry data लेकर उसे मनचाहे तरीके से modify करने और फिर renderable format में export करने वाली software pipeline तक पहुँचा
- इस प्रक्रिया में खास तौर पर normal processing के लिए बारीक ध्यान देना पड़ता है
- implementation details subdividing meshes for displacement लेख में हैं
अगला प्रयोग: Constructive Solid Geometry
- यहाँ सूचीबद्ध ज़्यादातर tool मूल रूप से किसी खास उपयोग के लिए one-off implementation के रूप में शुरू हुए थे, लेकिन बाद में दूसरे level और context में बार-बार reuse हुए
- आगे आज़माने की प्रमुख सोच Constructive Solid Geometry है
- Constructive Solid Geometry 3D space में boolean operator लागू करने वाली system है
- किसी भी दो mesh को जोड़ा जा सकता है
- mesh से chunk काटे जा सकते हैं
- और इसी तरह के दूसरे manipulation किए जा सकते हैं
- csg.js लगभग 500 LoC की एक annotated JavaScript file में mesh primitive, boolean operator और साफ़ API वाला CSG toolkit implement करता है
- कभी भविष्य में इस library को Rust में port करते हुए इसके काम करने के तरीके को और अच्छी तरह समझने की योजना है
- CSG को मौजूदा mesh processing pipeline के साथ इस्तेमाल करने पर दिलचस्प नतीजे निकलने की संभावना है
- खास तौर पर mesh को procedural तरीके से damage करने की क्षमता आज़माने की इच्छा है
- building या bridge से chunk काटकर decay या weathering simulate करना
- wall या road में crack generate करना
1 टिप्पणियां
Hacker News की टिप्पणियां
मैंने पहले procedural generation के साथ थोड़ा काम किया था, खासकर अच्छे दिखने वाले पेड़ बनाने की कोशिश की थी, लेकिन जो चीज़ मेरे पास नहीं थी वह geometry को आसानी से जोड़ने का तरीका था
दो cylinder बनाना आसान है, लेकिन दोनों को स्वाभाविक तरीके से जोड़ना बहुत मुश्किल था
सिद्धांत रूप में CSG इस कमी को पूरा कर सकता है, लेकिन समस्या को उस तरह से सोचना आसान नहीं था। इसे सिर्फ vertices जोड़ने वाले loop की तरह नहीं देख सकते, क्योंकि हर चीज़ को 3D shape के रूप में model करना पड़ता है
मैंने एक routine भी बनाई थी जो दो vertex loops लेकर heuristic से faces जोड़कर उन्हें connect करती थी, लेकिन कौन-से vertices आपस में जोड़ने हैं, यह चुनना उम्मीद से कहीं ज्यादा मुश्किल निकला, और खराब दिखने वाले connections बहुत आसानी से बन जाते थे
कभी मैं ऐसा game बनाना चाहूंगा जिसमें अलग-अलग modular procedural generation systems अपनी spontaneity बनाए रखते हुए साथ काम करें। जैसे systems world के किसी हिस्से को “occupy” करें, उस हिस्से को किसी दूसरे system को delegate करें, या आसपास की चीज़ों से naturally connect करें
हाल में generative trees बनाने का एक video [0] था, और solution बस cylinders को एक-दूसरे को intersect करने देना था। ऐसे hacky तरीके भी अच्छे से काम कर सकते हैं और result ठीक-ठाक हो सकता है
जैसा कहा, CSG भी संभव है लेकिन बहुत ज्यादा complex हो सकता है। एक और तरीका है पेड़ का skeleton बनाकर lofting करना, और जरूरत हो तो CSG के साथ combine करके trunk और bark बनाना
अच्छी libraries संभावनाएं खोल देती हैं। अगर ऐसी 3D geometry library मिल जाए जो cylinder union या geometry subtraction जैसे boolean operations करे, तो आप बहुत-से नए ideas try कर सकते हैं। मैंने कुछ इस्तेमाल की हैं, लेकिन जो थोड़ी पसंद आई वह सिर्फ JSCAD [1] थी
[0] https://youtu.be/8zMbJmuwEUc?si=KQclrVPeSrIRmsbA
[1] https://github.com/jscad/OpenJSCAD.org
यह 3D shapes को functional तरीके से describe और transform करने जैसा है
demoscene में लोगों ने इससे क्या किया है यह देखने के लिए YouTube पर Mercury Delight search करने की strongly recommend करूंगा। Shadertoy पर भी बहुत examples हैं, और सच में काफी कमाल की चीज़ें हैं
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Condition...
नीचे वाला example भी देखने लायक है
https://github.com/MaxBondABE/batteries/blob/master/src/geom...
अच्छी terrain generation बिल्कुल trivial नहीं है, चाहे world scale पर हो या eye-level scale पर
simple approach, जैसा कि article में दिखता है, एक bumpy heightmap बनाता है, जो असली terrain जैसा बहुत कम दिखता है और explore करने में भी खास दिलचस्प नहीं होता
उदाहरण के लिए Dwarf Fortress basic midpoint displacement से शुरू करता है, लेकिन बाद में काफी custom post-processing करता है
इस article में बताई गई चीज़ों में से कोई भी, धुंधले तौर पर भी, trivial नहीं है। लेखक GPU shader rendering के मामले में धरती पर लगभग किसी भी व्यक्ति की तुलना में साफ तौर पर 100x developer के करीब हैं
“simple approach”, क्या सच में simple है?
8 अरब लोगों में कितने प्रतिशत लोग इस article को शुरू करने के लिए जरूरी “Hello World” step तक implement कर सकते होंगे? और कितनों को पता होगा कि shader क्या होता है? OpenGL jobs भी इतनी ज्यादा नहीं हैं। “OpenGL क्या है, हम तो सिर्फ Unity इस्तेमाल करते हैं” जैसी स्थिति भी आम है
online gamers का क्या? 28 जुलाई 2024, दोपहर 1:22 EST तक Counter Strike 2 में online 1,021,282 लोगों [1] में से कितने प्रतिशत लोग अपने खेले जा रहे game के लिए जरूरी shader का पहला step भी implement कर सकते होंगे?
कितने प्रतिशत लोग एक simple command-line C++ program compile कर सकते होंगे या browser में और भी simple JavaScript script लिख सकते होंगे? असल में यह थोड़ा trick question है, क्योंकि ज्यादातर लोग email भी मुश्किल से manage कर पाते हैं
[1] https://steamdb.info/app/730/charts/
AI की तरह, सबसे अच्छी procedural content generation में भी final output के लिए custom post-processing होगी
web में इस्तेमाल होने वाली कई procedural techniques का यह अच्छा संकलन है, इसलिए काफी मददगार है
अगर आप उस procedural RPG level editor में interested हैं जिस पर मैं काम कर रहा हूं, तो https://github.com/gamedevgrunt/3D-Action-RPG-JavaScript देख सकते हैं
depth pre-pass इस्तेमाल करने का मेरा अनुभव mixed रहा है
कुछ बार try करने पर mid-range से high-end desktop GPUs पर मुझे noticeable performance improvement नहीं दिखा
सही वजह नहीं पता, लेकिन हो सकता है early Z rejection ने pixel shader calls कम कर दी हों। आमतौर पर opaque mesh को front-to-back order में render किया जाता है
हालांकि मेरे experiments games के बजाय CAD/CAM application के context में थे। scenes भी typical game environment से काफी अलग थे, textures कम थे और polygon count बहुत ज्यादा वाली geometry थी
depth pre-pass अक्सर occlusion culling का पहला step भी होता है, लेकिन यह भी situation पर निर्भर करता है। CAD model की तुलना में complex cityscape में यह कहीं ज्यादा useful होने की संभावना है
यह तब सबसे useful होता है जब depth complexity high हो और fragment shader महंगा हो। निष्पक्ष रूप से कहें तो ज्यादातर games इसी category में आते हैं
deferred renderer में आमतौर पर यह जरूरी नहीं होता, लेकिन forward+ में generally काफी फायदा देता है