GLSL 内置函数

dot()

返回两个向量的点积。对单位向量来说,它衡量两者方向有多一致:1.0 同向,0.0 垂直,-1.0 反向。

函数签名

float dot(vec2 x, vec2 y)
float dot(vec3 x, vec3 y)
float dot(vec4 x, vec4 y)

参数

x
第一个向量。
y
第二个向量,维度与 x 相同。

返回值

一个浮点数:x.x * y.x + x.y * y.y(+ x.z * y.z ...)。

在线示例

修改右侧代码,左侧预览会实时更新。

工作原理

公式很简单:对应分量相乘再相加。

dot(vec2(1.0, 2.0), vec2(3.0, 4.0)) // 1*3 + 2*4 = 11.0

有用的是它的含义。两个向量长度都为 1 时,dot 就是它们夹角的余弦:

方向关系dot
相同1.0
相差 60 度0.5
垂直0.0
相反-1.0

这正是漫反射光照需要的东西。示例中,球面正对光源的地方 dot(normal, light) 是 1.0,越靠近受光面的边缘越接近 0,背面变成负数,再由 max 截成 0。

常见用法

  • 漫反射(Lambert)光照:max(dot(normal, lightDir), 0.0)。
  • 长度的平方:dot(v, v) 等于 length(v) * length(v),但不用开方。
  • 投影到某个方向:dot(p, dir) 是 p 沿 dir 方向走了多远,可以做任意角度的渐变。
  • 哈希函数:在 fract(sin(...)) 之前,用 dot(p, vec2(12.9898, 78.233)) 把两个坐标混成一个数。

常见错误

  • 忘了归一化。向量长度大于 1 时,结果就不再在 -1 到 1 之间,光照会过亮或过暗。
  • 光照里没有截掉负数,背光面会比环境光还暗。
  • 传入维度不同的向量。dot(vec3, vec2) 无法编译。

相关函数

用到 dot() 的教程