WebGL 绘制点流程
- 初始化webgl
- 初始化着色器shader
- 处理数据,将数据带入着色器
- 绘制
初始化webgl
let webgl;
const glDiv = document.getElementById("webgl");
// 获取webgl上下文
webgl = glDiv.getContext("webgl");
// 定义webgl可视域范围
webgl.viewport(0, 0, glDiv.clientWidth, glDiv.clientHeight);
初始化shader
// 顶点着色器代码 attribute接收位置参数 uniform接收映射矩阵
const vertexString = `
attribute vec4 a_position;
void main(void){
gl_Position = a_position;
gl_PointSize = 60.0;
}
`;
// 片元着色器代码
const fragmentString = `
void main(void){
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
}
`;
// 创建顶点着色器 片元着色器
const vsShader = webgl.createShader(webgl.VERTEX_SHADER);
const fsShader = webgl.createShader(webgl.FRAGMENT_SHADER);
// 设置着色器代码源
webgl.shaderSource(vsShader, vertexString);
webgl.shaderSource(fsShader, fragmentString);
// 编译着色器代码
webgl.compileShader(vsShader);
webgl.compileShader(fsShader);
// 创建webgl容器 (项目)
const program = webgl.createProgram();
// 绑定项目和着色器
webgl.attachShader(program, vsShader);
webgl.attachShader(program, fsShader);
// 链接webgl和项目
webgl.linkProgram(program);
// 使用项目
webgl.useProgram(program);
// 储存项目 方便后面使用
webgl.program = program;
着色器变量赋值(传参,数据处理)
// 定义浮点 坐标数组
const pointPosition = new Float32Array([0.5, 0.5, 0.0, 1.0]);
// 获取a_position变量 attribute
const aPosition = webgl.getAttribLocation(webgl.program, "a_position");
// a_position变量赋值
webgl.vertexAttrib4fv(aPosition, pointPosition);
绘制点
// 重置背景颜色
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
// 清除颜色缓冲区
webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
// 绘制 类型,数组起始位置,绘制个数
webgl.drawArrays(webgl.POINTS, 0, 1);
扩展1:绑定鼠标事件动态绘制
webgl初始化和着色器初始化保持不变,数据缓冲区代码发生改变
// 绘制点坐标数组
const points = [];
// 获取a_position变量 attribute
const aPosition = webgl.getAttribLocation(webgl.program, "a_position");
const glDiv = document.getElementById("webgl");
glDiv.addEventListener("click", e => {
const x = e.offsetX; // 距离画布横向距离
const y = e.offsetY; // 距离画布纵向距离
const x_size = e.target.clientWidth / 2; // gl坐标系x轴长度
const y_size = e.target.clientHeight / 2; // gl坐标系y轴长度
const gl_x = (x - x_size) / x_size;
const gl_y = (y_size - y) / y_size;
points.push(gl_x); // x轴坐标
points.push(gl_y); // y轴坐标
points.push(0); // z轴坐标
points.push(1); // 齐次坐标
// 定义浮点数组
const pointPosition = new Float32Array(points);
// 创建缓冲区对象
const pointBuffer = webgl.createBuffer();
// 将缓冲区绑定到webgl.ARRAY_BUFFER目标上 webgl.ARRAY_BUFFER表示缓冲区对象中包含了顶点的数据
webgl.bindBuffer(webgl.ARRAY_BUFFER, pointBuffer);
// 向缓冲区写入数据(不能直接向缓冲区写入数据,只能向“目标”写入数据,所以第一个参数是webgl.ARRAY_BUFFER,所以如果要向缓冲区写入数据 必须先绑定目标
// 第三个参数标识如何使用数据
// 1.gl.STATIC_DRAW 只写入一次数据,但需要绘制很多次
// 2.gl.STREAM_DRAW 只写入一次数据,然后绘制若干次
// 3.gl.DYNAMTC_DRAW 会写入多次数据,并绘制很多次
webgl.bufferData(
webgl.ARRAY_BUFFER, // buffer类型
pointPosition, // 数据
webgl.STATIC_DRAW // 静态数据
);
// 将缓冲区对象分配给aPosition
webgl.vertexAttribPointer(
aPosition, // 变量名
4, // 一个点需要4个数据
webgl.FLOAT, // 浮点类型
false, // 是否转置
4 * 4, // 一个点需要4个数据 * 4个字节
0 * 4 // 从第几个偏移算起 0 * 4个字节
);
// 链接aPosition变量与分配给他的缓冲区对象 (开启,使得这次分配真正有效)
webgl.enableVertexAttribArray(aPosition);
// 重置颜色
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
// 清除颜色缓冲区
webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
// 绘制 类型,数组起始位置,绘制个数
webgl.drawArrays(webgl.POINTS, 0, points.length / 4);
});