Table of Contents
फाउंडेशन: तीन-आयामी अंतरिक्ष का प्रतिनिधित्व
एक एकल पिक्सेल तैयार होने से पहले, एक 3D इंजन में अंतरिक्ष में वस्तुओं का वर्णन करने के लिए एक गणितीय भाषा होनी चाहिए। कोर में vector] (तीन घटक टपल स्थिति, दिशा, या रंग का प्रतिनिधित्व करते हैं) और matrices (4×4 सरणी जो रूपांतरणों को एन्कोड करती हैं)]]]]]. C में, ये आम तौर पर सरल संरचना के रूप में परिभाषित किए जाते हैं:
- ]]] अंक और वेक्टर के लिए।
- ] ]] ] ]] ] []] []]]]]] []]]]]]] ]]]]]] []]]]] स्तंभ-माजर आदेश में संग्रहीत परिवर्तन मैटरिस के लिए।
प्रत्येक वस्तु triangles[ से बना है। एक त्रिकोण को तीन vertices द्वारा परिभाषित किया गया है, प्रत्येक एक स्थिति के साथ, और वैकल्पिक रूप से एक सामान्य और रंग। इन को एक क्यूब के लिए एक सुसंगत सरणी (जैसे, ]]] के रूप में संग्रहीत किया जाता है) कैश दक्षता में सुधार करता है - एक महत्वपूर्ण विचार जब आप बाद में फ्रेम प्रति हजारों चेहरे की प्रक्रिया करते हैं।
ग्राफिक्स पाइपलाइन: वर्टिक्स से पिक्सेल तक
एक ग्राफिक्स पाइपलाइन चरणों का एक अनुक्रम है जो 3 डी दृश्य डेटा को 2 डी छवि में बदल देता है। एक बुनियादी सॉफ्टवेयर-रेंडर इंजन में, आप प्रत्येक चरण को मैन्युअल रूप से लागू करते हैं। मुख्य चरण हैं:
- ]Vertex प्रसंस्करण - मॉडल, दृश्य और प्रक्षेपण को लागू करने में सक्षम है।
- Rasterization - परिवर्तित त्रिकोण को टुकड़ों (संभाव्य पिक्सल) में परिवर्तित करना।
- ]Shading – प्रकाश और सामग्री के आधार पर प्रत्येक टुकड़े के रंग की गणना।
- Output Merging – फ्रेम बफर के साथ टुकड़े मिश्रण, जिसमें गहराई परीक्षण शामिल है।
हार्डवेयर-accelerated इंजन (OpenGL, Vulkan, या DirectX का उपयोग करके) GPU पर इन चरणों का अधिकांश प्रदर्शन करते हैं, लेकिन सॉफ्टवेयर पथ को समझने से आपको गहरे अंतर्दृष्टि मिलती है कि GPU हुड के तहत कैसे काम करता है।
Vertex प्रसंस्करण और परिवर्तन
हर vertex शुरू होता है मॉडल अंतरिक्ष (स्थानीय वस्तु के सापेक्ष समन्वय)। इसे दुनिया में तैनात करने के लिए, आप एक ]] मॉडल मैट्रिक्स लागू करते हैं जो अनुवाद, रोटेशन और स्केलिंग को एन्कोड करता है। फिर view मैट्रिक्स विश्व को कैमरा-रिलिंडर निर्देशांक (view space) में बदल देता है। अंत में, प्रोजेक्शन मैट्रिक्स ]] नक्शे एक सामान्यीकृत प्रणाली (]] के लिए स्थान देखें।
C में परिवर्तन कार्य जैसे दिखते हैं:
- ]]] - एक पहचान मैट्रिक्स लौटाता है।
- - अनुवाद मैट्रिक्स का निर्माण करता है।
- ]] - X अक्ष के आसपास घूर्णन।
- ]] - 4-element वेक्टर (संभव्य निर्देशांक) द्वारा 4 × 4 मैट्रिक्स को गुणा करता है।
सॉफ्टवेयर में बराबर वर्टेक्स शेडर सभी vertices पर iterates, संयुक्त मैट्रिक्स द्वारा प्रत्येक गुणा, और परिणाम को एक परिवर्तित vertex बफर में स्टोर करता है।
प्रोजेक्शन: परिप्रेक्ष्य बनाम ऑर्थोग्राफिक
प्रोजेक्शन को नियंत्रित करता है कि स्क्रीन पर गहराई का प्रतिनिधित्व कैसे किया जाता है। Perspective प्रोजेक्शन दूरस्थ वस्तुओं को छोटा बनाता है, यथार्थवाद बनाता है। इसका मैट्रिक्स व्यू, पहलू अनुपात, निकट और दूर-दूर तक के क्लिपिंग विमानों के क्षेत्र से बनाया गया है। क्लासिक सूत्र में z ( मैट्रिक्स गुणन के बाद) द्वारा x और y घटकों को विभाजित करना शामिल है। C में, आप एक बार प्रोजेक्शन मैट्रिक्स का संकलन करते हैं और इसे हर फ्रेम का पुन: उपयोग करते हैं:
- ]] - एक मानक परिप्रेक्ष्य मैट्रिक्स लौटाता है।
Orthographic प्रोजेक्शन समानांतर रेखाओं को संरक्षित करता है और यह सरल है, जिसका उपयोग यूआई या सीएडी उपकरणों के लिए किया जाता है। इसमें परिप्रेक्ष्य विभाजन शामिल नहीं है।
Rasterization: भरने त्रिकोण
प्रक्षेपण के बाद, आपके पास 2 डी स्क्रीन निर्देशांक (जैसे पिक्सेल पोजीशन) और गहराई मान (z) है। Rasterization प्रत्येक त्रिकोण को पूर्णांक पिक्सेल निर्देशांक को कवर करने वाले टुकड़ों में तोड़ देता है। क्लासिक एल्गोरिदम scanline रूपांतरण :
- त्रिभुज के तीन vertices को वाई-समिति द्वारा क्रमबद्ध करें।
- बाएं और दाएं किनारों को नीचे चलना, प्रत्येक स्कैनलाइन के लिए एक्स सीमाओं की गणना करना।
- प्रत्येक पिक्सेल के लिए क्षैतिज अवधि में, त्रिकोण के पार अंतर करके खंड की गहराई की गणना करें।
- ] गहन परीक्षण : गहराई बफर में पहले से ही मूल्य के साथ टुकड़े के z की तुलना करें। यदि करीब, गहराई बफर अद्यतन करें और खंड के रंग की गणना करें।
सी में कुशलतापूर्वक किनारे-चलने वाले एल्गोरिदम को लागू करने के लिए तंग छोरों और फ्लोटिंग-पॉइंट ओवरहेड से बचने के लिए निश्चित-पॉइंट अंकेटिक का सावधानीपूर्वक उपयोग की आवश्यकता होती है। कई शौकी इंजन एक brute-force दृष्टिकोण (बाध्यक्ष बॉक्स में प्रत्येक पिक्सेल की जांच) के साथ शुरू होते हैं और बाद में किनारे समीकरणों के साथ अनुकूलन करते हैं।
छायांकन और प्रकाश
एक साधारण फ्लैट-शेड इंजन प्रति त्रिकोण एक एकल रंग का उपयोग करता है, जो चेहरे सामान्य और एक एकल प्रकाश स्रोत से जुड़ा होता है। Lambertian मॉडल फैलाव तीव्रता देता है: .C में, आप सामान्य को दो त्रिकोण किनारों के क्रॉस उत्पाद के रूप में गणना करते हैं (विश्व अंतरिक्ष के लिए vertices को बदलने के बाद) तो त्रिकोण के आधार रंग द्वारा प्रकाश तीव्रता को गुणा करते हैं।
गहराई जोड़ने के लिए, Gouraud shading (vertex normals, खंडों में interpolated) या Phong shading (प्रति पिक्सेल सामान्य)]. बाद में विश्व की स्थिति और सामान्य रूप से अनुवाद करने की आवश्यकता है, फिर प्रति टुकड़ा प्रकाश की गणना - अधिक महंगा लेकिन नाटकीय रूप से बेहतर परिणाम।
C: प्रैक्टिकल स्टेप्स में इंजन का निर्माण
चलो स्क्रैच से एक न्यूनतम सॉफ्टवेयर 3 डी इंजन के निर्माण के माध्यम से चलते हैं। लक्ष्य 640 × 480 पिक्सेल विंडो पर परिवेश और फैल प्रकाश व्यवस्था के साथ घूर्णन घन प्रदान करना है।
स्टेप 1 - एक पिक्सेल बफर सेट करें
फ्रेम और गहराई के लिए एक मेमोरी बफर को परिभाषित करें: और . फ्रेमबफ़र को ब्लैक और गहराई बफर को 1.0 (फरवरी प्लेन) प्रत्येक फ्रेम में साफ़ करें।
चरण 2 - दृश्य डेटा को परिभाषित करें
एक घन के लिए, छह चेहरे (12 त्रिकोण) को 12 × 3 = 36 vertices की आवश्यकता होती है। उन्हें स्थिति (3 फ्लोट) और रंग (3 आरजीबी के लिए तैरता) के साथ संरचनाओं की एक सरणी में स्टोर करें। 8 अद्वितीय क्यूब कोनों और छह चेहरे के रंगों को पूर्व-परिभाषित करें। वर्टिक्स को दोहराने से बचने के लिए एक इंडेक्स बफर का उपयोग करें।
चरण 3 - परिवर्तन पाइपलाइन
प्रत्येक फ्रेम, मॉडल मैट्रिक्स को एक कोण से गणना करते हैं (जैसे, घुमाने वाले)), एक निश्चित कैमरा से दृश्य मैट्रिक्स जो मूल पर नजर आते हैं, और प्रोजेक्शन मैट्रिक्स। उन्हें एक एकल MVP मैट्रिक्स में जोड़ दें: [[FLT: 12]]]. [[FLT: 13]]]] के साथ गुणा करके हर vertex को बदल दें। फिर परिप्रेक्ष्य में विभाजित करें (विभाजन x, वाई, जेड द्वारा) सामान्यीकृत उपकरण निर्देशांक (-1 से + 1) प्राप्त करने के लिए। स्क्रीन निर्देशांक के लिए मानचित्र: [[FLT: 14]], [[FLT: 15]] (y उलटा). गहराई परीक्षण के लिए NDC z रखें।
चरण 4 - रैस्टराइज़ और शेड
प्रत्येक त्रिकोण के लिए, स्कैनलाइन विधि का उपयोग करें। जबकि चलने वाले पिक्सल गहराई को इंटरपोलेट करते हैं और दुनिया-स्पेस स्थिति (Phong के लिए) या गोउराउड के लिए) जैसे प्रति-विरोध विशेषता को भी इंटरपोलेट करते हैं। लैम्बर्टियन फैलाव समीकरण लागू करें। फ्रेमबफ़र को अंतिम रंग लिखें यदि गहराई परीक्षण गुजरता है।
चरण 5 - प्रदर्शन
SDL (Simple DirectMedia लेयर) या विंडो बनाने के लिए एक समान पुस्तकालय का प्रयोग करें और फ्रेमबफ़र को जला दें। उदाहरण के लिए, SDL2: ], ], ]]], ], तो ] और प्रत्येक फ्रेम।
यह सॉफ्टवेयर पथ CPU पर चलता है, इसलिए प्रदर्शन प्रति फ्रेम कुछ हजार त्रिकोण तक सीमित है। एक बार आरामदायक, आप ओपनजीएल के साथ विकिरण परत को प्रतिस्थापित कर सकते हैं, जिससे आपके परिवर्तन और दृश्य तर्क को सी में रखते हुए जीपीयू को भारी काम को बंद कर दिया जा सकता है।
अपने इंजन को अनुकूलित करना
एक बुनियादी इंजन धीमी है। कई अनुकूलन वास्तविक समय के प्रदर्शन के लिए आवश्यक हैं:
- बैक-फेस क्यूलिंग: छोड़ो त्रिकोण जिनकी सामान्य कैमरे से दूर बिंदु है। अनुमानित त्रिकोण (2D में) के हस्ताक्षरित क्षेत्र को पूरा करें या देखने की दिशा के साथ सामान्य चेहरे के डॉट उत्पाद की जांच करें।
- ]Frustum culling: view frustum के छह विमानों के खिलाफ एक वस्तु के सीमा बॉक्स का परीक्षण करें। यदि पूरी तरह से बाहर है, तो पूरे ऑब्जेक्ट को छोड़ दें।
- ]Fixed-point arithmetic: तंग rasterization loops में पूर्ण गणित के साथ फ्लोटिंग-पॉइंट ऑपरेशन बदलें। कई इंजन बिल्डरों ने स्कैनलाइन इंटरपोलेशन के लिए 16.16 फिक्स्ड-पॉइंट का उपयोग किया।
- ]पूर्व ट्रांसफॉर्म कैश: एक बार जाल के सभी vertices को बदलकर एक ही vertex को कई बार बदलने से बचें, फिर सूचकांकों का उपयोग करते हुए।
- ]Blocked फ्रेम बफर लिखते हैं: कैश हिट को अधिकतम करने के लिए स्मृति-आदेश (बाएं-टू-राइट, टॉप-टू-बॉटम) में पिक्सेल लिखें।
ये तकनीक एक सॉफ्टवेयर रेंडर को 3-5 एफपीएस से 60 एफपीएस तक मध्यम जटिलता के दृश्यों के लिए धक्का दे सकती है (उदाहरण के लिए, कुछ सौ त्रिकोण)।
इंजन का विस्तार करना
एक बार जब एक ठोस आधार मौजूद होता है, तो आप सुविधाओं को बढ़ा सकते हैं:
- Texture मैपिंग:2D छवियों को स्टोर करें और त्रिकोणों के पार यूवी निर्देशांक को इंटरपोलेट करें। चिकनी परिणामों के लिए द्विरेखीय फ़िल्टरिंग लागू करें।
- Advanced shading: जोड़ें specular हाइलाइट्स (Blinn-Phong), ambient occlusion, या यहां तक कि छाया मानचित्र.
- Scene प्रबंधन:एक octree या BSP पेड़ का प्रयोग जल्दी से यह निर्धारित करने के लिए कि कौन से ऑब्जेक्ट दिखाई देते हैं।
- User बातचीत: कैमरा को कक्षाबद्ध करने या ऑब्जेक्ट चुनने के लिए कीबोर्ड और माउस इनपुट को हैंडल करें।
- Pipeline अमूर्त: एक छायांकन प्रणाली डिजाइन: वर्टेक्स और विखंडन कार्यों को फंक्शन पॉइंटर्स के रूप में परिभाषित करें, जो बिना किसी पुनरावृत्ति के लचीला प्रतिपादन को सक्षम बनाता है।
संसाधन और आगे पढ़ना
अपनी समझ को गहरा करने के लिए, इस इंजन को प्रेरित करने वाले क्लासिक टेक्स्ट और ऑनलाइन ट्यूटोरियल का पता लगाएं:
- ]Scratchapixel - रे ट्रेसिंग, rasterization, और गणित के गहन स्पष्टीकरण।
- ]LearnOpenGL – Modern OpenGL ट्यूटोरियल; "Hello Triangle" अध्याय के साथ शुरू।
- Wikipedia: 3D प्रोजेक्शन] - परिप्रेक्ष्य और आर्थोग्राफिक मैटरिस के पीछे औपचारिक गणित।
C में एक 3D इंजन का निर्माण ग्राफिक्स प्रोग्रामर के लिए मार्ग का एक संस्कार है। यह आपको न केवल कुशल कोड लिखने का तरीका सिखाता है बल्कि तीन आयामों में सोचने और प्रदर्शन-महत्वपूर्ण प्रणालियों को समझने का तरीका भी सिखाता है। एक एकल घूर्णन घन के साथ शुरू करें, फिर अधिक त्रिकोण, बनावट जोड़ें, और अंत में इसे GPU को सौंप दें। कच्चे C से पूरी तरह कार्यात्मक इंजन तक की यात्रा स्क्रीन पर हर पिक्सेल के पीछे जादू प्रकट करती है।