功能:使用webgl绘制一个矩形,这里通过绘制两个三角形来实现一个矩形的绘制
步骤:
1 | 获取webgl上下文 |
2 | 获取着色器字符串 |
3 | 创建,加载,编译着色器 |
4 | 给着色器的变量赋值 |
5 | 绘制图形 |
第一步:获取webgl上下文
// 获取WebGL上下文
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl");
if (!gl) {
return;
}
// 告诉WebGL怎样把提供的gl_Position裁剪空间坐标对应到画布像素坐标(屏幕空间)
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
// 清空画布
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
第二步:创建着色器字符串
这里几个注意事项:a_position.xy 其实是获取一个vec2的向量
vec2 zeroToOne = a_position.xy / u_resolution; 这里是vec2/vec2。我理解他的结果应该如下:
假设vec2 a1(x1,y1) a2(x2,y2) a3 = a1/a2 =(x1/x2,y1/y2)
其他的理解应该不难
获取着色器字符串
var vertexShaderSource = document.getElementById("2d-vertex-shader").text;
var fragmentShaderSource = document.getElementById("2d-fragment-shader").text;
第三步:创建,加载,编译着色器
// 创建着色器方法,输入参数:渲染上下文,着色器类型,数据源
function createShader(gl, type, source) {
var shader = gl.createShader(type);// 创建着色器对象
gl.shaderSource(shader, source);// 提供数据源
gl.compileShader(shader);// 编译 -> 生成着色器
var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (success) {
return shader;
}
console.log(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
}
// 然后我们将这两个着色器 link(链接)到一个 program(着色程序)
function createProgram(gl, vertexShader, fragmentShader) {
var program = gl.createProgram();//创建着色程序
gl.attachShader(program, vertexShader);// 附加顶点着色器
gl.attachShader(program, fragmentShader);// 附加片元着色器
gl.linkProgram(program);//链接到着色程序
var success = gl.getProgramParameter(program, gl.LINK_STATUS);//判断着色程序是否创建成功
if (success) {
gl.useProgram(program);
return program;
}
console.log(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
}
创建定点着色器和片元着色器,再创建程序
var vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
var program = createProgram(gl, vertexShader, fragmentShader);
第四步:给变量赋值
// 创建存放三个2维裁剪空间点的缓存
var positionBuffer = gl.createBuffer();
// 绑定位置信息缓冲(下面的绑定点就是ARRAY_BUFFER)
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
var positions = new Float32Array([
100, 200,
200, 200,
100, 30,
100, 30,
200, 200,
200, 30,
]);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
// 从着色程序中找到a_position属性值所在的位置
var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
// 从着色程序中找到u_resolution属性值所在的位置
var resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution");
// 启用对应属性
gl.enableVertexAttribArray(positionAttributeLocation);
// 告诉属性怎么从positionBuffer中读取数据 (ARRAY_BUFFER)
var size = 2; // 每次迭代运行提取两个单位数据
var type = gl.FLOAT; // 每个单位的数据类型是32位浮点型
var normalize = false; // 不需要归一化数据
var stride = positions.BYTES_PER_ELEMENT * 2; // 0 = 移动单位数量 * 每个单位占用内存(sizeof(type))每次迭代运行运动多少内存到下一个数据开始点
var offset = 0; // 从缓冲起始位置开始读取
gl.vertexAttribPointer(
positionAttributeLocation, size, type, normalize, stride, offset);
// 设置全局变量 分辨率
gl.uniform2f(resolutionUniformLocation, gl.canvas.width, gl.canvas.height);
第五步:绘制图像
// 绘制
var primitiveType = gl.TRIANGLES;
var offset = 0;
var count = 6;
gl.drawArrays(primitiveType, offset, count);
看一下效果:
我们可以调整一下坐标,就会发现是两个三角形了。
把坐标调整一下:
var positions = new Float32Array([
100, 200,
200, 200,
100, 30,
100, 30,
200, 200,
200, 100,
]);
就会变成下面的图了: