मैं एचएलएसएल के साथ चौड़े कोण / फिशये लेंस कैसे बना सकता हूं?


29

अलग-अलग छोरों के एक विस्तृत कोण लेंस के प्रभाव को प्राप्त करने के लिए किन अवधारणाओं को लागू करने की आवश्यकता है?

Pseudocode और विशिष्ट विवरण सामग्री पाइपलाइन के विभिन्न चरणों, साथ ही स्रोत कोड से HLSL में पारित करने के लिए क्या जानकारी की आवश्यकता है, बहुत उपयोगी होगा।

इसके अलावा, वाइड-एंगल लेंस को लागू करने और फिशिए के बीच क्या अंतर हैं?

जवाबों:


37

वाइड-एंगल लेंस को अन्य नियमित लेंस मॉडल की तुलना में अलग व्यवहार नहीं करना चाहिए। उनके पास बस एक बड़ा FOV है ( D3DXMatrixPerspectiveFovLHअर्थ में - मैं मान रहा हूं कि आप DirectX का उपयोग करते हैं), या बड़ा बाएं / दाएं और नीचे / शीर्ष मान (ओपनजीएल glFrustumअर्थ में)।

मेरा मानना ​​है कि वास्तव में दिलचस्प हिस्सा फिशये लेंस के मॉडलिंग में निहित है। वहाँ Fisheye भूकंप है कि आप अध्ययन कर सकते हैं, यह स्रोत के साथ आता है।

सच फिशये प्रोजेक्शन

एक फिशये लेंस का प्रक्षेपण, हालांकि, गैर-रैखिक है। अधिक सामान्य (मेरी जानकारी के लिए, जो निगरानी कैमरों तक सीमित है) लेंस की तरह, Mअंतरिक्ष में एक बिंदु को एक इकाई गोलार्ध की सतह पर पेश किया जाता है, फिर वह सतह इकाई डिस्क पर एक समानांतर प्रक्षेपण से गुजरती है:

           M
             x                 M: world position
              \                M': projection of M on the unit hemisphere
               \  ______       M": projection of M' on the unit disc (= the screen)
             M'_x'      `-.
             ,' |\         `.
            /   | \          \
           /    |  \          \
          |     |   \          |
__________|_____|____\_________|_________
                M"    O        1

अन्य फिशये मैपिंग हैं जो अधिक दिलचस्प प्रभाव दे सकते हैं। यह आप पर निर्भर करता है।

मैं एचएलएसएल में फिशी प्रभाव को लागू करने के दो तरीके देख सकता हूं।

विधि 1: शीर्ष छाया पर प्रक्षेपण करते हैं

फायदा : कोड में लगभग कुछ भी बदलने की जरूरत नहीं है। टुकड़ा shader अत्यंत सरल है। बजाय:

...
float4 screenPoint = mul(worldPoint, worldViewProjMatrix);
...

आप ऐसा कुछ करते हैं (शायद बहुत सरल किया जा सकता है):

...
// This is optional, but it computes the z coordinate we will
// need later for Z sorting.
float4 out_Point = mul(in_Point, worldViewProjMatrix);

// This retrieves the world position so that we can project on
// the hemisphere. Normalise this vector and you get M'
float4 tmpPoint = mul(in_Point, worldViewMatrix);

// This computes the xy coordinates of M", which happen to
// be the same as M'.
out_Point.xy = tmpPoint.xy / length(tmpPoint.xyz);
...

कमियां : चूंकि रेखीय परिवर्तनों के लिए पूरी रेंडरिंग पाइपलाइन पर विचार किया गया था, जिसके परिणामस्वरूप प्रक्षेपण लंबवत के लिए सटीक है, लेकिन सभी भिन्नताएं गलत होंगी, साथ ही बनावट निर्देशांक, और त्रिकोण अभी भी त्रिकोण के रूप में दिखाई देंगे, भले ही उन्हें विकृत होना चाहिए।

वर्कअराउंड : यह GPU के लिए एक परिष्कृत ज्यामिति भेजकर एक बेहतर सन्निकटन प्राप्त करने के लिए स्वीकार्य हो सकता है, जिसमें अधिक त्रिभुज उपविभाग होते हैं। यह एक ज्यामिति shader में भी किया जा सकता है, लेकिन चूंकि यह कदम शीर्ष shader के बाद होता है, ज्यामिति shader काफी जटिल होगा क्योंकि इसे अपने स्वयं के अतिरिक्त अनुमानों को पूरा करना होगा।

