GLSL 内置函数
reflect()
返回光线照到表面后反弹的方向:reflect(I, N) = I - 2.0 * dot(N, I) * N。
函数签名
vec2 reflect(vec2 I, vec2 N)
vec3 reflect(vec3 I, vec3 N)参数
- I
- 入射方向,指向表面。
- N
- 表面法线,必须是单位向量。
返回值
反射后的方向,长度与 I 相同。
在线示例
修改右侧代码,左侧预览会实时更新。
工作原理
把球扔向墙,它会以进来的角度弹出去。reflect(I, N) 计算的就是方向 I 照到法线为 N 的表面后的反弹方向:
vec3 r = reflect(I, N); // I - 2.0 * dot(N, I) * N
I 中垂直射入表面的那部分被翻转,沿着表面的那部分保持不变。
示例中相机直直地看向屏幕内部。对球面上的每个像素,视线方向在表面法线上反弹,再用反弹后的方向去查询一个简单的天空加地板环境。结果看起来像一个镀铬金属球。
常见用法
- 高光(Phong):
pow(max(dot(reflect(-lightDir, normal), viewDir), 0.0), shininess)。 - 环境反射:用反射方向查询天空颜色或立方体贴图。
- 粒子反弹:粒子撞墙时反射它的速度。
常见错误
- 方向传反。
I是指向表面的方向。光源方向通常是从表面指向光源,这时要写reflect(-lightDir, normal)。 - 法线没有归一化,反弹角度就会出错。一定要先
normalize(N)。 - 参数顺序写反:入射方向在前,法线在后。