一、搭建canvas环境
1) 创建<canvas>标签,指定绘图范围。
2 )获取<canvas>标签。
3 )获取webgl上下文
4 )设置背景颜色
5) 清空<canvas>
为了条理清除,我们分别创建一个index.html和main.js文件;
1、index.html文件
<!-- index.html文件 -->
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>绘制四边形 </title>
</head>
<!--页面加载完成后,执行JavaScript中的main()函数-->
<body οnlοad="main()">
<!--定义<canvas>标签,通过width属性和height属性规定它是一片400×400的绘制区域-->
<canvas id="myCanvas" width="400" height="400">
<!--当浏览器不支持时,会直接忽略<canvas>标签,而直接显示下面这一行提示-->
Please use a browser that supports "canvas".
</canvas>
</body>
<!-- 加载js文件-->
<script src="main.js"></script>
</html>
2、 main.js文件
//main.js 文件
function main() {
var canvas = document.getElementById("myCanvas"); //获取<canvas>标签
//如果没找到<canvas>标签,则输出错误信息
if (!canvas) {
console.log('Failed to retrieve the <canvas> element.');
return;
}
//获取绘图上下文,“webgl”代表我们用webgl绘制图形。
var gl = canvas.getContext("webgl");
//设置背景颜色 参数是 颜色三元素R G B 和透明度A
gl.clearColor(1.0,0.0,0.0,1.0);
//清除背景颜色缓存,就显示我们设置的背景颜色
gl.clear(gl.COLOR_BUFFER_BIT);
}
3、效果图
二、绘制四边形
在index.html 中创建顶点着色器和片段着色器
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>绘制四边形 </title>
<!-- 顶点着色器 -->
<script id="shader-vs" src="vshader.js" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
void main() {
// 直接将外部传入的顶点坐标作为最终坐标
gl_Position = vec4(aVertexPosition, 1.0);
}
</script>
<!-- 片段着色器 -->
<script id="shader-fs" type="x-shader/x-fragment">
// 设定 float 的精度, 这里我们使用中等精度
precision mediump float;
void main() {
// 输出为纯白色
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
</script>
<!-- 加载js文件-->
<script src="main.js"></script>
</head>
<!--页面加载完成后,执行JavaScript中的main()函数-->
<body onload="main()">
<!--定义<canvas>标签,通过width属性和height属性规定它是一片400×400的绘制区域-->
<canvas id="myCanvas" width="800" height="600">
<!--当浏览器不支持时,会直接忽略<canvas>标签,而直接显示下面这一行提示-->
Please use a browser that supports "canvas".
</canvas>
</body>
</html>
在main.js中
1、加载shader
2、加载顶点数据缓存
3、设置webgl初始化状态
4、绘制四边形
完整代码如下:
var gl;
var canvas;
var shaderProgram;
var vertexBuffer;
var vertexIndexBuffer;
//加载shader
function setupShaders() {
// 从 DOM 上创建对应的着色器
vertexShader = loadShaderFromDOM("shader-vs");
fragmentShader = loadShaderFromDOM("shader-fs");
// 创建程序并连接着色器
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
// 连接失败的检测
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Failed to setup shaders");
}
// 使用着色器
gl.useProgram(shaderProgram);
// 创建动态属性获取着色器中 aVertexPosition 属性的位置
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
}
//读取shader字符内容
function loadShaderFromDOM(id) {
// 获取 DOM
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
}
// 获取着色器代码
var shaderSource = "";
var currentChild = shaderScript.firstChild;
while (currentChild) {
if (currentChild.nodeType == 3) { // 3 corresponds to TEXT_NODE
shaderSource += currentChild.textContent;
}
currentChild = currentChild.nextSibling;
}
// 创建着色器
var shader;
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
// 编译着色器
gl.shaderSource(shader, shaderSource);
gl.compileShader(shader);
// 判断编译是否成功
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
//初始化顶点缓存数据
function setupBuffers() {
// 定义顶点数据
var triangleVertices = [
0.5, 0.5, 0.0,
0.5, -0.5, 0.0,
-0.5, -0.5, 0.0,
-0.5, 0.5, 0.0
];
var triangleIndex = [
0,1,2,
0,2,3
]
// 创建顶点缓冲
vertexBuffer = gl.createBuffer();
// 绑定顶点缓冲
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
// 提交顶点数据
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);
vertexBuffer.itemSize = 3;
vertexBuffer.numberOfItems = 3;
//创建顶点索引
vertexIndexBuffer = gl.createBuffer();
// 绑定顶点索引
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,vertexIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(triangleIndex),gl.STATIC_DRAW);
}
//绘图
function draw() {
// 设置视口大小, 使用像素, 调整该大小不影响显示内容,只影响图像在 Canvas 上显示的位置和尺寸
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
// 清除颜色缓冲
gl.clear(gl.COLOR_BUFFER_BIT);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,vertexIndexBuffer);
// 将提交的顶点数据绑定到着色器的 aVertexPosition 属性
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
// 开启属性 aVertexPosition 的使用
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
// 绘制图像
gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,0);
}
function main() {
canvas = document.getElementById("myCanvas");
//如果没找到<canvas>标签,则输出错误信息
if (!canvas) {
console.log('Failed to retrieve the <canvas> element.');
return;
}
//获取绘图上下文,“webgl”代表我们用webgl绘制图形。
gl = canvas.getContext("webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
setupShaders();//加载并创建shader
setupBuffers();//加载图形数据
// 定义清除颜色缓冲之后的填充色为黑色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
draw();//绘图
}
效果图如下: