携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第24天,点击查看活动详情
目的
通过 webgl 实现一个三角形,掌握实现webgl程序的最简流程,先熟练这一段,再学习后面的内容
分析
先分析如果绘制一个三角形,我们需要做什么
- 创建canvas元素
- 获取canvas元素,创建webgl上下文
- 创建着色器的 shader 实例,获取内容,并注册顶点着色器/片段着色器
- 创建 Program 实例、加载 shader 内容
- 获取顶点着色器的变量的地址,创建buffer并且赋值
- 绘制
创建上下文
我们直接先实现 1 和 2;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Demo</title>
</head>
<body>
<canvas id="webgl"></canvas>
</body>
</html>
<script>
// 创建上下文
function createWebglContext(id, opts) {
const webglCanvas = document.querySelector(id);
webglCanvas.width = opts.width;
webglCanvas.height = opts.height;
const context = webglCanvas.getContext("webgl");
return context;
}
const context = createWebglContext("#webgl",{width:800,height:400});
</script>
创建着色器的 shader 实例,获取内容,并注册顶点着色器/片段着色器
利用 createShader 创建 shader 实例,将着色器代码通过 shaderSource 传入,再进行编译
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
const isSuccess = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (isSuccess) {
return shader;
}
gl.deleteShader(shader);
}
可能会存在编译错误,所以用 getShaderParameter 判断一下是否成功,否则的话销毁掉 shader
到时候就是这样使用
const vertexShaderSource = document.querySelector("#vertex").text;
const fragmentShaderSource = document.querySelector("#fragment").text;
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(
gl,
gl.FRAGMENT_SHADER,
fragmentShaderSource
);
我们再补充一下 我们想要做的着色器代码
<script id="vertex" type="notjs">
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}
</script>
<script id="fragment" type="notjs">
precision mediump float;
void main() {
gl_FragColor = vec4(1, 0, 0.5, 1);
}
</script>
创建 Program 实例、加载 shader 内容
我们写一个创建 Program 的函数,加载顶点、片段着色器,然后连接进上下文
function createProgram(gl, vertexShader, fragmentShader) {
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
var isSuccess = gl.getProgramParameter(program, gl.LINK_STATUS);
if (isSuccess) {
return program;
}
gl.deleteProgram(program);
}
获取顶点着色器的变量的地址,创建 buffer 并且赋值
const positionAttributeLocation = gl.getAttribLocation(program,"a_position");
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
const positions = [0, 0, 0, 0.5, 0.7, 0];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(
positionAttributeLocation,
2,
gl.FLOAT,
false,
0,
0
);
绘制
调用 drawArrays 使用gl.TRIANGLES绘制,顶点着色器每运行三次WebGL将会根据三个gl_Position
值绘制一个三角形
gl.drawArrays(gl.TRIANGLES, 0, 3);