प्रकाश संगणना के लिए वर्ग त्रिज्या और व्युत्क्रम वर्ग त्रिज्या की उपयोगिता क्या है?


16

स्लाइड 3 में से एक पर "डायरेक्टएक्स 11 बैटलफील्ड 3 में रेंडरिंग" पावरपॉइंट मैंने फ़ॉउलिंग कोड पर ध्यान दिया:

struct Light {
    float3 pos; float sqrRadius;
    float3 color; float invSqrRadius;
}

मुझे समझ में नहीं आता है कि वे केवल त्रिज्या के भंडारण के बजाय वर्ग त्रिज्या और यहां तक ​​कि उलटा वर्ग (जो मेरा मानना ​​है कि 1 वर्ग त्रिज्या है) को क्यों संग्रहीत करेंगे? वे इस डेटा का उपयोग अपनी संगणना में कैसे कर रहे हैं? इसके अलावा, शंकु और लाइन रोशनी के बारे में क्या? यह संरचना केवल बिंदु रोशनी के लिए होनी चाहिए, मैं इसे अन्य प्रकारों के लिए काम नहीं कर सकता - पर्याप्त डेटा नहीं है। फिर भी मुझे यह जानकर अच्छा लगेगा कि वे उस वर्ग और इनस्वक्वेयर का उपयोग कैसे करते हैं।

अद्यतन: ठीक है, मैं अंत में मिल गया।

यहाँ क्लासिक प्रकाश क्षीणन समीकरण है, आसानी से नेट पर पाया जाता है:

float3 lightVector = lightPosition - surfacePosition;

float attenuation = saturate(1 - length(lightVector)/lightRadius);

यह length(lightVector)वास्तव में यह कर रहा है के रूप में अपेक्षाकृत महंगा है:

length(lightVector) = sqrt(dot(lightVector, lightVector);

इसके अलावा विभाजन ऑपरेशन (/lightRadius)भी काफी महंगा है।

इस तरह से प्रकाश क्षीणन की गणना करने के बजाय, आप इसे निम्न तरीके से गणना कर सकते हैं, जो बहुत तेज़ होगा:

attenuation = saturate(1 - dot(lightVector, lightVector)*invRadiusSqr);

जहाँ invRadiusSqr को CPU स्तर पर पूर्व-संगणित किया जा सकता है और एक shader स्थिरांक के रूप में पारित किया जाता है।

इसके अलावा, आपको परिणाम के रूप में एक द्विघात प्रकाश क्षीणन प्राप्त होता है (पूर्व मामले में रैखिक के बजाय), जो और भी बेहतर है, क्योंकि IRL प्रकाश में द्विघात फलन है।

आपकी मदद के लिए सभी को शुक्रिया!


13
गद्दी। शेड्स 16bytes संरेखित हैं। और यदि आप एक नज़र डालते हैं कि कोड कैसे बनता है, तो आप देखेंगे कि यह दो फ़्लोट 4 में पैक हो जाएगा। जब आप इसे कैश से मुक्त करेंगे तो कुछ उपयोगी स्टोर क्यों नहीं करेंगे?
टोरिन

जवाबों:


23

यह केवल एक प्रकार का अनुकूलन है invSqrRadius = 1/SqrRadius, जो हर बार प्रत्येक प्रकाश के लिए व्युत्क्रम वर्ग त्रिज्या की गणना करने के बजाय, बस इसे कैश करता है, इसका कारण यह है कि विभाजन आमतौर पर गुणा की तुलना में कम से कम "धीमा" ऑपरेशन होता है।

यह अनुकूलन विशेष रूप से प्रासंगिक है:

  • जब ऑपरेशन प्रत्येक प्रकाश के लिए कई बार किया जाता है, तो मूल्य को कैशिंग करने से अतिरिक्त सीपीयू / जीपीयू चक्र मुक्त हो जाएंगे
  • और मान पढ़ने के लिए मेमोरी एक्सेस समय मान लेना वास्तव में इसे पुनर्गणना करने की तुलना में तेज़ है।

इसका उपयोग कैसे किया जाता है, इस बारे में मैं उनके विशिष्ट कार्यान्वयन के बारे में निश्चित नहीं हूं, लेकिन इसके बारे में 1/sqrRadius, इसका उपयोग केवल हल्के क्षीणन, फॉलऑफ और पुलिंग के लिए किया जाता है। यह दिशात्मक और स्पॉटलाइट के लिए भी प्रासंगिक है, स्पॉटलाइट के मामले में एकमात्र अंतर यह है कि क्षीणन लगाने के बाद आपको स्पॉटलाइट कारक की गणना करने की आवश्यकता है । सूरज की तरह दिशात्मक रोशनी के संबंध में, इसमें आमतौर पर कोई क्षीणन या गिरावट नहीं होती है, इसलिए मुझे लगता है कि इसे अनदेखा किया जाएगा।

[संपादित करें] अधिक विस्तृत करने के लिए, यह अप्रासंगिक डेटा नहीं है । प्रकाश विकिरण की गणना निम्नलिखित समीकरण का उपयोग करके की जा सकती है:

E = Phi / 4 * pi * rSqr;

कहाँ पे

प्रवाह का क्षेत्र घनत्व है।

Phi मूलाधार प्रवाह है।

4 * pi * rSqr एक गोले का सतह क्षेत्र है।

यह समीकरण बताता है कि क्यों प्राप्त ऊर्जा की मात्रा चुकता दूरी के साथ गिर जाती है।

एक अन्य बिंदु यह है कि आपको एक विशिष्ट शीर्ष पर प्रकाश योगदान की गणना करने के लिए शीर्ष और प्रकाश के बीच की दूरी की गणना करने की आवश्यकता है (यह मान कैश होने की संभावना नहीं है), शीर्ष प्रकाश बिंदु में या बाहर हो सकता है जो हमें अगले बिंदु पर लाता है। Radius Squareकुल्लिंग के लिए उपयोगी कहाँ है।

यदि आप लाइट फॉलऑफ और कलिंग की गणना के लिए एक व्यावहारिक उदाहरण चाहते हैं, तो यह विशेष रूप से टाइल आधारित बेस्ड रेंडरर्स में उपयोगी है, यहां एक उदाहरण है


शाप, तुम मुझे 7 सेकंड से हरा दो! ;) (और अधिक व्यापक उत्तर के साथ, भी!)
ट्रेवर पॉवेल

