所有示例代码均可在我的gitee码云上,读者可自行下载:https://gitee.com/babyogl/learnWebGL,本文示例代码在chapter-01里面,引用文件都在libs文件夹下;为了让读者不至于枯燥乏味,这一篇文章我们不讲计算和理论,相关的矩阵运算和理论留在后面,现在只是单纯的介绍WebGL一些接口和用法,从一个简单的示例开始:绘制一个带颜色的三角形。
在开始之前,需要知道着色器的相关知识,可以参考:webgl介绍里面的着色器介绍,本文的demo 用到的着色器为:
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;//将精度设置为中等精度
void main() {
gl_FragColor = vec4(1, 0, 0.5, 1);
}
</script>
其中的attribute定义了一个vec4四维变量,用于表示每个顶点的位置信息,gl_Position代表顶点的位置, a_position是着色器用于接收来自JavaScript代码的顶点位置信息的入口。gl_FragColor代表每个片元的颜色,通俗的理解是用于设置顶点颜色。其中的vec4(1, 0, 0.5, 1)代表颜色信息(r, g, b, a),及(红,蓝,绿,透明度),它们的取值都在0-1之间,可以搭配出任意你想要的颜色;
首先,创建HTML文档,并在HTML文档的<body></body>里创建一个用于画图的canvas(画布),并引用相关的js文件,和创建相关的着色器脚本:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>triangle</title>
<style>
body {
margin: 0;
overflow: hidden;
}
canvas {
border: 3px solid blue;
display: block;
}
</style>
</head>
<body>
<canvas id="triangle" width="800" height="600"></canvas>
<script type="text/javascript" src="../libs/webgl-utils.js"></script>
<script type="text/javascript" src="../libs/shader.js"></script>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;//将精度设置为中等精度
void main() {
gl_FragColor = vec4(1, 0, 0.5, 1);
}
</script>
<script type="text/javascript">
.......//用于实现主要功能的脚本代码
</script>
</body>
</html>
主要功能的实现脚本如下:
获取canvas元素:
let canvas = document.getElementById('triangle');
判断浏览器是否支持WebGL,其中,antialias表示是否开启抗锯齿, depth表明绘制缓冲区包含一个深度至少为16位的缓冲区:
let gl = canvas.getContext('webgl', {antialias: true, depth: false});
if (!gl) {
console.log("您的浏览器不支持webgl!");
}
根据id获取着色器文本,并创建、编译和链接着色器:
//获取GLSL文本
let vShaderSource = document.getElementById('vertex-shader').text;
let fShaderSource = document.getElementById('fragment-shader').text;
//创建、编译和链接着色器
let program = initShader(gl, vShaderSource, fShaderSource);
在着色器中寻找attribute变量的位置:
let positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
创建缓冲区,并绑定数据:
//创建缓冲区
let positionBuffer = gl.createBuffer();
//将它绑定到ARRAY_BUFFER(将其视为ARRAY_BUFFER = positionBuffer)
//绑定缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
//三个顶点构成一个三角形
let positions = [
-0.25, 0,
0, 0.5,
0.25, 0
];
//通过绑定点向缓冲区绑定数据
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
最后进行画图:
//使画布的像素数和显示大小匹配
webglUtils.resizeCanvasToDisplaySize(gl.canvas);
//设置视口
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
//清除canvas
gl.clearColor(0, 0, 0, 1);//设置背景颜色
gl.clear(gl.COLOR_BUFFER_BIT);
//应用着色器
gl.useProgram(program);
//建立着色器中attribute变量与缓冲区之间的连接
gl.enableVertexAttribArray(positionAttributeLocation);
const size = 2;//2维坐标:每次迭代运行提取两个单位数据
const type = gl.FLOAT;//每个单位的数据类型是32位浮点型
const normalize = false;//不需要归一化数据
const stride = 0;//每次迭代前进大小* sizeof(类型)以获得下一个位置
const offset1 = 0;//从缓冲起始位置开始读取
//从缓冲区取出数据
gl.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset1);
let primitiveType = gl.TRIANGLES;//绘制三角形
let offset2 = 0;//从第一个顶点开始
let count = 3;//画图所顶点次数
gl.drawArrays(primitiveType, offset2, count);//画图
对于WebGL的画图接口gl.drawArrays和gl.drawElements的用法,可以参考这篇文章:https://blog.csdn.net/qq_37338983/article/details/78556091。
在一开始我们加了一个<style></style>,主要是利用CSS对页面元素的一些格式进行设置,主要是对canvas和body进行设置:
<style>
body {
margin: 0;<!--外边距-->
overflow: hidden;<!--隐藏溢出页面的元素-->
}
canvas {
border: 3px solid blue;<!--边界线设置-->
display: block;<!--生成的框的类型-->
}
</style>
显示效果:
从下一节开始,将结合实例讲解矩阵的一些运算、例如平移、旋转和缩放等。