🗳️ [WebGL编程指南] 3. 绘制和变换三角形
不管三维模型的型状多么负责,其组成的基本单位都是三角形。通过创建更细小和更大量的三角形,就可以创建更复杂和更逼真的三维模型。
绘制多个点
上文响应鼠标点击事件的实现中,points 储存鼠标的位置,每次遍历向着色器传入一个点,调用drawArrays 方法将这个点绘制出来。但这个方法只能绘制一个点,对于多个顶点的图形,需要一次性地将顶点传入着色器。
javascriptCopy
for(let i = 0; i < points.length; i+=2 ) {
// 传递变量
gl.vertexAttrib3f(a_Position, points[i], points[i+1], 0.0);
// 绘制
gl.drawArrays(gl.POINTS, 0, 1);
}WebGL提供了缓冲区对象,支持一次性向着色器传入多个顶点。
javascriptCopy
// 入口函数
function drawPoint() {
// ...
const n = 3;
// 创建三个顶点
const vertices = new Float32Array([
0.0, 0.5,
-0.5, -0.5,
0.5, -0.5
])
const vertextBuffer = gl.createBuffer();
// 将缓冲区对象绑定到目标
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
// 向缓冲区写入数据
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
// 获取 a_Position 储存位置
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
// ...
// 缓冲区对象分配给 a_Position
gl.vertexArribPointer(a_Position, 2, gl.FLOAT, false, 0, 0)
// 连接a_Position与缓冲区对象
gl.enableVertextAttribArray(a_Position)
// 绘制三个点
gl.drawArray(gl.POINTS, 0, n)
}
类型化数组
为了绘制三维图形,WebGL通常要处理大量类型相同的数据,如顶点坐标和颜色。为了优化性能,引入了特殊的数组。浏览器事先知道数据类型,处理起来更有效率

绘制三角形
javascriptCopy
// 入口函数
function drawPoint() {
// 顶点着色器
const VSHADER_SOURCE =
'attribute vec4 a_Position;\n' + // 使用attribute 变量
'void main() {\n' +
' gl_Position = a_Position;\n' + // 去掉了顶点大小
'}\n';
// ...
const n = 3;
// 创建三个顶点
const vertices = new Float32Array([
0.0, 0.5,
-0.5, -0.5,
0.5, -0.5
])
const vertextBuffer = gl.createBuffer();
// 将缓冲区对象绑定到目标
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
// 向缓冲区写入数据
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
// 获取 a_Position 储存位置
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
// ...
// 缓冲区对象分配给 a_Position
gl.vertexArribPointer(a_Position, 2, gl.FLOAT, false, 0, 0)
// 连接a_Position与缓冲区对象
gl.enableVertextAttribArray(a_Position)
// 绘制三个点
gl.drawArray(gl.TRIANGLES, 0, n)
}


绘制矩形
javascriptCopy
// 入口函数
function drawPoint() {
const n = 4;
// 创建四个顶点
const vertices = new Float32Array([
-0.5, 0.5,
-0.5, -0.5,
0.5, 0.5,
0.5, -0.5,
])
// ...
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n)
}平移、旋转、缩放
平移旋转缩放,被称为变换(trasnformations)或者仿射变换(affine transformations)

给顶点着色器每个分量,都平移TX,TY,TZ,可以实现平移。
javascriptCopy
// 入口函数
function drawPoint() {
// 顶点着色器
const VSHADER_SOURCE =
'attribute vec4 a_Position;\n' + // 使用attribute 变量
'uniform vec4 u_Translation;\n' + // 平移分量
'void main() {\n' +
' gl_Position = a_Position + u_Translation;\n' + // 平移分量
'}\n';
// ...
}





javascriptCopy
// 入口函数
function drawPoint() {
// 顶点着色器
const VSHADER_SOURCE =
'attribute vec4 a_Position;\n' + // 使用attribute 变量
'uniform vec4 u_xformMatrix;\n' + // 变换矩阵
'void main() {\n' +
' gl_Position = a_Position * u_xformMatrix;\n' +
'}\n';
// ...
const ANGLE = 90.0
const radian = Math.PI * ANGLE / 180 // 角度转弧度
const cosB = Math.cos(radian)
const sinB = Math.sin(radian)
const xformMatrix = new Float32Array([
cosB, sinB, 0.0, 0.0,
-sinB, cosB, 0,0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
])
const u_xformMatrix = gl.getUniformLocation(gl.program, 'u_xformMatrix')
gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix)
// ...
}
javascriptCopy
// 入口函数
function drawPoint() {
// 顶点着色器
const VSHADER_SOURCE =
'attribute vec4 a_Position;\n' + // 使用attribute 变量
'uniform vec4 u_xformMatrix;\n' + // 变换矩阵
'void main() {\n' +
' gl_Position = a_Position * u_xformMatrix;\n' +
'}\n';
// ...
const Tx = 0.5
const Ty = 0.5
const Tz = 0.0
const xformMatrix = new Float32Array([
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0,0, 0.0,
0.0, 0.0, 1.0, 0.0,
Tx, Ty, Tz, 1.0
])
const u_xformMatrix = gl.getUniformLocation(gl.program, 'u_xformMatrix')
gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix)
// ...
}

javascriptCopy
// 入口函数
function drawPoint() {
// 顶点着色器
const VSHADER_SOURCE =
'attribute vec4 a_Position;\n' + // 使用attribute 变量
'uniform vec4 u_xformMatrix;\n' + // 变换矩阵
'void main() {\n' +
' gl_Position = a_Position * u_xformMatrix;\n' +
'}\n';
// ...
const Sx = 0.5
const Sy = 0.5
const Sz = 0.0
const xformMatrix = new Float32Array([
Sx, 0.0, 0.0, 0.0,
0.0, Sy, 0,0, 0.0,
0.0, 0.0, Sz, 0.0,
0.0, 0.0, 0.0, 1.0
])
const u_xformMatrix = gl.getUniformLocation(gl.program, 'u_xformMatrix')
gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix)
// ...
}
比如上图在Float32数组里面的顺序应该是[a, e, i, m, b, f, j ,n ….]
