2008-12-03 29 views
6

glsl में दो मानकों के बीच कोण की गणना कैसे करते हैं? मैं किसी ऑब्जेक्ट के बाहरी किनारों (फ़ोंग छायांकन के साथ उस प्रभाव को जोड़कर) में फ़्रेज़नेल प्रभाव जोड़ने की कोशिश कर रहा हूं, और मुझे लगता है कि कोण केवल एक चीज है जिसे मैं याद कर रहा हूं।glsl में दो मानकों के बीच कोण की गणना कैसे करते हैं?

टुकड़ा shader:

varying vec3 N; 
varying vec3 v; 

void main(void) { 
    v = vec3(gl_ModelViewMatrix * gl_Vertex); 
    N = normalize(gl_NormalMatrix * gl_Normal); 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
} 

शीर्ष shader:

varying vec3 N; 
varying vec3 v; 

void main(void) { 
    vec3 L = normalize(gl_LightSource[0].position.xyz - v); 
    vec3 E = normalize(-v); 
    vec3 R = normalize(-reflect(L,N)); 

    vec4 Iamb = gl_FrontLightProduct[0].ambient 
    vec4 Idiff = gl_FrontLightProduct[0].diffuse * max(dot(N,L), 0.0); 
    vec4 Ispec = gl_FrontLightProduct[0].specular * pow(max(dot(R,E),0.0), gl_FrontMaterial.shininess); 
    vec4 Itot = gl_FrontLightModelProduct.sceneColor + Iamb + Idiff + Ispec; 

    vec3 A = //calculate the angle between the lighting direction and the normal// 
    float F = 0.33 + 0.67*(1-cos(A))*(1-cos(A))*(1-cos(A))*(1-cos(A))*(1-cos(A)); 
    vec4 white = {1.0, 1.0, 1.0, 1.0}; 

    gl_FragColor = F*white + (1.0-F)*Itot; 
} 

vec3

उत्तर

5

अलग दो वैक्टर की डॉट उत्पाद से आप उन दोनों के बीच

कोण की कोज्या प्राप्त कर सकते हैं
cos A = DotProduct(v1, v2)/(Length(v1) * Length(v2)) 

इसका उपयोग करते हुए, आपको एफ की गणना करते समय कोसाइन की गणना करने की आवश्यकता नहीं है। चूंकि आपके वैक्टर यूनिट वैक्टर हैं, उदाहरण के लिए, लंबाई एक है, आप विभाजन से बच सकते हैं।

+0

glsl में अंतर्निहित डॉट उत्पाद ऑपरेटर भी है। कोड की रेखा खूबसूरती से सरल होगी: सीए = डॉट (v1, v2); इसके बाद, सभी कॉस (ए) संदर्भ सीए के साथ प्रतिस्थापित किए जा सकते हैं। –

11

दो वैक्टरों के बीच डॉट उत्पाद कोण के कोसाइन लौटाएगा (जीएलएसएल में यह डॉट (ए, बी) में)। उस के आर्क-कोसाइन लेना रेडियंस में कोण लौटाएगा (जीएलएसएल में यह एकोस (एक्स) है)।

डॉट उत्पाद बहुत सस्ता है, आर्क-कोसाइन काफी महंगा है।

हालांकि, फ़्रेज़नेल प्रभाव को वास्तव में कोण की आवश्यकता नहीं है। वैक्टर के बीच बस डॉट परिणाम पर्याप्त है। फ़्रेज़नेल प्रभाव के लिए कई अनुमान हैं, सस्ता में से एक बस सीधे डॉट का उपयोग कर रहा है। या इसे (x * x) स्क्वायर करना, या किसी अन्य शक्ति को उठाना।

उपरोक्त आपके शेडर में, ऐसा लगता है कि आप सिर्फ 5 वें शक्ति को डॉट उठाना चाहते हैं। कुछ ऐसा:

float oneMinusDot = 1.0 - dot(L, N); 
float F = pow(oneMinusDot, 5.0);