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)无法编译。