faceforward()
函数用于判断向量朝向,它可以通过比较入射向量与几何法线的方向,是否一致确定向量朝向。
bvec2 faceforward(bvec2 N, bvec2 I, bvec2 Nref);
bvec3 faceforward(bvec3 N, bvec3 I, bvec3 Nref);
bvec4 faceforward(bvec4 N, bvec4 I, bvec4 Nref);
N
:几何法线向量,即法向量。
I
:入射向量。
Nref
:法线参考向量。可以理解为“参照物”,通常为表面法线向量。
返回一个Boolean类型的向量。
返回值为一个具有两个或三个分量的 Boolean 向量。
示例1
vec3 normal = normalize(normalMatrix * a_normal);
vec3 lightDir = normalize(light.position - v_position);
if (dot(normal, lightDir) < 0.0) {
normal = -normal;
}
vec3 diffuse = max(dot(normal, lightDir), 0.0) * u_material.diffuse.rgb;
在这个示例中,我们使用 dot()
函数来计算法线向量和光源方向向量之间的夹角。如果这个夹角小于 0,就意味着光线从物体的背面照射到表面上。我们可以使用 faceforward()
函数来修正这个问题。
示例代码:
vec3 normal = normalize(normalMatrix * a_normal);
vec3 lightDir = normalize(light.position - v_position);
normal = faceforward(normal, -lightDir, normal);
vec3 diffuse = max(dot(normal, lightDir), 0.0) * u_material.diffuse.rgb;
在这个示例中,我们使用了 faceforward()
函数来判断入射方向,如果被照射物体的法向量与光线方向相反,则法向量取反。
示例2
vec3 norm = normalize(N);
vec3 toLight = normalize(u_lightPos - v_worldPos);
vec3 toEye = normalize(u_eyePos - v_worldPos);
vec3 reflection = reflect(-toLight, norm);
// 计算菲涅耳反射
float fresnel = pow(clamp(1.0 - dot(toEye, reflection), 0.0, 1.0), 5.0);
vec4 fragColor = mix(texture(tex, v_texcoord), vec4(u_color, 1.0), fresnel);
在这个示例中,我们使用了 reflect()
函数来计算反射向量。但是,在某些情况下,反射向量的方向可能与表面法向量相反,我们可以使用 faceforward()
函数来解决这个问题。
示例代码:
vec3 norm = normalize(N);
vec3 toLight = normalize(u_lightPos - v_worldPos);
vec3 toEye = normalize(u_eyePos - v_worldPos);
vec3 reflection = reflect(-toLight, norm);
reflection = faceforward(reflection, -toEye, norm);
// 计算菲涅耳反射
float fresnel = pow(clamp(1.0 - dot(toEye, reflection), 0.0, 1.0), 5.0);
vec4 fragColor = mix(texture(tex, v_texcoord), vec4(u_color, 1.0), fresnel);
在这个示例中,我们使用了 faceforward()
函数来保证反射向量的方向与表面法向量一致。