使用缓冲区绘制多个点
缓冲区对象是webG L系统中的一块内存区域,可以一次性地向缓冲区对象中填充大量点顶点数据,然后将这些数据保存在其中,供顶点着色器使用
-
创建顶点数据
/* 类型化数组类型 Float32Array: 32位浮点型数组 Float64Array: 64位浮点型数组 Int8Array: 8位整型数组 Uint8Array: 8位无符号整型数组 Uint8ClampedArray: 8位无符号整型固定数组 Int16Array: 16位整型数组 Uint16Array: 16位无符号整型数组 Int32Array: 32位整型数组 Uint32Array: 32位无符号整型数组 */ const points = new Float32Array([ 0.0, 0.5, -0.5, -0.5, 0.5, -0.5 ]) -
创建缓冲区对象
// 创建缓冲区对象
const buffer = gl.createBuffer()
-
绑定缓冲区对象
// 将缓冲区对象绑定到目标 // gl.ARRAY_BUFFER => 顶点缓冲区对象 // gl.ELEMENT_ARRAY_BUFFER => 索引缓冲区对象 gl.bindBuffer(gl.ARRAY_BUFFER, buffer) -
将数据写入缓冲区对象
// 向缓冲区对象中写入数据 target data type // gl.STATIC_DRAW => 只写入一次数据,但需要绘制很多次 // gl.STREAM_DRAW => 只写入一次数据,然后绘制若干次 // gl.DYNAMIC_DRAW => 多次写入数据,然后绘制很多次 gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW) -
将缓冲区对象分配给一个attribute变量
// 将缓冲区对象分配给 attribute 变量 // gl.vertexAttribPointer(location, size, type, normalized, stride, offset) // location => 指定待分配 attribute 变量的存储位置 // size => 指定缓冲区中每个顶点的分量个数,1-4 // type => 指定数据格式 // normalized => 是否将非浮点型的数据归一化到[0, 1]或[-1, 1]区间 // stride => 指定相邻两个顶点间的字节数,默认为0 // offset => 指定缓冲区对象中的偏移量(以字节为单位) gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0)实现流程
-
开启attribute变量
// 连接 a_Position 变量与分配给它的缓冲区对象 gl.enableVertexAttribArray(a_Position) // gl.disableVertexAttribArray(a_Position) // 禁用缓冲区对象
数据偏移
// 获取 attribute 变量的存储位置
const a_Position = gl.getAttribLocation(program, 'a_Position')
const a_PointSize = gl.getAttribLocation(program, 'a_PointSize')
const points = new Float32Array([
0.0, 0.5, 10.0,
-0.5, -0.5, 20.0,
0.5, -0.5, 30.0
])
// 创建缓冲区对象
const buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW)
const FSIZE = points.BYTES_PER_ELEMENT // 一个类型化数组中的元素所占的字节数
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 3, 0)
gl.enableVertexAttribArray(a_Position)
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, FSIZE * 3, FSIZE * 2)
gl.enableVertexAttribArray(a_PointSize)
多图形绘制
// gl.drawArrays(gl.LINES, 0, 3) // 奇数个顶点,会自动忽略最后一个顶点
// gl.drawArrays(gl.LINE_STRIP, 0, 3) // 绘制连续线段
// gl.drawArrays(gl.LINE_LOOP, 0, 3) // 绘制连续线段,闭合
// gl.drawArrays(gl.TRIANGLES, 0, 6) // 绘制三角形,顶点时3点倍数
// gl.drawArrays(gl.TRIANGLE_FAN, 0, 4) // 绘制飘带状三角形
//gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4) // 绘制条带状三角带
图形平移-着色器
// 顶点着色器
const VERTEX_SHADER = `
// attribute 变量 => 只传递顶点数据,默认值为 vec4(1.0, 0.0, 0.0, 1.0)
attribute vec4 a_Position;
attribute float a_PointSize;
attribute float a_translate;
void main() {
// 设置坐标 x y z w(齐次坐标) => (x/w, y/w, z/w)
gl_Position = vec4(a_Position.x + a_translate,a_Position.y,a_Position.z,1.0);
gl_PointSize = a_PointSize;
}
`
// 获取 平移变量的存储位置
const a_translate = gl.getAttribLocation(program, 'a_translate')
// 。。。 启动缓冲区
let x = -1;
setInterval(() => {
x += 0.01
if (x > 1) {
x = -1
}
gl.vertexAttrib1f(a_translate, x)
gl.clear(gl.COLOR_BUFFER_BIT)
gl.drawArrays(gl.TRIANGLES, 0, 3)
}, 100)
图形缩放-着色器
在顶点着色器中使用缩放变量乘以对应顶点坐标
// 顶点着色器
const VERTEX_SHADER = `
attribute vec4 a_Position;
attribute float a_PointSize;
attribute float a_scale;
void main() {
gl_Position = vec4(a_Position.x * a_scale ,a_Position.y,a_Position.z,1.0);
gl_PointSize = a_PointSize;
}
`
图形旋转-着色器
// 顶点着色器
const VERTEX_SHADER = `
attribute vec4 a_Position;
attribute float a_PointSize;
attribute float a_deg;
void main() {
gl_Position.x = a_Position.x * cos(a_deg) - a_Position.y * sin(a_deg);
gl_Position.y = a_Position.x * sin(a_deg) + a_Position.y * cos(a_deg);
gl_Position.z = a_Position.z;
gl_Position.w = 1.0;
gl_PointSize = a_PointSize;
}
`
图形平移-平移矩阵
矩阵:纵横排列的数据表格(m行n列)
类别:行主序,列主序
原理先挖坑,后续填上
// 顶点着色器
const VERTEX_SHADER = `
attribute vec4 a_Position;
attribute float a_PointSize;
uniform mat4 u_Translate; //声明矩阵偏移变量
void main() {
gl_Position = u_Translate * a_Position;
}
`
// 获取 平移变量的存储位置
const u_Translate = gl.getUniformLocation(program, 'u_Translate')
// 创建矩阵函数
function getTranslateMatrix (x = 0, y = 0, z = 0) { //
const matrix = 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,
x, y, z, 1.0,
])
return matrix
}
// 使用
function animation () {
x += 0.01
if (x > 1) {
x = -1
}
const matrix = getTranslateMatrix(x, x, 0)
gl.uniformMatrix4fv(u_Translate, false, matrix) // 参数:指定uniform存储位置,是否转置,在webgl中恒为false,矩阵数组
// gl.vertexAttrib1f(a_translate, x)
gl.clear(gl.COLOR_BUFFER_BIT)
gl.drawArrays(gl.TRIANGLES, 0, 3)
requestAnimationFrame(animation)
}
animation()
图形缩放-缩放矩阵
// 创建矩阵函数
function getScaleMatrix (x = 1, y = 1, z = 1) { //
const matrix = new Float32Array([
x, 0.0, 0.0, 0.0,
0.0, y, 0.0, 0.0,
0.0, 0.0, z, 0.0,
0.0, 0.0, 0.0, 1.0,
])
return matrix
}
图形旋转-旋转矩阵
// 创建绕z轴旋转的矩阵函数
function getRotateMatrix (deg) { //
const matrix = new Float32Array([
Math.cos(deg), Math.sin(deg), 0.0, 0.0,
-Math.sin(deg), Math.cos(deg), 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
])
return matrix
}
复合矩阵
// 矩阵复合函数
function getMinMatrix(A, B) {
const result = new Float32Array(16);
for (let i = 0; i < 4; i++) {
result[i] =
A[i] * B[0] + A[i + 4] * B[1] + A[i + 8] * B[2] + A[i + 12] * B[3];
result[i + 4] =
A[i] * B[4] + A[i + 4] * B[5] + A[i + 8] * B[6] + A[i + 12] * B[7];
result[i + 8] =
A[i] * B[8] + A[i + 4] * B[9] + A[i + 8] * B[10] + A[i + 12] * B[11];
result[i + 12] =
A[i] * B[12] + A[i + 4] * B[13] + A[i + 8] * B[14] + A[i + 12] * B[15];
}
return result;
}