2012-05-28 18 views
7

के साथ Omnidirectional छाया मानचित्रण मैं omnidirectional बिंदु रोशनी के साथ काम कर रहा हूँ। मैंने पहले से ही 6 फ्रेमबफर के रंग अटैचमेंट के रूप में एक क्यूबमैप बनावट का उपयोग करके छाया मैपिंग लागू किया है, और प्रत्येक पिक्सेल में प्रकाश-से-खंड दूरी को एन्कोड कर रहा है।गहराई cubemap

अब मैं, चाहते हैं, तो यह संभव है, मेरी कार्यान्वयन इस तरह से बदलने के लिए:

  • 1), मेरे framebuffers की गहराई बफर करने के लिए एक गहराई cubemap बनावट देते हैं रंग की बजाय।
  • 2) केवल गहराई से प्रस्तुत करना,,, मुख्य पास में यह पास
  • 3) में रंग लिख सकता हूँ नहीं cubemap बनावट से गहराई पढ़ यह एक दूरी में बदलने का है, और जाँच वर्तमान टुकड़ा द्वारा occluded रहा है या नहीं प्रकाश या नहीं।

मेरी समस्या तब होती है जब क्यूबमैप से गहराई मूल्य को दूरी में परिवर्तित किया जाता है। मैं cubemap में अपनी गहराई मूल्य लाने के लिए प्रकाश-से-खंड वेक्टर (विश्व अंतरिक्ष में) का उपयोग करता हूं। इस बिंदु पर, मुझे नहीं पता कि छह चेहरों का उपयोग किस प्रकार किया जा रहा है, न ही 2 डी बनावट निर्देशांक जो गहराई मूल्य पढ़ रहा हूं उससे मेल खाता है। तो मैं उस गहराई मूल्य को दूरी में कैसे परिवर्तित कर सकता हूं?

यहाँ मेरी कोड के स्निपेट वर्णन करने के लिए कर रहे हैं:

गहराई को बनावट:

glGenTextures(1, &TextureHandle); 
glBindTexture(GL_TEXTURE_CUBE_MAP, TextureHandle); 
for (int i = 0; i < 6; ++i) 
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, 
       Width, Height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); 

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

framebuffers निर्माण:

for (int i = 0; i < 6; ++i) 
{ 
    glGenFramebuffers(1, &FBO->FrameBufferID); 
    glBindFramebuffer(GL_FRAMEBUFFER, FBO->FrameBufferID); 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
      GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, TextureHandle, 0); 
    glDrawBuffer(GL_NONE); 
} 

टुकड़ा शेडर का टुकड़ा मैं प्राप्त करने के लिए लिखने के लिए कोशिश कर रहा हूँ मेरा कोड:

float ComputeShadowFactor(samplerCubeShadow ShadowCubeMap, vec3 VertToLightWS) 
{ 
    float ShadowVec = texture(ShadowCubeMap, vec4(VertToLightWS, 1.0)); 
    ShadowVec = DepthValueToDistance(ShadowVec); 
    if (ShadowVec * ShadowVec > dot(VertToLightWS, VertToLightWS)) 
     return 1.0; 

    return 0.0; 
} 

DepthValueToDistance फ़ंक्शन मेरी वास्तविक समस्या है।

+0

"क्या मेरी समस्या का समाधान है?" दूरी को गहराई में कनवर्ट करें, क्यूबमैप में संग्रहीत गहराई से तुलना करें। "घन नक्शा छाया के लिए अपरिवर्तनीय" मुझे लगता है कि 5..7 साल पहले किसी को "रॉन फ्रैज़ियर" कहा जाता था, छाया मैपिंग के लिए क्यूबमैप्स का उपयोग करने के बारे में एक लेख लिखा था। – SigTerm

+0

@ सिगटर्म http://www.ronfrazier.net/apparition/index.html?appmain=research/index.html मुझे लगता है कि आप किस बारे में बात कर रहे हैं। –

+0

@ जोहान रिसेलवेटो: हाँ। मैं ** सोचता हूं ** यह [यह] था (http://www.ronfrazier.net/apparition/index.html?appmain=research/index.html) आलेख। आधुनिक ओपनजीएल/बेहतर परिशुद्धता के साथ कुछ ऐसा करना संभव है (फ्लोटिंग पॉइंट बनावट, जीएलएसएल, '* छाया 'नमूने इत्यादि हैं) - मेरे पास बस एक काम करने वाला स्निपेट नहीं है और एक लिखना पसंद नहीं है । – SigTerm

उत्तर

10

तो, समाधान क्यूबमैप से दूरी में पढ़ने की गहराई को परिवर्तित करने के बजाय, प्रकाश-से-खंड वेक्टर को गहराई मूल्य में परिवर्तित करना था।

float VectorToDepthValue(vec3 Vec) 
{ 
    vec3 AbsVec = abs(Vec); 
    float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z)); 

    const float f = 2048.0; 
    const float n = 1.0; 
    float NormZComp = (f+n)/(f-n) - (2*f*n)/(f-n)/LocalZcomp; 
    return (NormZComp + 1.0) * 0.5; 
} 

