三个矩阵,三次换坐标系
顶点在模型文件里的坐标是局部坐标。要画到屏幕上,要连乘三个 4×4 矩阵:
glsl
gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0);- Model(模型矩阵):局部 → 世界。物体的缩放、旋转、位置。
- View(视图矩阵):世界 → 相机。它是“相机摆放”的逆:相机往右移,等价于整个世界往左移。
lookAt(eye, target, up)用三次叉乘构造出相机的正交基。 - Projection(投影矩阵):相机 → 裁剪空间。透视投影把视锥体压成一个立方体,并把深度放进 w,GPU 随后做“透视除法” x/w、y/w,于是远处的东西变小。
列主序与乘法顺序
GLSL 的矩阵是列主序:数组里先存第一列,平移量位于第 12、13、14 个元素。矩阵乘法不满足交换律,M = 公转 × 平移 × 自转 × 缩放 读起来要从右往左:先缩放,再自转,再推出去,最后绕原点公转。本例的小立方体“月亮”就是这样组合的,换个顺序试试,结果完全不同。
深度测试
不开深度测试时,后画的三角形总是盖住先画的,不管谁离相机更近。gl.enable(gl.DEPTH_TEST) 让 GPU 为每个像素记录深度,只保留最近的片元。每帧记得 gl.clear(... | gl.DEPTH_BUFFER_BIT)。
背面剔除
封闭物体的背面永远看不见,gl.enable(gl.CULL_FACE) 直接丢掉它们,省下一半片元。判断正反面靠顶点顺序:从外面看是逆时针(CCW)的三角形为正面。关掉剔除和深度测试,片元着色器里用 gl_FrontFacing 把背面涂成品红色,你会看到它们“透”出来。
glsl
if (!gl_FrontFacing) c = vec3(0.9, 0.1, 0.35) * 0.6;法线也要变换
光照需要世界空间的法线。只有旋转和统一缩放时,可以直接用 mat3(uModel);有非均匀缩放时要用法线矩阵(模型矩阵逆的转置)。
核心 API
uniformMatrix4fvperspectivelookAtgl.enable(gl.DEPTH_TEST)gl.enable(gl.CULL_FACE)gl.DEPTH_BUFFER_BITgl_FrontFacing动手试试
- 1关掉 DEPTH_TEST,保持 CULL_FACE,看小立方体何时“穿”到大立方体前面。
- 2把月亮矩阵里的平移和公转对调顺序,观察运动变化。
- 3把 fov 拉到 110 并缩短相机距离,感受强烈的透视畸变。
还没有输出。console.log 的内容会显示在这里。
运行中