विधि 2: टुकड़ा shader पर प्रक्षेपण करें

एक अन्य विधि एक विस्तृत कोण प्रक्षेपण का उपयोग करके दृश्य को प्रस्तुत करना होगा, फिर एक फुलस्क्रीन टुकड़ा shader का उपयोग करके एक फिशये प्रभाव प्राप्त करने के लिए छवि को विकृत करें।

यदि बिंदु Mको (x,y)फिशिय स्क्रीन में निर्देशांक है, तो इसका मतलब है कि यह (x,y,z)गोलार्ध की सतह पर निर्देशांक के साथ था z = sqrt(1-x*x-y*y)। इसका मतलब यह है कि यह (ax,ay)हमारे दृश्य में निर्देशांक था thetaकि इस तरह की एक FOV के साथ गाया a = 1/(z*tan(theta/2))। (यहां मेरे गणित के बारे में 100% निश्चित नहीं है, मैं आज रात फिर से जांच करूंगा)।

टुकड़ा shader इसलिए कुछ इस तरह होगा:

void main(in float4 in_Point : POSITION,
          uniform float u_Theta,
          uniform sampler2D u_RenderBuffer,
          out float4 out_FragColor : COLOR)
{
    z = sqrt(1.0 - in_Point.x * in_Point.x - in_Point.y * in_Point.y);
    float a = 1.0 / (z * tan(u_Theta * 0.5));
    out_FragColor = tex2D(u_RenderBuffer, (in_Point.xy - 0.5) * 2.0 * a);
}

लाभ : आपको पिक्सेल सटीकता के कारण उन लोगों के अलावा कोई विकृतियों के साथ एक परिपूर्ण प्रक्षेपण मिलता है।

दोष : आप शारीरिक रूप से पूरे दृश्य को नहीं देख सकते हैं, क्योंकि FOV 180 डिग्री तक नहीं पहुंच सकता है। इसके अलावा, FOV जितना बड़ा होता है, छवि के केंद्र में उतना ही सटीक होता है ... जो कि सटीक है जहां आप अधिकतम परिशुद्धता चाहते हैं।

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

(नोट: यदि आपको यह उपयोगी लगता है लेकिन पर्याप्त स्पष्ट नहीं है, तो कृपया मुझे बताएं, मुझे ऐसा लगता है कि इस बारे में अधिक विस्तृत लेख लिखना है)।


बहुत उपयोगी है, और मैं और अधिक विस्तृत लेख का स्वागत करना चाहता हूं जो आप पूरे दिल से लिखना चाहते हैं!
सिरयाकोट

क्या बेहतर परिणाम प्राप्त करने के लिए दोनों दृष्टिकोणों को जोड़ना संभव होगा? पहले वीएस में सब कुछ देखने के लिए प्रोजेक्शन करते हैं और फिर पीएस में अप्रमाणित करते हैं और सही यूवी और सब कुछ पाने के लिए फिर से प्रोजेक्ट करते हैं? मूल रूप से सही ढंग से अप्रमाणित करने के लिए PS को कुछ और पैरामीटर भेजना आवश्यक हो सकता है।
ओन्ड्रेज पेट्रिजल्का

3

यह होना चाहिए z = sqrt(1.0 - in_Point.x * in_Point.x - in_Point.y * in_Point.y), है ना?

मेरा GLSL कार्यान्वयन है:

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoord;
uniform sampler2D u_texture;
uniform float fovTheta; // FOV's theta

// fisheye
void main (void)
{   
    vec2 uv = v_texCoord - 0.5;
    float z = sqrt(1.0 - uv.x * uv.x - uv.y * uv.y);
    float a = 1.0 / (z * tan(fovTheta * 0.5));
//  float a = (z * tan(fovTheta * 0.5)) / 1.0; // reverse lens
    gl_FragColor = texture2D(u_texture, (uv* a) + 0.5);
}

हे @ जोश, कैसे fovTheta की गणना की गई थी?
टॉम

1
मैंने केवल स्वरूपण को समायोजित करने के लिए इस उत्तर को संपादित किया, मुझे विश्वास है कि आप सीधे @bman को संबोधित करना चाहते हैं।
जोश
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.