目录
- 1 前言
- 2 缓冲区介绍
- 3 声明顶点的位置和颜色
- 4 回忆Shader的初始化
- 5 开始缓冲区的逻辑
- 5.1 声明顶点坐标
- 5.2 创建并绑定缓冲区
- 5.3 获取顶点着色器中的变量
- 5.4 使变量从缓冲区取值
- 5.5 绘制
- 5.6 完整代码
- 6 总结
1 前言
上一篇中我们介绍了WebGL
的环境搭建及Shader
的初始化,并绘制了一个点,这一篇我们来绘制一个三角形,并介绍缓冲区的使用方法。
2 缓冲区介绍
缓冲区就是一块存储数据的区域,为了方便我们一次性把所需的数据都传给WebGL
,而不是每次都去传。这次我们的流程和上一篇的操作流程基本是一致的,唯一不同的在于绘制时使用缓冲区的数据绘制三角形,我们还是将整个流程梳理一下:
- 创建着色器对象
- 获取着色器对象的源代码
- 绑定着色器的源
- 编译着色器
- 创建并关联项目
- 创建并绑定缓冲区
- 读取缓冲区数据并绘制三角形
最后就我们要的三角形是这样的,颜色是红色:
3 声明顶点的位置和颜色
这一块的代码并没有什么特别之处,只是去掉了声明点的那一句代码gl_PointSize = 10.0;
,因为这次我们不再需要绘制点了,其他的保持原样。
<script id="vertex-shader" type="x-shader/x-vertex">//声明一个点,vec2表示2维向量attribute vec2 aPos;void main(){//点的位置,将vec2补齐为vec4gl_Position = vec4(aPos,0.0,1.0);}</script><script id="fragment-shader" type="x-shader/x-fragment">precision highp float;void main(){//点的颜色,rgba形式,红色gl_FragColor = vec4(1.0,0.0,0.0,1.0);}</script>
4 回忆Shader的初始化
这一块的代码我们在上一篇已经介绍过了,这里不再细说,全部一次性给出,由于我们之后的每一篇博文都有这个操作,因此,这块的代码可以封装为一个函数重复调用,之后的博文也将不再列出。
const canvas = document.getElementById("canvas");const gl = canvas.getContext("webgl");//创建着色器对象let vertexShader = gl.createShader(gl.VERTEX_SHADER);let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);//获取着色器对象的源let vertexSource = document.getElementById("vertex-shader").innerText;let fragmentSource = document.getElementById("fragment-shader").innerText;//绑定着色器的源gl.shaderSource(vertexShader,vertexSource);gl.shaderSource(fragmentShader,fragmentSource);//编译着色器gl.compileShader(vertexShader);gl.compileShader(fragmentShader);console.log(gl.getShaderInfoLog(vertexShader));//创建并关联项目let program = gl.createProgram();gl.attachShader(program,vertexShader);gl.attachShader(program,fragmentShader);gl.linkProgram(program);gl.useProgram(program);
5 开始缓冲区的逻辑
5.1 声明顶点坐标
const vertices = new Float32Array([-0.5,0.0,0.0,1.0,0.5,0.0,
]);
5.2 创建并绑定缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
5.3 获取顶点着色器中的变量
let aPos = gl.getAttribLocation(program,"aPos");
5.4 使变量从缓冲区取值
//指定aPos如何读取缓冲区 两个值表示一个坐标,float类型,不使用归一化,2个值所占的字节长度,从偏移0倍字节开始读取
gl.vertexAttribPointer(aPos,2,gl.FLOAT,false,2*Float32Array.BYTES_PER_ELEMENT,0);
//允许aPos变量从缓冲区取值
gl.enableVertexAttribArray(aPos);
什么是归一化?
举个例子,假设我们的数据范围是从0-10,变为0-1的过程,就叫归一化。那怎么变为0-1呢?很简单,将每个值都除以10就可以了。这里我们不使用归一化,意味着不允许WebGL修改我们的数据。
5.5 绘制
//绘制三角形,从零好索引开始,绘制三个点
gl.drawArrays(gl.TRIANGLES,0,3);
大功告成,看一下效果:
5.6 完整代码
//声明顶点坐标
const vertices = new Float32Array([-0.5,0.0,0.0,1.0,0.5,0.0,
]);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
let aPos = gl.getAttribLocation(program,"aPos");let length = Float32Array.BYTES_PER_ELEMENT;//数组中单个元素的字节长度
//指定aPos如何读取缓冲区 两个值表示一个坐标,float类型,不使用归一化,2个值所占的字节长度,从偏移0倍字节开始读取
gl.vertexAttribPointer(aPos,2,gl.FLOAT,false,2*length,0);
gl.enableVertexAttribArray(aPos);
//绘制三角形,从零号索引开始,绘制三个点
gl.drawArrays(gl.TRIANGLES,0,3);
6 总结
本篇中,我们首先回忆了Shader
的初始化过程,然后介绍了如何使用缓冲区进行三角形的绘制,并详细介绍了如何从缓冲区进行取值,及各个参数的含义,下一篇我们讲如何将三角形变为彩色的,回见~