WebGL入门教程三:更灵活的数据传递和绘制图形

作者:心叶
时间:2018-05-16 10:55

绘制三个点

前一篇文章我们绘制了一个点,现在想绘制三个点,怎么办?

当然,你可以按照绘制一个点的方法,绘制三次,不过我们这里来说说如何一次绘制三个点。

在前面代码的基础上,我们只需要修改传递点的个数,然后修改绘画方法就可以了。

传递三个点

之前【传递点的位置】处的代码的传递方法只可以传递一个点,如果想传递三个点,需要使用缓冲区。

因此,我们第一步要创建一个缓冲区,并且把点的数据写入缓冲区,代码如下(注释调原来【传递点的位置】的代码,在相同位置添加):

//1.创建缓冲区对象
var vertexBuffer = gl.createBuffer();
// 2.绑定缓冲区对象(表明了缓冲区对象的用途)
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
// 3.向缓冲区对象中写入数据
var tempData=new Float32Array([
    0.0, 0.5,  
    -0.5, -0.5, 
    -0.5, 0.5
]);
gl.bufferData(gl.ARRAY_BUFFER, tempData, gl.STATIC_DRAW);

这样,缓冲区就准备好了,接着,把缓冲区和着色器联系起来:

// 4.获取变量存储位置
var a_Position = gl.getAttribLocation(glProgram, 'a_Position');
// 5.把缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
// 6.连接缓冲区对象和a_Position变量
gl.enableVertexAttribArray(a_Position);

这样,点的位置就传递好了。

修改绘图方法

现在,修改一下绘图方法:

gl.drawArrays(gl.POINTS, 0, 3);

刷新页面,应该可以看见下图:
WebGL入门教程三:更灵活的数据传递和绘制图形

绘制三个不同大小的点

数据修改

首先,我们要在缓冲区或准备一下数据,表示每个点的大小,对应代码修改如下:

var tempData=new Float32Array([
    0.0, 0.5,  10.0,
    -0.5, -0.5, 20.0,
    -0.5, 0.5,30.0
]);
//这个是每个数据大小,辅助用的
var FSIZE = tempData.BYTES_PER_ELEMENT;

传递点位置的方法修改

由于数据重新调整了,缓冲区分配给点位置的变量也要对应调整:

gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE*3, 0);

不清楚的可以去百度一个vertexAttribPointer这个方法,后面我们会统一说明一些常用方法,这里就不说了。

现在,你刷新页面,应该和之前的一样。

传递点大小的方法修改

和上面类似,之前传递一个点大小,现在传递三个就可以了:

//【传递点的大小】
var a_PointSize=gl.getAttribLocation(glProgram,'a_PointSize');
//之前传递一个的方法注释调了
// gl.vertexAttrib1f(a_PointSize,30.0);
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, FSIZE*3, FSIZE*2);
gl.enableVertexAttribArray(a_PointSize);

现在刷新页面,应该就可以了:
WebGL入门教程三:更灵活的数据传递和绘制图形

绘制三角形

普通三角形

到目前为止,传递多个点应该没有问题了吧,如果想绘制复杂图形,调用对应api就可以了,比如绘制三角形,修改最后一个绘制方法(绘制三角形的话,点的大小就没有意义了,可以删除,留着也没事):

// gl.drawArrays(gl.POINTS, 0, 3);
gl.drawArrays(gl.TRIANGLES, 0, 3);

结果如下:
WebGL入门教程三:更灵活的数据传递和绘制图形

彩色三角形

既然位置可以传递多个,是不是颜色也可以,是的,也可以。

同样的,我们先添加颜色数据:

var tempData=new Float32Array([
    0.0, 0.5,  10.0,1.0,0.0,1.0,
    -0.5, -0.5, 20.0,0.0,1.0,0.0,
    -0.5, 0.5,30.0,0.0,0.0,1.0
]);

修改缓冲区绑定位置的方法:

gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE*6, 0);

由于要传递三个点,uniform只可以传递一致的数据,因此我们需要用attribute,可是attribute有只可以用在顶点着色器,因此,需要先传递改顶点着色器,然后借助varying传递给片段着色器,着色器修改如下(点的大小代码就没有删除了):

<!-- 顶点着色器 -->
<script type='x-shader/x-vertex' id='shader-vs'>
    attribute vec4 a_Position;
    attribute float a_PointSize;
    attribute vec4 a_Color;
    varying vec4 v_FragColor;
    void main(){
        gl_Position=a_Position;
        gl_PointSize=a_PointSize;
        v_FragColor=a_Color;
    }
</script>
<!-- 片段着色器 -->
<script type='x-shader/x-fragment' id='shader-fs'>
    precision lowp float;
    varying vec4 v_FragColor;
    void main(){
        gl_FragColor=v_FragColor;
    }
</script>

然后,和点的位置一样,修改传递色彩的代码:

// 【传递点的颜色】
var a_Color = gl.getAttribLocation(glProgram, 'a_Color');
// gl.uniform4f(u_FragColor,1.0,0.0,0.0,1.0);
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);
gl.enableVertexAttribArray(a_Color);

显示效果如下:
WebGL入门教程三:更灵活的数据传递和绘制图形

相关推荐