相关库的地址:WebGLBook/lib at master
效果预览见最后。
注意:这只是个人的理解,不保证正确。如有错误欢迎指正!
首先准备具有一个画布(canvas)的页面,所有的 WebGL 程序都会通过这个 canvas 展现出来:
Hello Canvas
然后就是 app.js,即实现描点的相关代码。通过 DOM 操作,可以很容易地获得 canvas 的 DOM 节点,进而获得 WebGL 的上下文:
var canvas = document.getElementById('webgl'); var gl = getWebGLContext(canvas); if (!gl) { console.log('Error on getting context of WebGL'); return; }
初始化完毕后,分别准备顶点着色器和片元着色器的GLSL ES代码。值得注意的是,JavaScript 是一个弱类型的语言,但 GLSL ES 不是,所以不能手滑将 0.0 写成 0,否则会出现类型错误。
在每一行 GLSL ES 代码后添加换行符 ‘\n’ 后可以在发生错误时输出行号,降低调试难度。当然,不写也是完全可以的。
var VSHADER_SOURCE = 'void main() {' + ' gl_Position = vec4(0.0, 0.0, 0.0, 1.0);' + ' gl_PointSize = 10.0;' + '}'; var FSHADER_SOURCE = 'void main() {' + ' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);' + '}';
继续初始化 shader:
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) { console.log('Error on initialize shaders.'); return; }
设置画布默认空颜色,并清空画布:
gl.clearColor(0, 0, 0, 1); gl.clear(gl.COLOR_BUFFER_BIT);
然后,描点:
gl.drawArrays(gl.POINT, 0, 1);
简单说说我的理解吧。这些代码里获得 GL 上下文没啥好说的,主要的问题就在着色器(Shader)。此处一共出现了两个着色器:顶点着色器、片元着色器。描绘一个点所必须提供的参数就是点的位置与颜色,可以认为这里的顶点着色器指明了点的位置,而片元着色器则指明了其颜色。
顶点着色器代码 VSHADER_SOURCE 中有一个 main 函数,其中存在两个变量。其中 gl_Position 是一个四维向量,由四个浮点分量组成,是一个齐次坐标。其次坐标[x, y, z, w]等价于通常理解的[x/w, y/w, z/w]。使用齐次坐标进行三维处理可以获得更高的效率(?)。此处将 w 分量置为 1.0,即可将齐次坐标直接当成三位笛卡尔坐标使用。第二个变量 gl_PointSize,指明了点的大小。
片元着色器中只存在一个变量:gl_FragColor。它也是一个四维的矢量,其意义分别为红、绿、蓝与透明度的值。与常规的表示方法不同,GL 使用[0, 1]来表示单个颜色的强度,例如[0., 0., 0., 0.]表明了完全透明黑色,而[1., 1., 1., 1.]则表明完全不透明白色。
清空画布后,我们使用了 gl.drawArrays 来描点,其本质就是执行着色器代码。三个参数的意义分别为 描绘类型,从哪个点开始描绘,以及描绘的次数。当此函数被调用时,顶点着色器将会被执行 n 次,顶点着色器代码执行完毕后立即执行片元着色器。全部完成后,就可以看到灰色屏幕中的黑色画布里,描绘了一个红色的点。
顺便这哪里是点啊 这么大明明就是个正方形了嘛好伐)
效果预览~