向量数学是计算机图形学的基石,贯穿从几何建模到最终渲染的每一个环节。以下是针对图形学领域的重点补充:
一、图形学特有的向量表示与运算
1.1 齐次坐标(Homogeneous Coordinates)
-
扩展维度:三维点/向量用四维表示,如点(x,y,z,1)(x,y,z,1),方向向量(x,y,z,0)(x,y,z,0)
-
统一变换:将平移、旋转、缩放统一为矩阵乘法
-
透视变换:方便实现投影变换,w分量用于透视除法
-
区分点与方向:w=0时为方向向量(不受平移影响),w=1时为点
1.2 颜色向量
-
RGBA表示:颜色通常表示为四维向量(r,g,b,a)(r,g,b,a)
-
颜色运算:颜色混合、光照计算使用向量运算
-
色域转换:通过矩阵乘法实现RGB到其他色彩空间的转换
二、几何处理中的向量应用
2.1 表面法线计算
cpp
// 三角形法线计算:叉积标准化
Vector3 ComputeTriangleNormal(Vector3 p0, Vector3 p1, Vector3 p2) {
Vector3 u = p1 - p0;
Vector3 v = p2 - p0;
Vector3 normal = CrossProduct(u, v);
return Normalize(normal);
}
2.2 顶点法线平均
-
光滑表面:共享顶点的面法线加权平均
-
硬边:为同一几何位置存储不同法线(顶点复制)
2.3 碰撞检测
-
分离轴定理:使用点积测试凸体相交
-
射线与三角形求交:Möller-Trumbore算法(基于向量)
-
包围体测试:AABB、OBB、球体的快速剔除
三、变换与坐标系统
3.1 变换矩阵的向量基础
text
模型变换矩阵 = 缩放 × 旋转 × 平移 View Matrix = [Right, Up, Forward, Position]^T
3.2 坐标空间转换
-
模型空间 → 世界空间 → 观察空间 → 裁剪空间 → 屏幕空间
-
法线变换:使用逆转置矩阵保持垂直性
-
切线空间:用于法线贴图,TBN矩阵(Tangent, Bitangent, Normal)
3.3 视锥体裁剪
-
平面方程:n⃗⋅p⃗+d=0n⋅p+d=0
-
点积判断:n⃗⋅p⃗+d>0n⋅p+d>0 表示在平面前方
四、光照与着色
4.1 经典光照模型
glsl
// Phong光照模型中的向量计算 vec3 L = normalize(lightPos - fragPos); // 光线方向 vec3 N = normalize(normal); // 法线 vec3 V = normalize(viewPos - fragPos); // 视线方向 vec3 R = reflect(-L, N); // 反射方向 float diff = max(dot(N, L), 0.0); // 漫反射 float spec = pow(max(dot(V, R), 0.0), shininess); // 镜面反射
4.2 BRDF(双向反射分布函数)
-
基于向量的微表面理论
-
Cook-Torrance模型:法线分布、几何遮蔽、菲涅尔项
-
各向异性BRDF:考虑切线方向
4.3 环境光遮蔽
-
法线半球积分
-
屏幕空间环境光遮蔽(SSAO):基于深度和法线缓冲区
五、纹理与UV映射
5.1 纹理坐标插值
-
重心坐标:P⃗=αA⃗+βB⃗+γC⃗P=αA+βB+γC
-
透视正确插值:需要在裁剪空间进行插值
5.2 法线贴图
-
切线空间法线:(0,0,1)(0,0,1)表示与表面法线对齐
-
世界空间转换:Nworld=TBN×NtangentNworld=TBN×Ntangent
5.3 视差映射与浮雕映射
-
高度场偏移:基于视线方向与法线的点积
-
光线步进方向:沿观察向量的切平面分量
六、几何着色与曲面细分
6.1 贝塞尔曲线/曲面
-
控制点:向量数组
-
de Casteljau算法:递归线性插值
-
法线计算:参数曲面的偏导数叉积
6.2 曲面细分
-
PN三角形:基于顶点位置和法线生成平滑曲面
-
置换贴图:沿法线方向偏移顶点:P′=P+h⋅NP′=P+h⋅N
七、屏幕空间技术
7.1 深度缓冲
-
深度值归一化:透视除法后的z值
-
深度比较:用于遮挡测试
7.2 屏幕空间反射(SSR)
-
视线向量:从相机到像素
-
反射向量计算:R=I−2(I⋅N)NR=I−2(I⋅N)N
-
射线步进:在屏幕空间追踪反射光线
7.3 屏幕空间阴影(SSS)
-
光线方向到光源
-
深度比较判断遮挡
八、物理模拟相关
8.1 刚体动力学
cpp
// 角速度更新 Vector3 torque = CrossProduct(forcePoint - centerOfMass, force); Vector3 angularAcceleration = inverseInertiaTensor * torque; angularVelocity += angularAcceleration * dt; // 旋转更新(四元数表示) Quaternion rotationDelta = Quaternion(angularVelocity * dt); orientation = Normalize(rotationDelta * orientation);
8.2 粒子系统
-
位置更新:pnew=pold+v⋅dtpnew=pold+v⋅dt
-
速度更新:vnew=vold+a⋅dtvnew=vold+a⋅dt
-
力场:重力、风力、涡旋场等
8.3 流体模拟(简化)
-
速度场:每个网格点存储速度向量
-
平流项:u⋅∇uu⋅∇u
-
压力梯度:∇p∇p
九、着色器编程优化
9.1 向量化运算
-
SIMD优化:一次操作处理多个分量
-
GLSL/HLSL内置函数:
dot(),cross(),normalize(),reflect(),refract() -
着色器中的分支优化:基于向量运算避免if语句
9.2 近似计算
-
快速标准化:rsqrt近似
-
小角度近似:sinθ≈θsinθ≈θ,cosθ≈1cosθ≈1
-
反射向量近似:避免
reflect()函数的开销
十、现代图形API中的向量
10.1 数据布局
cpp
// 顶点数据结构(内存对齐优化)
struct Vertex {
Vector3 position; // 位置
Vector3 normal; // 法线
Vector2 texcoord; // 纹理坐标
Vector3 tangent; // 切线(法线贴图用)
// 16字节对齐优化
};
10.2 计算着色器中的向量
-
GPU上的并行向量运算
-
波前(Wavefront)级别的向量操作
-
共享内存中的向量数据交换
10.3 光线追踪中的向量
cpp
// 光线结构
struct Ray {
Vector3 origin;
Vector3 direction;
float t_min, t_max;
};
// 光线-球体求交
bool IntersectSphere(Ray ray, Sphere sphere) {
Vector3 oc = ray.origin - sphere.center;
float a = Dot(ray.direction, ray.direction);
float b = 2.0 * Dot(oc, ray.direction);
float c = Dot(oc, oc) - sphere.radius * sphere.radius;
float discriminant = b*b - 4*a*c;
return discriminant >= 0;
}
十一、实用技巧与注意事项
11.1 精度问题
-
世界空间使用双精度/高精度浮点数
-
屏幕空间使用半精度浮点数
-
法线、切线等方向向量需要定期重新标准化
11.2 左手 vs 右手坐标系
-
DirectX:左手坐标系(z向前)
-
OpenGL:传统为右手坐标系(z向后)
-
法线方向、叉积顺序需保持一致
11.3 常见陷阱
-
法线变换不正确的"游泳"效果
-
透视除法过早导致的插值错误
-
没有正确处理w分量的齐次坐标
结语
在计算机图形学中,向量不仅是一种数学工具,更是表达几何、光照和物理的基本语言。从最简单的顶点位置到复杂的光线追踪算法,向量运算无处不在。掌握向量数学在图形学中的应用,意味着能够:
-
高效实现图形算法
-
深入优化着色器性能
-
正确理解渲染管线各阶段
-
灵活设计新颖的视觉效果
随着实时光线追踪和机器学习在图形学中的应用加深,向量运算的重要性将进一步增强。理解向量背后的几何直觉,往往比记住公式更为重要——它能帮助你在面对复杂图形问题时,找到最优雅高效的解决方案。

被折叠的 条评论
为什么被折叠?