float ComputeShadowFactor(samplerCubeShadow ShadowCubeMap, vec3 VertToLightWS) 
{ 
    float ShadowVec = texture(ShadowCubeMap, vec4(VertToLightWS, 1.0)); 
    if (ShadowVec + 0.0001 > VectorToDepthValue(VertToLightWS)) 
     return 1.0; 

    return 0.0; 
} 

Explaination पर VectorToDepthValue(vec3 Vec):

LocalZComp क्या cubemap का मिलान छिन्नक में दिया Vec की जेड घटक होगा से मेल खाती है

यहाँ संशोधित शेडर कोड है। यह वास्तव में Vec का सबसे बड़ा घटक है (उदाहरण के लिए यदि Vec.y सबसे बड़ा घटक है, तो हम या तो वाई + या क्यूबमैप के वाई-चेहरे पर देखेंगे)।

यदि आप इस wikipedia article को देखते हैं, तो आप गणित को समझने के बाद (मैंने इसे समझने के औपचारिक रूप में रखा है) को समझेंगे, जो कि LocalZComp को सामान्यीकृत जेड मान में परिवर्तित करता है ([-1.1.1] के बीच) और फिर इसे [0..1] में मैप करें जो गहराई बफर मानों के लिए वास्तविक सीमा है। (मानते हुए कि आपने इसे नहीं बदला है)। n और f क्यूबमैप उत्पन्न करने के लिए उपयोग किए जाने वाले फ्रस्टम्स के निकट और दूर मूल्य हैं।

ComputeShadowFactor तो बस गहराई मूल्य टुकड़ा करने वाली प्रकाश वेक्टर (यहाँ VertToLightWS नाम) से गणना की है, यह भी एक छोटे से गहराई पूर्वाग्रह जोड़ने के साथ cubemap से गहराई का मान (जो सवाल में याद आ रही थी), और रिटर्न की तुलना 1 अगर प्रकाश प्रकाश द्वारा गुमराह नहीं किया जाता है।

4

मैं व्युत्पन्न के बारे में अधिक जानकारी जोड़ना चाहता हूं।

वी प्रकाश-से-खंड दिशा वेक्टर बनें।

Benlitz जैसा कि पहले ही कहा, संबंधित घन पक्ष छिन्नक/"आंख अंतरिक्ष" में जेड मूल्य वी के शुद्ध मान का अधिकतम निकालकर किया जा सकता है के घटकों।

Z = max(abs(V.x),abs(V.y),abs(V.z)) 

फिर, सटीक होना करने के लिए, हम जेड क्योंकि ओपन में, स्क्रीन/दृश्य छिन्नक में नकारात्मक Z- अक्ष अंक नकारना चाहिए।

अब हम उस -Z के गहराई बफर "संगत" मान प्राप्त करना चाहते हैं।

ओपन परिप्रेक्ष्य मैट्रिक्स को देखते हुए ...

http://www.songho.ca/opengl/files/gl_projectionmatrix_eq16.png

http://i.stack.imgur.com/mN7ke.png (बैकअप लिंक)

... हम देखते हैं कि, के लिए किसी भी सजातीय वेक्टर कि मैट्रिक्स के साथ गुणा , परिणामी जेड मान वेक्टर के एक्स और वाई घटकों से पूरी तरह से स्वतंत्र है।

तो हम बस इस मैट्रिक्स सजातीय वेक्टर के साथ गुणा कर सकते हैं (0,0, -Z, 1) और हम वेक्टर (घटकों) मिलती है:

x = 0 
y = 0 
z = (-Z * -(f+n)/(f-n)) + (-2*f*n/(f-n)) 
w = Z 

फिर हम परिप्रेक्ष्य क्या करने की जरूरत विभाजन है, तो हम डब्ल्यू (जेड) जो हमें देता है द्वारा जेड विभाजित:

z' = (f+n)/(f-n) - 2*f*n/(Z* (f-n)) 

इस z 'ओपन के सामान्यीकृत डिवाइस समन्वय (एनडीसी) की सीमा [-1,1] में है और एक के रूप में तब्दील करने की आवश्यकता है गहराई बफर compatibl के ई रेंज [0,1]:

z_depth_buffer_compatible = (z' + 1.0) * 0.5 

इसके अलावा नोट:

  • यह के परिणाम (च + एन) अपलोड करने के लिए कोई मतलब हो सकता है, (एफ एन) और (च * एन) गणना को बचाने के लिए शेडर वर्दी के रूप में।

  • वी दुनिया अंतरिक्ष में हैं, क्योंकि छाया घन नक्शा सामान्य रूप से इस तरह दुनिया अंतरिक्ष में गठबंधन अक्ष है "अधिकतम (पेट (Vx), पेट (Vy), पेट (VZ))" की जरूरत है - भाग केवल तभी काम करता है जब वी एक विश्व अंतरिक्ष दिशा वेक्टर है।

संबंधित मुद्दे