准备
要真正了解一个engine,肯定需要掌握webgl,万丈高楼平地起,无论engine的功能多么丰富,在浏览器中底层接口必定使用的是canvas,而webgl则是这一切的源头。
你可能听说过矩阵,不过从0编写一个webgl程序,我们暂时还用不到这么高深的知识,不要被矩阵所吓倒,让我们先从最基本的开始吧。
第一个webgl程序
我们先看下本节教程的目标效果:在渲染区域的中心绘制了一个红色的点
看起来并不是太复杂,其实实现的代码也就30行:
- html
<canvas id="canvas"></canvas>
- js
const canvas = document.getElementById("canvas");
const gl = canvas.getContext("webgl");
// 背景色
gl.clearColor(0, 1, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// 创建顶点着色器
const vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, `void main()
{
gl_Position = vec4(0.0,0.0,0.0, 1.0);
gl_PointSize = 10.0;
}`);
gl.compileShader(vs);
// 创建片段着色器
const fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, `void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}`);
gl.compileShader(fs);
// 链接shader
const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
// 使用shader
gl.useProgram(program);
// 绘制图形
gl.drawArrays(gl.POINTS, 0, 1);
为了方便查看效果,我将这段代码放在了CodePen,你可以直接打开这个链接直接运行。
代码中使用到的gl aip也不是非常多,需要你自己耐心一个一个看一下api的用法,尽可能的熟悉这些,对后续阅读cocos creator源码阅读非常有帮助,因为cocos creator本质上就是基于webgl开发的一个framework,我们现在用到的gl api,cocos creator也在用。
代码分析
- 获取gl上下文
- 创建、编译着色器,主要是顶点着色器和片段着色器
- 创建program,附加着色器,并链接使用program
- 绘制DrawCall
这里面有几个概念:
- shader:GLSL语言编写的一段运行在GPU上的代码,游戏中各种炫酷的效果,都需要编写对应效果的shader
- program:一般都是由2个shader组成,program更像是一对shader组合,当后续渲染时,我们只需要切换program,就能在不同的shader组合之间切换,以此来绘制更加复杂的效果。
- draw:webgl提供了非常多的draw函数,教程中用到的只是其中的一个,我们经常听到术语dc,其实就是draw call的意思,说的再直白一点,就是调用一个draw函数。
draw call为100,意思就是调用了draw函数100次。
短短的28行代码,我并没有加入一些校验容错逻辑的代码,并且已经将代码精简到极致了,目的就是排除学习干扰,一针见血的看到核心逻辑。
webgl状态机
状态机是webgl里面非常重要的一个概念,它是webgl渲染的基本原理,对于理解webgl十分重要。
通俗点说,可以认为一个画家站在画板前作画,我们可以告诉这个画家此刻你应该使用什么画笔,画什么形状,当画家绘制完毕后,如果我们不更新这个状态,画家会一直维持这些状态,直到我们再次设置新的绘画状态。