विस्तृत टिप्पणी के लिए धन्यवाद, लिंक के लिए esp! बाद के लिंक से मुझे जो समझ में आया, बैटलफील्ड 3 में त्रिज्या नहीं बल्कि प्रकाश स्रोत और प्रकाश रिसीवर के बीच वास्तविक दूरी है, है ना? वह "घ" मान है जो वे लेख में उपयोग करते हैं।
क्यूब्रमैन

@cubrman कोड देखे बिना अटकलें लगाना कठिन है। मेरा अनुमान है कि यह विलोम त्रिज्या है। और उनके द्वारा उपयोग किए जाने वाले समीकरण लेख से बहुत भिन्न हो सकते हैं।
concept3d

लेकिन मुझे बताओ, आप प्रकाश गणना में एक नंगे उल्टे प्रकाश त्रिज्या का उपयोग कैसे कर सकते हैं? नेट पर पाया गया हर स्रोत मुझे बताता है कि मुझे प्राप्त सतह और प्रकाश स्रोत के बीच DISTANCE को खोजने की आवश्यकता है, मूल प्रकाश त्रिज्या द्वारा उत्तर को विभाजित करें और परिणाम को वर्ग करें। आप कभी चुकता त्रिज्या या invSqrRadius का उपयोग कहाँ करेंगे? यह मेरे लिए पूरी तरह अप्रासंगिक डेटा की तरह लगता है।
शावक

1
@cubrman ने उत्तर को अपडेट किया।
कॉन्सेप्ट

6

invSqrRadius 1 नहीं है - sqrRadius; यह 1 / sqrRadius है।

इसका मतलब है कि आप sqrRadius द्वारा विभाजन के बजाय invSqrRadius से गुणा कर सकते हैं (क्योंकि विभाजन आमतौर पर गुणा से अधिक महंगा है)


6

यहाँ अन्य उत्तर उलटे वर्ग त्रिज्या से निपटते हैं, लेकिन मैं इसके बजाय वर्ग त्रिज्या को देखने जा रहा हूं (जो कि अवधारणा 3 डी पर स्पर्श किया गया था, लेकिन मेरा मानना ​​है कि यह आगे की चर्चा करता है)।

दूरी की तुलना के लिए कौन से वर्ग उपयोगी हैं। हम जानते हैं कि दो बिंदुओं के बीच की दूरी की गणना में एक वर्गमूल शामिल होता है, और वर्गमूलों की गणना करना महंगा होता है, लेकिन यदि हम सब करना चाहते हैं तो दूरी का उपयोग करें (यह पता लगाने के लिए कि कौन सा कम या अधिक है, और आधार पर कुछ दिलचस्प करें परिणाम) हम वर्गमूल निकाल सकते हैं।

यदि sqrt (x)> sqrt (y) है तो यह भी मामला है कि x> y।

एक प्रकाश के लिए, चौकोर त्रिज्या प्रकाश के केंद्र के बीच की दूरी के समान है और यह अधिकतम सीमा है - चुकता।

प्रकाश गणना के लिए इसका उपयोग एक प्रारंभिक-आउट मामले के लिए किया जा सकता है। यदि आप उस बिंदु के बीच की दूरी जो आप प्रकाश कर रहे हैं और प्रकाश का केंद्र (वर्ग) वर्ग त्रिज्या से अधिक है, तो बिंदु प्रकाश नहीं भरता है और आपको अपनी शेष गणनाएँ चलाने की आवश्यकता नहीं है। इसलिए यह सिर्फ एक अनुकूलन है (एक काफी सामान्य) - हम महंगी वर्ग जड़ों के बिना दूरी की तुलना करने के लिए चुकता त्रिज्या का उपयोग कर सकते हैं, और सिर्फ एक घटाव और डॉट उत्पाद की लागत पर।

मैं, निश्चित रूप से, नहीं जानता कि क्या यह ठीक है कि BF3 इसके लिए उपयोग कर रहा है, लेकिन मुझे उम्मीद है कि मैं निशान से बहुत दूर नहीं हूं।


तो अगर मैं आपको सही तरीके से समझाता हूं, तो कोड होगा: if (dot (lightPos - surfacePos), (lightPos - SurfacePos))> lightRadiusSqr) प्रकाश व्यवस्था नहीं करते हैं, है ना?
क्यूब्रमैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.