WebGL学习入门(二)基本几何图元绘制

承接上文,当我们将编译好的着色器与JS程序连接后,WebGL就可以开始使用了。但是我们需要解决几个关键的问题:

  1. 着色器绘制所需的数据,比如说顶点还有颜色,JS该怎么给它。
  2. 拿到数据,该怎么调动WebGL开始绘制?

WebGL中JS向着色器传值的方式

着色器的变量类型

  1. attribute变量
    使用attribute关键字声明的变量属于顶点属性,常用的顶点属相包括位置坐标值、纹理坐标值、颜色值、切向量、法向量和骨骼权重值等。

    attribute关键字声明的变量不需要赋值,WebGL驱动会自动将存在顶点缓存中的顶点数据传输到Vertex Shader(顶点着色器)中。Vertex Shader中,attribute变量只有可读属性,只能用于Vertex Shader中。

  2. uniform变量
    使用uniform关键字声明的变量属于全局变量,Vertex Shader和Fragment Shader(片元着色器)都能使用,也只有可读属性
  3. varying变量
    使用varying关键字声明的变量是从Vertex Shader传到Fragment Shader的变量,不需要外部输入,直接在Vertex Shader复值,也是唯一一个可读写的变量。

JS输入attribute变量

完整代码

function initArrayBuffer(gl, attribute, data, num, type) {
  // 创建缓冲区对象
  var buffer = gl.createBuffer();
  if (!buffer) {
    console.log('Failed to create the buffer object');
    return false;
  }
  // 将缓存区对象绑定到target上
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  // 将顶点相关数据写到缓存区对象
  // - gl.STATIC_DRAW: 缓冲区的内容可能经常使用,而不会经常更改。内容被写入缓冲区,但不被读取。
  // - gl.DYNAMIC_DRAW: 缓冲区的内容可能经常被使用,并且经常更改。内容被写入缓冲区,但不被读取。
  // - gl.STREAM_DRAW: 缓冲区的内容可能不会经常使用。内容被写入缓冲区,但不被读取。
  gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
  // 获取对应的attribute变量
  var a_attribute = gl.getAttribLocation(gl.program, attribute);
  // 判断着色器是否存在该变量
  if (a_attribute < 0) {
    console.log('Failed to get the storage location of ' + attribute);
    return false;
  }
  //将缓存区对象分配给对应的attribute变量
  // void gl.vertexAttribPointer(index, size, type, normalized, stride, offset);
  // - index:指定要修改的顶点属性的索引。
  // - size:指定每个顶点属性的组成数量,必须是1,2,3或4。
  // - type:指定数组中每个元素的数据类型可能是:gl.BYTE、gl.SHORT、gl.UNSIGNED_BYTE,gl.UNSIGNED_SHORT、gl.FLOAT
  // - normalized:当转换为浮点数时是否应该将整数数值归一化到特定的范围。
  // - stride:一个GLsizei,以字节为单位指定stride个为一组处理。不能大于255。如果stride为0,则假定该属性是紧密打包的,即不交错属
  // 性,每个属性在一个单独的块中,下一个顶点的属性紧跟当前顶点之后。
  // - offset:这一组偏移offset个数据再赋值。必须是类型的字节长度的倍数。
  gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
  // 开启attribute对象
  gl.enableVertexAttribArray(a_attribute);

  return true;
}

JS输入uniform变量

顶点着色器存在这三个变量:

  'uniform mat4 u_MvpMatrix;/n' +
  'uniform vec3 u_LightColor;/n' +   
  'uniform vec3 u_LightDirection;/n'
  1. 获取着色器中的uniform变量
  var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
  var u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');
  var u_LightDirection = gl.getUniformLocation(gl.program, 'u_LightDirection');
  1. 赋值
 gl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);                          //赋三个浮点数
 gl.uniform3fv(u_LightDirection, lightDirection.elements);           //赋长度为3的数组
 gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);       //赋变量

JS输入varying变量

