webgl中如何通过一个缓冲区,实现传递多种顶点数据.

1.webgl中如何通过一个缓冲区,实现传递多种顶点数据.

这个要求是什么呢?一般我们创建一个缓冲区,都是对顶点坐标进行操作。如果我们要对每个顶点的尺寸也是一个缓冲区进行的赋值操作,那么我们一般又要创建一个缓冲区。如果我们又要对什么进行赋值的话,我们又又要创建一个新的缓冲区。

 而我要讲的是入通过一个缓冲区,将顶点的不同信息一起传入赋值。

如何完成上面的需求呢?

  1. 首先你要会使用webgl的缓冲
  2. 我们只需要改变 vertexAttribPointer这个API的某几个参数就可以了。

如果你不知道 如何使用 webgl的缓冲区将一批数据同时传入webgl的着色器中。请看我的以往的博客。这里不再解释。
webgl(3) -如何使用webgl的缓冲区,使其一次性的写入多条数据,渲染多条数据。

好看代码
1.顶点着色器

const VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' +
  'attribute float a_PointSize;\n' +
  'void main() { \n' +
  '   gl_Position = a_Position;\n' +
  '   gl_PointSize = a_PointSize;\n' +
  '}\n';

这个顶点着色器中,我们有两个变量是attribute的,分别是 a_Position, a_PointSize;
表示顶点的位置,顶点的尺寸。是我们可以通过js进行修改的

2.片源着色器

const FSHADER_SOURCE =
  'void main() { \n' +
  '   gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
  '}\n';

这里的片源着色器,没有什么特别的。

3.看看在创建缓冲区的代码

const vertices = new Float32Array([0.0, 0.5, 0.5, 0.5, 0.0, 2.0, -0.5, 0.0, 3.0])
1.这里的vertices是我们传入缓冲区的全部数据。
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // 是将缓冲区vertexBuffer 绑定到 gl.ARRAY_BUFFER
gl.bufferData(gl.ARRAY_BUFFER, vertices) // 是向缓冲区中写入数据 --> vertices

好了,我们上面完成了什么事情呢?
1.初始化了数据
2.创建一个缓冲区
3.将缓冲区绑定到了gl.ARRAY_BUFFER
4.然后向缓冲区中写入数据.

接下来我们需要将缓冲区中的数据分配给a_Position, a_PointSize变量
const a_Position = gl.getAttribLocation(gl.program, 'a_Position'); // 获取a_Postion的存储地址.
const FSIZE = vertices.BYTES_PER_ELEMENT; // 返回元素字节数
gl.vertexAttribPointer(a_Postion, 2, FLOAT, false, FSIZE * 3, 0);
gl.enableVertexAttribArray(a_Postion); // 开启
const a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
gl.vertexAttribPointer(a_PointSize, 1, FLOAT, false, FSIZE * 3, FSIZE * 2);
gl.enableVertexAttribArray(a_PointSize); // 开启

gl.vertexAttribPointer(index, size, type, normalized, stride, offset)的api

index ----> a_Position  attribute变量的存储地址。
size  ---- 指定每个顶点属性的组成数量。我们这里 a_Position 是为 2。a_PointSize 是为 1
		   因为 a_Position是坐标只需要两个值来表示就够了(x, y)。
		   因为 a_PointSize是表示每个顶点的尺寸只需要一个值就可以了。
type  ----> 表示数据的类型 FLOAT 浮点型
normalized -----> ........
stride -----> 以字节为单位指定连续顶点属性开始之间的偏移量(即数组中一行长度)。不能大于255。如果stride为0,则假定该属性是紧密打包的,即不交错属性,每个属性在一个单独的块中,下一个顶点的属性紧跟当前顶点之后
我简单理解为,每组顶点数据的长度,因为我们这里是 (x, y, size) 所以值为 FSIZE * 3
offset ---> 指定顶点属性数组中第一部分的字节偏移量。必须是类型的字节长度的倍数.简单理解为开始的位置。
因为 a_Position是在(x, y, size)中的前面两个值,所以是 0
因为 a_PointSize 是在(x, y, size)中的最后那一个,所以偏移是 FSIZE * 2;

实例代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #canvas {
            height: 400px;
            width: 400px;
            background-color: red;
        }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
    <script>
        const gl = canvas.getContext('webgl')
        const initShader = (type, source) => {
            const shader = gl.createShader(type);
            gl.shaderSource(shader, source);
            gl.compileShader(shader); // 开始编译着色器
            const compilShader = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
            if (!compilShader) {
                const err = gl.getShaderInfoLog(shader); // 获取编译报错信息
                alert(err)
                console.log(`编译报错信息为${err}`);
                gl.deleteShader(shader);
                return null
            }
            return shader
        }
        // const VSHADER_SOURCE = 
        // 'attribute vec4 a_Position;\n'+
        // 'void main() {\n'+
        // '   gl_Position = a_Position;\n'+
        // '   gl_PointSize = 5.0;\n'+
        // '}\n';
        const VSHADER_SOURCE =
            'attribute vec4 a_Position;\n' +
            'attribute float a_PointSize;\n' +
            'void main() { \n' +
            '   gl_Position = a_Position;\n' +
            '   gl_PointSize = a_PointSize;\n' +
            '}\n';
        const FSHADER_SOURCE =
            'void main() { \n' +
            '   gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
            '}\n';
        const shader = initShader(gl.VERTEX_SHADER, VSHADER_SOURCE);
        // console.log(shader, 'shader')
        const createProgram = (vshader, fshader) => {
            const vertexShader = initShader(gl.VERTEX_SHADER, vshader);
            const fragmentShader = initShader(gl.FRAGMENT_SHADER, fshader);
            // console.log(vertexShader, 'vertexShader')
            // console.log(fragmentShader, 'fragmentShader')
            const program = gl.createProgram();
            gl.attachShader(program, vertexShader);
            gl.attachShader(program, fragmentShader);
            gl.linkProgram(program);
            const linkState = gl.getProgramParameter(program, gl.LINK_STATUS);
            if (!linkState) {
                const err = gl.getProgramInfoLog(program);
                console.log('链接报错的信息为:'+err);
                gl.deleteShader(vertexShader);
                gl.deleteShader(fragmentShader);
                gl.deleteProgram(program);
                return null
            }
            // return program;
            gl.useProgram(program);
            gl.program = program;
        }
        const initVetexBuffers = () => {
            const vertices = new Float32Array([0.5, 0.0, 2.0, 0.0, 0.5, 2.0, -0.5,0,3.0]);
            const FSIZE = vertices.BYTES_PER_ELEMENT;
            var vertexBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
            gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
            const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
            // gl.vertexAttribPointer(a_Position, 2)
            gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 3, 0);
            gl.enableVertexAttribArray(a_Position);
            const a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
            gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, FSIZE * 3, FSIZE * 2);
            gl.enableVertexAttribArray(a_PointSize);
            
        }

        createProgram(VSHADER_SOURCE, FSHADER_SOURCE)
        initVetexBuffers();
        gl.clearColor(0.0,0.0,1.0,1.0);
        gl.clear(gl.COLOR_BUFFER_BIT);
        gl.drawArrays(gl.POINTS, 0, 3)


    </script>
</body>

</html>

效果如下
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值