WebGL编程指南-21 通过顶点索引绘制渐变色的立方体

1.demo效果

在这里插入图片描述如上,通过顶点索引绘制出了一个渐变色的立方体

2. 顶点索引原理

在这里插入图片描述
如上,立方体有8个顶点,v0~v7;6个面,前、后、上、下、左、右;以最前面的面为例,由四个顶点v0-v1-v2-v3拼出的两个三角形组成,这两个三角形使用的顶点索引分别是 (0,1,2)和(0,2,3)。通过三角形的顶点索引,可以取到对应索引的顶点坐标和颜色信息。
创建顶点信息和索引信息示例如下

 const verticesAndColors = new Float32Array([
        1.0, 1.0, 1.0, 1.0, 1.0, 1.0,1.0, //v0 white
        -1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0,//v1 品红
        -1.0, -1.0, 1.0, 1.0, 0.0, 0.0,1.0, //v2 红色
        1.0, -1.0, 1.0, 1.0, 1.0, 0.0,1.0, //v3 黄色
        1.0, -1.0, -1.0, 0.0, 1.0, 0.0,1.0, //v4
        1.0, 1.0, -1.0, 0.0, 1.0, 1.0,1, //v5
        -1.0, 1.0, -1.0, 0.0, 0.0, 1.0,1, //v6
        -1.0, -1.0, -1.0, 0.0, 0.0, 0.0,1, //v7 
    ]);
    const indices = new Uint8Array([
        0, 1, 2, 0, 2, 3, //front
        0, 3, 4, 0, 4, 5, //right
        0, 5, 6, 0, 6, 1, //up
        1, 6, 7, 1, 7, 2, //left
        7, 4, 3, 7, 3, 2, //bottom
        4, 7, 6, 4, 6, 5 //behind
    ]);

3.gl.drawElements() 方法

函数功能:执行着色器,按照mode参数指定的方式,根据gl.ELEMENT_ARRAY_BUFFER的缓冲区的顶点索引绘制图形
--------------------------------------------------------------------------
调用示例:gl.drawArrays(mode, count, type, offset)
--------------------------------------------------------------------------
参数		
			mode		指定绘制的方式,可以接收以下常量符号:
						gl.POINTS,gl.LINES,gl.LINE_STRIP,gl.LINE_LOOP
						gl.TRIANGLES,gl.TRIANGLE_STRIP,gl.TRIANGLE_FAN
			count		指定绘制顶点的个数
			type		指定索引值数据类型,可以以下值
						gl.UNSIGNED_BYTE
						gl.UNSIGNED_SHORT					
			offset		指定索引数组中开始绘制的位置,以字节为单位
--------------------------------------------------------------------------		
返回值		无
--------------------------------------------------------------------------
错  误		INVALID_ENUM			传入的mode参数不是指定参数
			INVALID_VALUE			参数count或offset是负数	

第一个参数mode说明
gl.drawArray()方法可以绘制各种图形,它的第一个参数可以取众多常量:gl.POINTS,gl.LINES,gl.LINE_STRIP,gl.LINE_LOOP,gl.TRIANGLES,gl.TRIANGLE_STRIP,gl.TRIANGLE_FAN,接下来通过一张图来解释
在这里插入图片描述

4.demo代码

const VSHADER_SOURCE = `
attribute vec4 a_Position;
attribute vec4 a_Color;

uniform mat4 u_ViewMatrix;
uniform mat4 u_ProjMatrix;
varying vec4 v_Color;

void main() {
    gl_Position = u_ProjMatrix* u_ViewMatrix*a_Position;
    v_Color = a_Color;
}
`;

const FSHADER_SOURCE = `
    precision mediump float;

varying vec4 v_Color;
void main() {
    gl_FragColor = v_Color;
}
`;

const main = () => {
  //获取绘制dom
  const canvas = document.getElementById("webgl");

  //获取canvas上下文
  const gl = canvas.getContext("webgl");
  gl.enable(gl.DEPTH_TEST);

  //初始化着色器
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    return console.log("Failed to initialize shaders.");
  }

  const initVertexBuffers = (gl) => {
    const u_ViewMatrix = gl.getUniformLocation(gl.program, "u_ViewMatrix");
    const u_ProjMatrix = gl.getUniformLocation(gl.program, "u_ProjMatrix");

    const viewMatrix = new Matrix4();
    const projMatrix = new Matrix4();

    viewMatrix.setLookAt(3, 3, 7, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    projMatrix.setPerspective(30, canvas.width/canvas.height, 1.0, 100);

    gl.uniformMatrix4fv(u_ProjMatrix,false,projMatrix.elements)
    //类型化数组设置顶点坐标
    const verticesAndColors = new Float32Array([
        1.0, 1.0, 1.0, 1.0, 1.0, 1.0,1.0, //v0 white
        -1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0,//v1 品红
        -1.0, -1.0, 1.0, 1.0, 0.0, 0.0,1.0, //v2 红色
        1.0, -1.0, 1.0, 1.0, 1.0, 0.0,1.0, //v3 黄色
        1.0, -1.0, -1.0, 0.0, 1.0, 0.0,1.0, //v4
        1.0, 1.0, -1.0, 0.0, 1.0, 1.0,1, //v5
        -1.0, 1.0, -1.0, 0.0, 0.0, 1.0,1, //v6
        -1.0, -1.0, -1.0, 0.0, 0.0, 0.0,1, //v7 
    ]);
    const indices = new Uint8Array([
        0, 1, 2, 0, 2, 3, //front
        0, 3, 4, 0, 4, 5, //right
        0, 5, 6, 0, 6, 1, //up
        1, 6, 7, 1, 7, 2, //left
        7, 4, 3, 7, 3, 2, //bottom
        4, 7, 6, 4, 6, 5 //behind
    ]);
    // const n = verticesAndColors.length/6; //点的个数

    //创建缓冲区对象
    const vertexBuffer = gl.createBuffer();
    //创建IndexBuffer
    const indicesBuffer = gl.createBuffer();
    if (!vertexBuffer) {
      console.log("Failed to create the buffer object");
      return -1;
    }

    //将缓冲区对象绑定到目标
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    //向缓冲区对象中写入数据
    gl.bufferData(gl.ARRAY_BUFFER, verticesAndColors, gl.STATIC_DRAW);

    const a_Position = gl.getAttribLocation(gl.program, "a_Position");
    const a_Color = gl.getAttribLocation(gl.program, "a_Color");
    const FSIZE = verticesAndColors.BYTES_PER_ELEMENT;

    gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);

    //将缓冲区对象分配给a_Position变量
    gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false,FSIZE * 7, 0);

    //链接a_Position变量与分配给它的缓冲区对象
    gl.enableVertexAttribArray(a_Position);

    gl.vertexAttribPointer(a_Color, 4, gl.FLOAT, false, FSIZE * 7, FSIZE * 3);
    gl.enableVertexAttribArray(a_Color);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indicesBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indices,gl.STATIC_DRAW)
    return indices.length;
  };

  const n = initVertexBuffers(gl);
  if (n < 0) {
    console.error("n<0");
    return;
  }

  gl.clearColor(0.0, 0.0, 0.0, 1.0);

  //清空canvas

  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  //绘制一个点
  gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE,0);
};
main();

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值