varying变量是用来顶点着色器与片元着色器传输数据的,所以不需要JS给它传值了

WebGL的绘制

WebGL的七种绘制方式

假如依次传入v0,v1,v2,v3,v4,v5六个顶点

  1. gl.POINTS:依次画六个顶点
  2. gl.LINES:一系列单独的线段 (v0,v1) (v2,v3) (v4,v5) 三条线段
  3. gl.LINE_STRIP:一系列连接起来的线段,(v0,v1) (v1,v2) (v2,v3)…五条线段
  4. gl.LINE_LOOP:在上一个的基础上把首尾两个点连接成线段,(v0,v1) (v1,v2) (v2,v3)…(v5,v0)六条线段
  5. gl.TRIANGLES:一系列单独的三角形,(v0,v1,v2) (v3,v4,v5) 两个三角形
  6. gl.TRIANGLE_STRIP:一系列带条状的三角形。前三个点构成一个三角形,从第二个点开始的三个点构成第二个三角形(与上一个共一条边)以此类推。(v0,v1,v2) (v1,v2,v3) (v2,v3,v4) (v3,v4,v5) 四个三角形
  7. gl.TRIANGLE_FAN:一系列三角形构成类似于扇形的图形。前三个点构成一个三角形,接下来的一个点和上一个三角形的最后一条边组成下一个三角形,以此类推。(v0,v1,v2) (v0,v2,v3) (v0,v3,v4) (v0,v4,v5) 四个三角形在这里插入图片描述

WebGL的四种绘制函数

  1. gl.drawArrays(mode, first, count);
  2. gl.drawElements(mode, count, type, offset);
    在这里插入图片描述

    下面为实例绘制方法,告诉GPU使用共享模型来绘制每一个实例,可以用来实现粒子系统。初学者可以跳过这部分。
    WebGL2.0新方法
    3. gl.drawArraysInstanced(mode,first,count,instanceCount);
    4. gl.drawElementsInstanced(mode, count, type, offset, instanceCount);

    实例绘制,下面这个方法调整 每个实例位置
    gl.vertexAttribDivisor(attributeIndex,divisor);
    具体使用如同向Vertex Shader传递顶点数据,一个顶点对应一个偏移数据。

    WebGL1.0没有上面两个方法,但可以使用扩展:

    var offsets = new Float32Array(offsetArray);
    var ext = gl.getExtension('ANGLE_instanced_arrays');
    var offsetBuffer = gl.createBuffer();
    var aOffsetLocation = gl.getAttribLocation(shaderProgram, 'aOffset');
    gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, offsets, gl.STATIC_DRAW);
    gl.enableVertexAttribArray(aOffsetLocation);
    gl.vertexAttribPointer(aOffsetLocation, 3, gl.FLOAT, false, 12, 0);
    ext.vertexAttribDivisorANGLE(aOffsetLocation, 1);

记得清除

每次绘制之前都要清除画布,清除缓冲区,是为了防止多次绘制的结果重叠在屏幕上。
gl.clear(gl.COLOR_BUFFER_BIT);
这是清除颜色缓冲区,如果打开了深度检测,记得清除深度缓冲区(gl.DEPTH_BUFFER_BIT)

参考

  • [1] [WebGL编程指南]

 

来源:https://blog.csdn.net/from_the_star/article/details/105268470

WEBGL学习网(WebGLStudy.COM)专注提供WebGL 、ThreeJS、BabylonJS等WEB3D开发案例源码下载。
声明信息:
1. 本站部分资源来源于用户上传和网络,如有侵权请邮件联系站长:1218436398@qq.com!我们将尽快处理。
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源打赏售价用于赞助本站提供的服务支出(包括不限服务器、网络带宽等费用支出)!
7.欢迎加QQ群学习交流:549297468 ,或者搜索微信公众号:WebGL学习网
WEBGL学习网 » WebGL学习入门(二)基本几何图元绘制

发表评论

提供优质的WebGL、ThreeJS源码

立即查看 了解详情