你如何计算glsl中两个法线之间的角度?我试图将菲涅尔效果添加到对象的外边缘(将该效果与phong着色相结合),我认为角度是我唯一缺少的.
片段着色器:
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; }
顶点着色器:
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
两个向量之间的点积将返回角度的余弦(在GLSL中它是点(a,b)).取弧度的余弦将以弧度返回角度(在GLSL中它是acos(x)).
Dot产品非常便宜,电弧余弦相当昂贵.
但是,菲涅耳效应并不需要角度.只需在矢量之间得到点结果即可.菲涅耳效应有很多近似值,其中最便宜的就是直接使用点.或者将其平方(x*x),或者提升到其他力量.
在上面的着色器中,看起来你只想将点数提升到5倍.就像是:
float oneMinusDot = 1.0 - dot(L, N); float F = pow(oneMinusDot, 5.0);
从两个向量的点积可以得到它们之间角度的余弦
cos A = DotProduct(v1, v2) / (Length(v1) * Length(v2))
使用这个,你不需要在计算F时计算余弦.因为你的向量是单位向量,例如,长度为1,你甚至可以避免除法.