前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WebGL第三十课:多个绘制对象的参数调节-颜色

WebGL第三十课:多个绘制对象的参数调节-颜色

作者头像
玖柒的小窝
修改2021-11-04 09:21:24
6880
修改2021-11-04 09:21:24
举报
文章被收录于专栏:各类技术文章~

引子

在上篇文章中,我们可以看到,如果想更改多个绘制对象中的某一个对象的参数时,我们直接重新申请的gl中的buffer,然后重新把所有的顶点数据传入到buffer中,进而绘制。

这种办法主要是针对顶点数据不得不改的时候,比如说,你本来画的是一个格子形状的东西,但是后面需要变成球形的东西。这种时候直接替换新的顶点数据是可以的。

但是,有的时候,我们并不是想要把格子-->球形,仅仅是想换一下格子的颜色。就为了这个,整个替换顶点数据当然不好。

那怎么办呢?使用 shader 中的 uniform 变量,即可。

program uniform buffer 厘清关系

在这里,回顾一下,program 和 uniform 和 buffer 的关系。

当我们绘制三角形的时候,简单这么说:当你调用绘制api(例如gl.drawArrays)之前,必须要选定一个 program,然后调用绘制api,这个时候,program 就开始跑。 怎么跑呢? 答:迭代当前buffer中的数据,例如坐标啦,颜色啦,啥的,然后在屏幕上绘制一个点,每三个点,就用插值法,绘制中间的区域,也就是绘制一个三角形,这样就将一个buffer中的数据都绘制完成。在这个过程之前,你可以设置一下uniform变量,那么在这个绘制过程中,这个变量就会保持不变。当某一个buffer的数据绘制结束之后,你可以随时更改uniform变量,然后接着绘制。

你发现了吗?也就是说不同buffer的数据,可以共用一个 program,但是在切换buffer的时候,我们可以对uniform变量进行修改,从而得到我们的目的,那就是,不同绘制对象的某些参数,可以自由独立的控制,例如可以控制颜色。

你又发现了吗?这样写,不用重新生成buffer数据。真是个好办法!

利用 uniform 来设置颜色

首先第一步要在 fragment_shader里加一个uniform变量,按照习惯,我们命名为:u_color

由于颜色是RGB三个数组成的,这个 u_color应该是一个vec3类型:

代码语言:javascript
复制
    uniform vec3 u_color;
复制代码

然后需要在 js 代码里,获取这个uniform变量引用:

代码语言:javascript
复制
    u_color = gl.getUniformLocation(program, "u_color");
复制代码

这块可以留意一下,获取一个变量的引用,是需要传program的,这也恰恰说明了,uniform是属于program的。

如何给这个变量传值呢?如下:

代码语言:javascript
复制
        gl.uniform3f(u_color, this.color.R, this.color.G, this.color.B);
复制代码

这里注意下,由于 u_color 变量是 vec3 类型,所以传值的时候,需要使用 uniform3f 这个api,后面需要传三个参数,分别代表 vec3 的第一个元素,第二个元素,第三个元素。

这里三个值分别代表 颜色 RGB。

好了,我们要想这个 u_color 生效,还需要真正的设置一下颜色:

代码语言:javascript
复制
      gl_FragColor = vec4(u_color, 1.0);
复制代码

看一下上面的代码,我们完全用这个uniform变量来设置颜色,而忽略buffer中的 color 部分了。所以,我们在构造buffer的时候,不用把颜色传递进去了。

代码语言:javascript
复制
    这里说一点,buffer中到底应不应该带颜色,取决于你的需求,大部分时候,buffer中是应该带上颜色的。 
    我们可以使用uniform这种动态的变量,和buffer中的静态颜色,进行叠加计算,从而得出好玩的效果。
    这点后面再说。
复制代码

绘制多个格子

在上篇文章,我们定义了一个 GridObject 的class,来描述一个格子的行为。

其中 render 方法,根据本文提出的新做法,需要修改如下:

代码语言:javascript
复制
    render(gl, program) {
        gl.bindBuffer(gl.ARRAY_BUFFER, this.glbuffer);
        if (this.modelUpdated) {
            this.modelUpdated = false;
            if (this.a_PointVertex == null) {
                this.a_PointVertex = gl.getAttribLocation(program, 'a_PointVertex');
            }
        }
        //////////////////////////
        gl.vertexAttribPointer(this.a_PointVertex, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(this.a_PointVertex);
        gl.uniform3f(u_color, this.color.R, this.color.G, this.color.B); // 设置颜色uniform
        gl.drawArrays(gl.TRIANGLES, 0, this.pointCount);                 // 绘制当前格子的buffer
    }

复制代码

我们可以看到,主要就是在绘制之前,要修改一下 u_color。

如果有两个 GridObject 对象,前后分别调用 render 的话,那么设置uniform和绘制的顺序如下:

  • 第一个格子 设置 program 中的 u_color
  • 第一个格子 进行绘制 第一个格子 自己的buffer
  • 第二个格子 设置 program 中的 u_color
  • 第二个格子 进行绘制 第二个格子 自己的buffer

如果有更多的格子,只要按照这个顺序,去写逻辑,那么每个格子之间是不会乱的,而自始至终,u_color 就是一个变量,被所有的格子所共用。

还是用滑竿来做个小实验

代码语言:javascript
复制
    <p>
        <b>第一个格子的颜色R:</b>
        <input id="gridcolorR" type="range" min="0" max="1" value="0" step="0.01" oninput="gl_draw()" />
        <b id="gridcolorRvalue">0</b>
    </p>

    <p>
        <b>第一个格子的颜色G:</b>
        <input id="gridcolorG" type="range" min="0" max="1" value="0" step="0.01" oninput="gl_draw()" />
        <b id="gridcolorGvalue">0</b>
    </p>
    <p>
        <b>第一个格子的颜色B:</b>
        <input id="gridcolorB" type="range" min="0" max="1" value="0" step="0.01" oninput="gl_draw()" />
        <b id="gridcolorBvalue">0</b>
    </p>

复制代码

在 gl_draw 这个回调函数里,设置一下第一个格子的颜色, 然后绘制两个格子:

代码语言:javascript
复制
    gridOne.color.R = gridColorRDom.value;
    gridOne.color.G = gridColorGDom.value;
    gridOne.color.B = gridColorBDom.value;

    gridOne.render(gl, program);
    gridTwo.render(gl, program);

复制代码

效果如下:

colorgrid.gif
colorgrid.gif



代码语言:javascript
复制
  正文结束,下面是答疑
复制代码

小丫丫说:除了颜色之外,还有什么可以单独调节?

  • 位置,旋转,拉伸,等等。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • program uniform buffer 厘清关系
  • 利用 uniform 来设置颜色
  • 绘制多个格子
  • 还是用滑竿来做个小实验
  • 小丫丫说:除了颜色之外,还有什么可以单独调节?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档