[WebGL] 简单的 WebGL 描点实现

相关库的地址:WebGLBook/lib at master

效果预览见最后。

注意:这只是个人的理解,不保证正确。如有错误欢迎指正!

首先准备具有一个画布(canvas)的页面,所有的 WebGL 程序都会通过这个 canvas 展现出来:



    
        
        Hello Canvas
    
    
        
            你可能是正版IE的受害者。
        
        
        
        
        
        
    

然后就是 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 次,顶点着色器代码执行完毕后立即执行片元着色器。全部完成后,就可以看到灰色屏幕中的黑色画布里,描绘了一个红色的点。

顺便这哪里是点啊 这么大明明就是个正方形了嘛好伐)

效果预览~

QQ截图20160408000243