Program
v9 里没有 Program 这个类。着色器编译与管线链接被拆成
Shader 与 RenderPipeline,日常绘制再由 Model 封装。
这一页说明它为什么消失,以及旧代码怎么迁移。
| v8 | v9 对应物 | 说明 |
|---|---|---|
Program |
RenderPipeline |
把顶点与片元着色器链接成可绘制的管线 |
Program 的 vs / fs 字符串 |
device.createShader({ stage, source }) |
着色器先编译为独立的 Shader 对象 |
Program 的 attributes |
bufferLayout |
用格式字符串声明,不依赖 WebGL 的属性位置 |
Program 的 uniforms |
绑定与 shaderInputs |
uniform 通过缓冲区绑定,适配 WebGPU |
Model(v8) |
Model(v9) |
仍是高层绘制入口,但构造签名改为 (device, props) |
为什么去掉 Program
WebGPU 的渲染管线是不可变对象:深度、混合、图元类型、附件格式都在创建时固定,
改动要新建管线。WebGL 的 program 只是一个着色器链接结果,状态在其他地方设置。
两种模型的差异太大,用一个 Program 同时抽象两边,会不断泄漏后端细节。
v9 的做法是把「着色器」与「管线」分开:着色器负责编译,管线负责把着色器、 顶点布局与固定状态组合起来。WebGL 后端的管线可以在参数变化时内部重建, 对外仍是同一套接口。
创建着色器与管线
const vs = device.createShader({
stage: 'vertex',
source: [
'#version 300 es',
'in vec3 positions;',
'void main() {',
' gl_Position = vec4(positions, 1.0);',
'}'
].join('\n')
});
const fs = device.createShader({
stage: 'fragment',
source: [
'#version 300 es',
'precision highp float;',
'out vec4 fragColor;',
'void main() {',
' fragColor = vec4(0.35, 0.80, 0.62, 1.0);',
'}'
].join('\n')
});
const pipeline = device.createRenderPipeline({
vs: vs,
fs: fs,
topology: 'triangle-list',
bufferLayout: [
{ name: 'positions', stepMode: 'vertex', format: 'float32x3' }
],
parameters: {
depthWriteEnabled: true,
depthCompare: 'less-equal'
}
});
着色器编译是异步的。生产环境可以先检查
shader.compilationStatus,或等待
shader.asyncCompilationStatus,再把管线投入绘制,
避免首帧出现空洞。
实际绘制仍建议用 Model
直接操作管线要自己管理顶点数组、绑定组与渲染通道状态,代码很快就会变得冗长。
Model 已经把这些封装好,并且在参数变化时自动重建管线。
只有需要精细控制管线状态、或实现自定义图层基类时,才需要直接接触
RenderPipeline。
const model = new Model(device, {
vs: vsSource,
fs: fsSource,
attributes: { positions: positions },
bufferLayout: [
{ name: 'positions', stepMode: 'vertex', format: 'float32x3' }
],
vertexCount: 3,
topology: 'triangle-list'
});
const pass = device.beginRenderPass({ clearColor: [0.05, 0.07, 0.1, 1] });
model.draw(pass);
pass.end();
迁移检查清单
- 把
new Program(gl, {...})改为Model或createRenderPipeline,不要继续寻找createProgram。 - 把
attributes的位置索引改为bufferLayout的格式声明。 - 把 uniform 更新从
program.setUniforms迁到绑定或shaderInputs。 - 把
program.draw迁到model.draw(renderPass), 绘制需要显式开渲染通道。
看到旧教程先看版本。v8 的 Program、Geometry 的 GPU 缓冲、
AnimationLoop 的自动设备创建,在 v9 里都不成立。
按旧代码逐行翻译,通常会在第一处就停在「is not a constructor」。
经纬志(2026)。《Program》。https://www.jingweizhi.com/lumagl/api/program.html(访问日期 2026-11-03)。