2013-01-07 52 views
5

में सामान्य घुमाएं मेरे पास व्यक्तिगत स्थिति और घूर्णन वाले कई मॉडल के साथ एक दृश्य है। मानदंडों को देखते हुए, शेडर्स प्रत्येक पिक्सेल को सरल बिडरेक्शनल लाइटिंग लागू करते हैं।शेडर

यह मेरा कट्टर शेडर है।

#version 150 

in vec3 position; 
in vec3 normal; 
in vec2 texcoord; 

out vec3 f_normal; 
out vec2 f_texcoord; 

uniform mat4 model; 
uniform mat4 view; 
uniform mat4 proj; 

void main() 
{ 
    mat4 mvp = proj * view * model; 

    f_normal = normal; 
    f_texcoord = texcoord; 

    gl_Position = mvp * vec4(position, 1.0); 
} 

और यहां खंड टुकड़ा है।

#version 150 

in vec3 f_normal; 
in vec2 f_texcoord; 

uniform sampler2D tex; 

vec3 sun = vec3(0.5, 1.0, 1.5); 

void main() 
{ 
    vec3 light = max(0.0, dot(normalize(f_normal), normalize(sun))); 

    gl_FragColor = texture(tex, f_texcoord) * vec4(light, 1.0); 
} 

रोटेशन के बिना वस्तुओं के लिए यह ठीक काम करता है। लेकिन घुमावदार मॉडल के लिए प्रकाश भी घुमाया जाता है, बेशक, यह मामला नहीं होना चाहिए।

इसका कारण यह है कि मानक घुमाए नहीं जाते हैं। मैंने पहले से ही f_normal = model * normal; की कोशिश की है लेकिन यह मानकों में घूर्णन और परिवर्तन दोनों लागू होता है।

तो मैं प्रकाश के लिए टुकड़े टुकड़े करने के लिए उन्हें भेजने से पहले वर्टेक्स शेडर में मानक कैसे घुमा सकता हूं? एक आम दृष्टिकोण क्या है?

उत्तर

4

मॉडल-व्यू-प्रक्षेपण मैट्रिक्स के ऊपरी 3 पंक्तियों/कोल्स द्वारा आपको मानक को बदलने की आवश्यकता है। (यदि आप हालांकि कोई स्केलिंग कर रहे हैं, तो आपको इस मैट्रिक्स के व्यस्त ट्रांसपोज़ का उपयोग करने की आवश्यकता है। See this article)।

mat3 normalMatrix = mat3(mvp); 
normalMatrix = inverse(normalMatrix); 
normalMatrix = transpose(normalMatrix); 
f_normal = normalize(normal * normalMatrix); 
// You should also send your tranformed position to the fragment shader 
f_position = vec3(mvp * vec4(position, 1.0)); 

अपने टुकड़े टुकड़े में, आपको अपने प्रकाश स्रोत से दूरी को अपने टुकड़े और सामान्यीकृत करने की दूरी की गणना करने की आवश्यकता है। सामान्य और प्रकाश वेक्टर के डॉट उत्पाद को ढूंढें और हल्के रंग से इसे गुणा करें।

vec3 light = normalize(sun - f_position); 
light = max(dot(f_normal, light), 0.0) * vec3(1.0, 1.0, 1.0); 
gl_FragColor = texture(tex, f_texcoord) * vec4(light, 1.0); 

मेरे कोड में अनुकूलन के लिए निश्चित रूप से कमरा है।

मैं इस पुस्तक को OpenGL 4.0 Shading Language Cookbook की अनुशंसा करता हूं।

+0

धन्यवाद। क्या आप मुझे एक अलग सामान्य मैट्रिक्स (केवल मॉडल रोटेशन सहित न तो स्केलिंग और न ही परिवर्तन) भेजने के लिए सलाह देंगे? मैंने उस अभ्यास को कहीं और देखा कि क्या वह शेडर में मॉडल मैट्रिक्स से घूर्णन को फिर से निकालने से बेहतर है। – danijar

+0

इसके बारे में क्षमा करें, पिछली टिप्पणी संपादित करते समय मेरा समय समाप्त हो गया ... मुझे लगता है कि स्केलिंग आवश्यक है, क्योंकि यह प्रकाश स्रोत को सतह की दूरी बदल सकती है। और चूंकि आपको स्केल की आवश्यकता है, आपको ऊपरी 3 एक्स 3 मैट्रिक्स के व्यस्त ट्रांसपोज़ का उपयोग करके स्केल के लिए सही करने की आवश्यकता है। मैं अपने सामान्य मैट्रिक्स को शेडर को एक वर्दी के रूप में भेजता हूं, ताकि यह केवल प्रति चरम के बजाय एक बार गणना की जा सके।ऐसा करने के लिए आपको गणित पुस्तकालय की आवश्यकता हो सकती है, क्योंकि आपका प्लेटफ़ॉर्म इन मैट्रिक्स गणनाओं को निष्पादित करने के लिए फ़ंक्शंस प्रदान नहीं कर सकता है। – bwroga

+0

यह समझ में आता है। जिस तरह से मैं जीएलएम का उपयोग करता हूं। – danijar

0

निम्नलिखित समाधान मेरे मॉडल के साथ काम करता है, लेकिन मुझे इसके पीछे गणित की बहुत गहरी समझ नहीं है। यह मेरा स्रोत है: Adding Depth and Realism - Surface Normals

को बदलने आप अपने सामान्य वैक्टर करने के लिए आवेदन करने की आवश्यकता से दर्शाया जाता है: एन '= एन * (एम -1) टी

मूल रूप से, इसका मतलब है कि आप अपने मॉडल व्यू मैट्रिक्स (एम) के व्यस्त-हस्तांतरण से अपने मानदंडों (एन) को गुणा करें। यदि आपका एम मैट्रिक्स 4x4 है, तो आपको सामान्य गुणा के लिए परिणामस्वरूप 3x3 ऊपरी-बाएं चतुर्भुज (एम -1) टी का उपयोग करना चाहिए।

फिर से, यह मेरे लिए काम करता है लेकिन मैं गणित को बहुत अच्छी तरह से समझा नहीं सकता।

+0

धन्यवाद, मुझे मिल गया। – danijar