什么是 uniform
attribute 每个顶点不同,uniform 则在一次绘制调用内对所有顶点和片元都相同。它是 CPU 给 GPU 传参数的主要方式:时间、画布尺寸、鼠标位置、颜色、矩阵……
glsl
uniform float u_time; // 秒
uniform vec2 u_resolution; // 画布像素尺寸
uniform vec2 u_mouse; // 鼠标像素坐标(左下角为原点)设置 uniform 的三步
- 链接后用
gl.getUniformLocation(program, "u_time")查到位置。只查一次,把结果缓存起来。 - 绘制前先
gl.useProgram(program):uniform 属于当前程序。 - 用类型匹配的函数赋值:
uniform1f、uniform2f、uniform3fv、uniform1i、uniformMatrix4fv……类型写错不会报错,只会静默失败。
本例用 gl.getActiveUniform 遍历程序里所有活跃的 uniform,自动建好查找表。注意:着色器里声明了但没用到的 uniform 会被编译器优化掉,查到的位置是 null。
三个经典 uniform
- u_time 让一切动起来。花瓣半径是
sin(petals * angle + u_time * 2.0)的函数,每帧只改一个数字,GPU 就重新算出所有顶点。 - u_resolution 用来修正宽高比。裁剪空间永远是 -1 到 1 的正方形,把 x 乘以
高 / 宽,圆才不会被拉扁。 - u_mouse 来自
pointermove事件。DOM 的 y 轴向下,GL 的 y 轴向上,记得翻转,并乘上设备像素比。
不用缓冲区也能画
花朵的顶点完全由 gl_VertexID(当前是第几个顶点)计算出来:每 3 个顶点一个三角形,第 0 个在中心,另外两个在圆周上。WebGL2 只要求绑定一个 VAO,不需要任何 attribute。
glsl
int tri = gl_VertexID / 3, corner = gl_VertexID % 3;把鼠标移到画布上,背景的光晕会跟着你:这就是 u_mouse 在片元着色器里的作用。
核心 API
gl.getUniformLocationgl.getActiveUniformgl.uniform1fgl.uniform2fgl.uniform3fvgl.uniform1igl_VertexID动手试试
- 1把 u_petals 设为 0,花会变成什么?再试试 12。
- 2新增一个 uniform u_twist,让花瓣角度随半径扭转。
- 3删掉 p.x 乘以宽高比的那一行,然后改变窗口大小。
还没有输出。console.log 的内容会显示在这里。
运行中