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)。
  • 参数顺序写反:入射方向在前,法线在后。

相关函数

用到 reflect() 的教程