#sec-1
Computer Graphics · Chapter 4 · 04

WebGL 中的变换:矩阵传递与着色器计算

矩阵库 · uniformMatrix4fv · 顶点着色器 · 实时重绘

CPU (gl-matrix)
→
uniformMatrix4fv
→
Vertex Shader
→
uModelView * aPos
→
GPU Realtime Mesh
#sec-2-1
Problem

医工问题:三维医学模型为何能实时交互?

拖动鼠标时,复杂医学模型实时旋转。每一帧都重新计算并上传所有顶点吗?

医学实时可视化导入
#sec-2-2
Prediction

Prediction:每帧更新什么?

A

Vertex Buffer不断重写

B

只更新变换状态

先投票,稍后用Demo观察。

#sec-3-1
Pipeline

变换数据流:顶点 + 矩阵 → 新位置

在WebGL2中,应用程序维护矩阵,通过uniform传入Shader,由Vertex Shader显式计算新顶点位置。

变换数据流
#sec-3-2
State

Buffer不变,Uniform改变

很多交互式旋转中,原始几何数据可以保持不变;每帧更新的是变换矩阵或旋转参数。

Buffer不变Uniform改变
#sec-4-1
Interactive Demo

Demo:WebGL2变换流水线显微镜

观察矩阵如何从 JavaScript 进入 GPU Uniform,并改变观察顶点的 gl_Position。

D04-04 · 教学仪器 WebGL2 + GLSL ES 3.00 交互实验

WebGL2变换流水线显微镜

透视矩阵怎样从 JavaScript (CPU) 传入 GPU Uniform,观察单顶点 \(P' = M \cdot P\) 的计算过程与 CPU/GPU 负载分工。

🔹 数据流水线监视:实时追踪 JavaScript State → gl.uniformMatrix4fv → GPU Uniform 全流程
🔹 三种架构策略对比:对比 CPU 顶点重写 / CPU 矩阵+GPU 变换 / GPU 自主矩阵构建
🔹 单顶点计算显微镜:监视所选顶点 \(v_0\) 原始坐标、矩阵 \(M\) 与输出 \(gl\_Position\) 实时解算
课堂观察任务 3 min

带着问题观察流水线数据流

  1. 每帧更新了什么?拖动旋转角或平移滑块,观察“Vertex Buffer Updated”与“uModelMatrix Updated”状态标志。
  2. 三种实现策略权衡:切换方案 A (CPU Vertex Update)、方案 B (CPU Matrix + GPU Transform) 与方案 C (GPU Matrix),观察数据吞吐与 GPU 负荷。
  3. 医工场景实时性成因:切换到“Medical Viewer”预设,解释上百万顶点的医学模型为什么能以 60 FPS 顺畅拖拽交互。
💡 核心规律:几何顶点数据保存在 GPU Buffer 中(不变),每帧只需上传 16 个浮点数的变换矩阵(极小带宽)。
#sec-4-2
Quick Check

随堂测试:哪一个随姿态变化更新?

单选

若采用“CPU计算Model Matrix并上传Uniform”的方案,模型旋转时通常每帧更新的是?

A

原始Vertex Buffer

B

uModelMatrix

C

HTML按钮文本

答案:B。

#sec-5-1
Strategies

三种实现策略:计算位置不同

同样让模型旋转,可以选择不同的CPU/GPU分工方式;没有一种在所有场景下绝对最好。

三种实现策略
#sec-5-2
Code Walkthrough

最小JavaScript:把矩阵送入GPU


const modelLoc = gl.getUniformLocation(program, "uModelMatrix");

gl.uniformMatrix4fv(
  modelLoc,
  false,
  modelMatrix
);

getUniformLocation

找到Shader中的uniform位置。

uniformMatrix4fv

把4×4矩阵数据送入GPU。

false

WebGL中矩阵转置参数必须为false。

#sec-5-3
Shader

最小Vertex Shader:真正执行M×P


#version 300 es

in vec4 aPosition;
uniform mat4 uModelMatrix;

void main() {
    gl_Position = uModelMatrix * aPosition;
}

真正改变顶点位置的是顶点着色器中的矩阵乘法。

#sec-6-1
Data Flow

uniform矩阵进入Shader的路径

从JavaScript中的矩阵,到GPU中的uniform,再到Vertex Shader中的乘法,需要一条明确的数据通道。

uniform矩阵进入Shader
#sec-6-2
AI Collaboration

AI协作:WebGL会自动应用Model Matrix吗?

AI协作任务

向AI提问:“WebGL2中定义Model Matrix以后,GPU是不是会自动把它作用到所有顶点?”

  1. 要求AI说明Model Matrix存在哪里。
  2. 要求AI指出它如何从JavaScript进入GPU。
  3. 要求AI找出Shader中真正执行 \(M imes P\) 的语句。
  4. 用本页代码核验AI回答是否混入旧式固定功能管线表述。
#sec-7-1
Connection

与动画循环连接

第三章的动画循环在这里变成:更新状态 → 构造矩阵 → 上传uniform → 重新渲染。

动画循环中的矩阵更新
#sec-7-2
Extension

拓展:欧拉角的问题

三维旋转不仅是矩阵乘法问题,还涉及旋转表示的选择。欧拉角直观,但存在顺序依赖和万向节锁问题。

欧拉角与万向节锁
#sec-7-3
Closure

第四章总闭环:从医学模型到实时显示

CT/MRI
→
Mesh
→
Vertices
→
Matrix
→
Uniform
→
Vertex Shader
→
Realtime Scene
现在你能解释:为什么复杂的三维医学模型可以被移动、旋转、定位并实时显示了吗?
#sec-7-4
Summary

本课时小结:矩阵如何真正进入GPU

本课把数学矩阵、JavaScript状态、uniform变量和Vertex Shader连接起来,解释三维医学模型为何能实时交互。

Buffer可以保持不变

复杂医学Mesh通常不需要每帧重新上传全部顶点。

Uniform传递变换状态

应用程序每帧更新Model Matrix或角度参数,把变化状态送入GPU。

Shader显式计算顶点

gl_Position = uModelMatrix * aPosition 是矩阵真正作用到顶点的位置。

State
→
Model Matrix
→
uniform
→
Vertex Shader
→
Realtime View
#sec-7-5
Exit Ticket

Exit Ticket

一句话回答

改变一个三维医学模型的姿态时,是否必须每帧重写整个Vertex Buffer?为什么?

期望回答:不一定。常见做法是保持几何Buffer不变,更新变换矩阵或参数,通过Vertex Shader计算新的顶点位置。