[✔️]cocos creator shader 入门教程2:webgl动起来

1,003 阅读3分钟

在上一节,我们成功使用webgl绘制了一个点,这一节我们就来实现让这个点动起来。

分析:如何让点动起来?

先复习下上节课的shader:

  • vertex shader
void main() { 
    gl_Position = vec4(0.0,0.0,0.0, 1.0); 
    gl_PointSize = 10.0; 
}
  • fragment shader
void main() { 
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 
}

运动的本质就是坐标的变化,我们想要修改坐标,其实就是要修改gl_Position,也就是说我们需要在vertex shader定义一个变量,同时程序能够控制变量的值。

修改点的位置

因为shader使用的是glsl语言,这里就需要用到attribute, attribute变量只能定义在vertex shader中,attribute更像是一个修饰符,表示这是一个可以被js代码修改的属性(为了方便理解暂且这么解释,更专业的解释你需要看glsl语言规范)。

  • vertex shader修改

    attribute vec2 a_pos;
    void main()
    {
        gl_Position = vec4(a_pos.x,a_pos.y,0.0, 1.0);
        gl_PointSize = 10.0;
    }
    

    在shader中我们定义了a_pos属性,然后将a_pos.x、a_pos.y分别传递给了gl_Position,当我们通过代码修改a_pos后,gl_Postion也会随之改变。

  • 在js代码中,我们可以这样传递数据给a_pos

    // 放到program之后,从vertex shader里面获取a_pos属性
    const a_pos = gl.getAttribLocation(program, "a_pos");
    // 设置a_pos属性值
    gl.vertexAttrib2f(a_pos, 0.9, 0.9);
    

重新运行程序观察到点的位置渲染到了右上角,通过这个表现,不难推理出,webgl的坐标是[-1, 1]

image.png

实现:让点动起来!

原理也非常简单,不停的改变a_pos属性即可:

// ...
let x = -1;
setInterval(() => {
    x += 0.1;
    if (x > 1) {
        x = -1;
    }
    gl.vertexAttrib2f(a_pos, x, 0);
    gl.drawArrays(gl.POINTS, 0, 1);
}, 100)

这样子,我们就看到了一个红点,从左往右移动,完整的代码我放到了CodePen

整体思路回顾:

  1. vertex shader增加attribute、vec2、a_pos,并且将a_pos的值赋给gl_Position
  2. 通过getAttribLocation获取a_pos
  3. 通过vertexAttrib2f设置a_pos的值,并调用draw进行渲染绘制
  4. 使用定时器,改变a_pos,进而实现点的移动效果

定时器的一个callback,我们通常称为一帧,要绘制出复杂的游戏画面,通常需要进行多次的draw函数调用,在这一帧中我们调用了几次draw函数,那么我们通常就说drawcall是多少,drawcall是性能优化的一个非常重要的指标。

当然以上的代码非常的简陋,在实际项目中我们也不会使用setInterval驱动渲染更新,因为无法保证100ms,但是这个思路是通用的。

游戏引擎其实就是一个死循环,每次循环开始都要擦除上一次的绘制结果,然后计算出当前帧的绘制数据,多次调用draw函数进行渲染,希望到这里,能让你对游戏引擎有更深层次的理解。

拓展

上边的代码中,我们如果要绘制多个不同颜色、不同位置、不同大小的点,就比较麻烦,而且数据量比较多,webgl当然考虑到了这种情况,所以产生了buffer的概念,并且可以通过gl.vertexAttribPointer进行数据的绑定,这里就不再展开了,留给你自己探索了。

要从webgl的角度理解cocos creator的shader,webgl的基础准备知识暂时就介绍到这里就可以了,下一节就写一个非常简单的cocos creator shader。