वर्चुअल टेक्सचर बनावट एटलस का तार्किक चरम है।
एक बनावट एटलस एक विशालकाय बनावट है, जिसमें इसके अंदर व्यक्तिगत जाल के लिए बनावट होती है:
बनावट atlases इस तथ्य के कारण लोकप्रिय हो गई कि बदलते बनावट के कारण GPU पर एक पूर्ण पाइपलाइन फ्लश हो जाता है। मेष बनाते समय, UVs को संकुचित / स्थानांतरित किया जाता है ताकि वे संपूर्ण बनावट एटलस के सही 'भाग' का प्रतिनिधित्व करें।
जैसा कि @ nathan-reed ने टिप्पणियों में उल्लेख किया है, बनावट atlases की मुख्य कमियों में से एक दोहराव, दबाना, सीमा, आदि जैसे रैप मोड खो रहे हैं। इसके अलावा, यदि बनावट के चारों ओर पर्याप्त सीमा नहीं है, तो आप गलती से कर सकते हैं। फ़िल्टरिंग करते समय आसन्न बनावट से नमूना। इससे रक्तस्राव कलाकृतियों को हो सकता है।
बनावट एटलस में एक प्रमुख सीमा होती है: आकार। ग्राफिक्स एपीआई एक नरम सीमा रखता है कि बनावट कितनी बड़ी हो सकती है। उस ने कहा, ग्राफिक्स मेमोरी केवल इतनी बड़ी है। तो आपके वी-राम के आकार द्वारा दी गई बनावट के आकार की एक कठिन सीमा भी है। आभासी बनावट इस समस्या को हल करती है, वर्चुअल मेमोरी से अवधारणाओं को उधार लेकर ।
आभासी बनावट इस तथ्य का फायदा उठाती है कि ज्यादातर दृश्यों में, आपको केवल सभी बनावट का एक छोटा हिस्सा दिखाई देता है। अतः, केवल उस उप-विषयवस्तु को ही विक्रम में होना चाहिए। बाकी मुख्य रैम या डिस्क पर हो सकता है।
इसे लागू करने के कुछ तरीके हैं, लेकिन मैं शॉन बैरेट द्वारा उनके जीडीसी वार्ता में वर्णित कार्यान्वयन की व्याख्या करूंगा । (जो मैं देखने की सलाह देता हूं)
हमारे पास तीन मुख्य तत्व हैं: आभासी बनावट, शारीरिक बनावट और देखने की मेज।
आभासी बनावट सैद्धांतिक मेगा एटलस का प्रतिनिधित्व करती है अगर हमारे पास सब कुछ फिट करने के लिए पर्याप्त विक्रम होता। यह वास्तव में कहीं भी स्मृति में मौजूद नहीं है। शारीरिक बनावट यह दर्शाती है कि वास्तव में हमारे पास कौन से पिक्सेल डेटा हैं। लुकअप टेबल दोनों के बीच मैपिंग है। सुविधा के लिए, हम सभी तीन तत्वों को समान आकार की टाइलों, या पृष्ठों में तोड़ देते हैं।
लुकअप तालिका भौतिक बनावट में टाइल के ऊपरी-बाएँ कोने के स्थान को संग्रहीत करती है। तो, पूरे आभासी बनावट के लिए एक यूवी दिया, हम शारीरिक बनावट के लिए इसी यूवी कैसे प्राप्त करते हैं?
सबसे पहले, हमें भौतिक बनावट के भीतर पृष्ठ का स्थान खोजने की आवश्यकता है। फिर हमें पृष्ठ के भीतर यूवी के स्थान की गणना करने की आवश्यकता है। अंत में हम भौतिक बनावट के भीतर यूवी के स्थान को प्राप्त करने के लिए इन दोनों ऑफसेटों को एक साथ जोड़ सकते हैं
float2 pageLocInPhysicalTex = ...
float2 inPageLocation = ...
float2 physicalTexUV = pageLocationInPhysicalTex + inPageLocation;
PageLocInPhysicalTex की गणना करना
अगर हम लुकअप टेबल को आभासी बनावट में टाइलों की संख्या के समान आकार का बनाते हैं, तो हम सिर्फ निकटतम पड़ोसी नमूने के साथ लुकअप टेबल का नमूना ले सकते हैं और हमें पृष्ठ की ऊपरी-बाएँ कोने का स्थान भौतिक बनावट के भीतर मिल जाएगा।
float2 pageLocInPhysicalTex = lookupTable.Sample(virtTexUV, nearestNeighborSampler);
InPageLocation की गणना
inPageLocation एक यूवी समन्वय है जो पूरे बनावट के शीर्ष-बाएं के बजाय पृष्ठ के शीर्ष-बाएं के सापेक्ष है।
इसकी गणना करने का एक तरीका पृष्ठ के शीर्ष बाईं ओर के यूवी को घटाकर, फिर पृष्ठ के आकार को स्केल करना है। हालाँकि, यह काफी गणित है। इसके बजाय, हम शोषण कर सकते हैं कि IEEE फ़्लोटिंग पॉइंट का प्रतिनिधित्व कैसे किया जाता है। IEEE फ़्लोटिंग पॉइंट बेस 2 फ्रैक्शंस की एक श्रृंखला द्वारा संख्या के भिन्नात्मक भाग को संग्रहीत करता है।
इस उदाहरण में, संख्या है:
number = 0 + (1/2) + (1/8) + (1/16) = 0.6875
अब आभासी बनावट के सरलीकृत संस्करण को देखें:
1/2 बिट हमें बताता है कि क्या हम बनावट के दाईं ओर या दाईं ओर हैं। 1/4 बिट हमें बताता है कि हम आधे में से किस तिमाही में हैं। इस उदाहरण में, चूंकि बनावट 16 में विभाजित है, या 4 एक तरफ, ये पहले दो बिट्स हमें बताते हैं कि हम किस पेज में हैं। बिट्स हमें पृष्ठ के अंदर का स्थान बताते हैं।
हम एक्सपैट 2 () के साथ फ्लोट को शिफ्ट करके और उन्हें फ्रैक्चर से बाहर निकालकर शेष बिट्स प्राप्त कर सकते हैं।
float2 inPageLocation = virtTexUV * exp2(sqrt(numTiles));
inPageLocation = fract(inPageLocation);
जहाँ numTiles एक int2 है जो बनावट के अनुसार प्रति टाइल की संख्या दे रहा है। हमारे उदाहरण में, यह (4, 4) होगा
तो चलो हरे बिंदु के लिए inPageLocation की गणना करते हैं, (x, y) = (0.6875, 0.375)
inPageLocation = float2(0.6875, 0.375) * exp2(sqrt(int2(4, 4));
= float2(0.6875, 0.375) * int2(2, 2);
= float2(1.375, 0.75);
inPageLocation = fract(float2(1.375, 0.75));
= float2(0.375, 0.75);
एक आखिरी बात हम करने से पहले करते हैं। वर्तमान में, InPageLocation आभासी बनावट 'अंतरिक्ष' में एक यूवी समन्वय है। हालांकि, हम भौतिक बनावट 'स्पेस' में एक यूवी समन्वय चाहते हैं। ऐसा करने के लिए हमें बस inPageLocation को आभासी बनावट के आकार से भौतिक बनावट के आकार के अनुपात में स्केल करना होगा
inPageLocation *= physicalTextureSize / virtualTextureSize;
तो समाप्त समारोह है:
float2 CalculatePhysicalTexUV(float2 virtTexUV, Texture2D<float2> lookupTable, uint2 physicalTexSize, uint2 virtualTexSize, uint2 numTiles) {
float2 pageLocInPhysicalTex = lookupTable.Sample(virtTexUV, nearestNeighborSampler);
float2 inPageLocation = virtTexUV * exp2(sqrt(numTiles));
inPageLocation = fract(inPageLocation);
inPageLocation *= physicalTexSize / virtualTexSize;
return pageLocInPhysicalTex + inPageLocation;
}