自学内容网 自学内容网

WebGL缓冲区

一、缓冲区对象

缓冲区对象时WebGL系统中的一块内存区域,可以一次性地向缓冲区对象中填充大量的顶点数据,然后将这些数据保存其中,供顶点着色器使用。

类型化数组

这样程序可以预知数组中的类型,提高性能

类型描述
Int8Array8位整型
UInt8Array8位无符号整型
Int16Array16位整型
UInt16Array16位无符号整型
Int32Array32位整型
UInt32Array32位无符号整型
Float32Array单精度32位浮点型
Float64Array双精度64位浮点型
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>使用缓冲区对象</title>
    <script src="../../lib/index.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        canvas {
            margin: 50px auto 0;
            display: block;
            background: yellow;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="400" height="400">
        此浏览器不支持webGL
    </canvas>
</body>
</html>

<script>
    const ctx = document.getElementById('canvas')

    const gl = ctx.getContext('webgl');

    //着色器
    //创建着色器源码
    const VERTEX_SHADER_SOURCE = `
        attribute vec4 aPosition;
        void main(){
            //要绘制的坐标
            gl_Position = aPosition;
            //要绘制的大小(着色器变量使用的是浮点型)
            gl_PointSize = 10.0;
        }
    `; //顶点着色器

    const FRAGMENT_SHADER_SOURCE = `
        void main(){
            //要绘制的颜色
            gl_FragColor = vec4(1.0,0.0,0.0,1.0);
        }
    `; //片元着色器

    const program =  initShader(gl,VERTEX_SHADER_SOURCE,FRAGMENT_SHADER_SOURCE)
    const aPosition = gl.getAttribLocation(program, 'aPosition')

  
    const points = new Float32Array([
        -0.5,-0.5,
        0.5,-0.5,
        0.0,0.5
    ])

    //创建缓冲区
    const buffer = gl.createBuffer();
    //绑定缓冲区对象
    gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
 //向缓冲区写入数据
    gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)
    //指定顶点变量
    gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,0,0);
    //激活
    gl.enableVertexAttribArray(aPosition)
    //使用gl.disableVertexAttribArray禁用
    gl.drawArrays(gl.POINTS,0,3)
</script>

gl.bufferData(target,data,type)

target表示缓冲区对象:

  • gl.ARRAY_BUFFER:表示缓冲区存储的是顶点数据
  • gl.ELEMENT_ARRAY_BUFFER:表示缓冲区存储的是顶点的索引值

data表示需要写入到缓冲区的顶点数据,如程序中的points

type表示如何使用缓冲区的数据分为如下几类:

  • gl.STATIC_DRAW:写入一次,多次绘制
  • gl.STREAM_DRAW:写入一次,绘制若干次
  • gl.DYNAMIC_DRAW:写入多次,绘制多次

gl.vertexAttribPointer(location,size,type,normalized,stride,offset)

location : attribute变量存储位置

size: 指定每个顶点所使用数据的个数

type: 指定数据格式:

  • gl.FLOAT:浮点型
  • gl.UNSIGNED_BYTE:无符号字节
  • gl.SHORT:短整型
  • gl.UNSIGNED_SHORT:无符号短整型
  • gl.INT 整型
  • gl.UNSIGNED_INT:无符号整型

normalized:表示是否将数据归一化

stride: 两个相邻顶点之间的字节数

offset: 数据偏移量

在这里插入图片描述

缓冲区对象使用流程

请添加图片描述

缓冲区对象执行过程

请添加图片描述

二、多缓冲区和数据偏移

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>多缓冲区与数据偏移</title>
    <script src="../../lib/index.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        canvas {
            margin: 50px auto 0;
            display: block;
            background: yellow;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="400" height="400">
        此浏览器不支持webGL
    </canvas>
</body>
</html>

<script>
    const ctx = document.getElementById('canvas')

    const gl = ctx.getContext('webgl');

    //着色器
    //创建着色器源码
    const VERTEX_SHADER_SOURCE = `
        attribute vec4 aPosition;
        attribute float aPointSize;
        void main(){
            //要绘制的坐标
            gl_Position = aPosition;
            //要绘制的大小(着色器变量使用的是浮点型)
            gl_PointSize = aPointSize;
        }
    `; //顶点着色器

    const FRAGMENT_SHADER_SOURCE = `
        void main(){
            //要绘制的颜色
            gl_FragColor = vec4(1.0,0.0,0.0,1.0);
        }
    `; //片元着色器

    const program =  initShader(gl,VERTEX_SHADER_SOURCE,FRAGMENT_SHADER_SOURCE)
    const aPosition = gl.getAttribLocation(program, 'aPosition')
    const aPointSize = gl.getAttribLocation(program, 'aPointSize')

    
    const points = new Float32Array([
        -0.5,-0.5,10.0,//点的大小10.0
        0.5,-0.5,20.0,//点的大小20.0
        0.0,0.5,30.0//点的大小30.0
    ])

    const buffer = gl.createBuffer();
    
    gl.bindBuffer(gl.ARRAY_BUFFER,buffer);

    gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)

    const BYTES = points.BYTES_PER_ELEMENT;

    gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,BYTES*3,0);
    gl.enableVertexAttribArray(aPosition)
//BYTES*3,BYTES*2 就是数据偏移量
    gl.vertexAttribPointer(aPointSize,1,gl.FLOAT,false,BYTES*3,BYTES*2);
    gl.enableVertexAttribArray(aPointSize)
    gl.drawArrays(gl.POINTS,0,3)
</script>

在这里插入图片描述

多缓冲区流程

在这里插入图片描述

三、多种图形的绘制

可绘制的图形

作用说明
gl.POINTS一系列点
gl.LINES线段一系列单独的线段,如果顶点是奇数,最后一个点会被忽略
gl.LINE_LOOP闭合线一系列连续的线段,结束时,会闭合起点和终点
gl.LINE_STRIP线条一系列连接的线段,不会闭合终点和起点
gl.TRIANGLES三角形一系列单独的三角形
gl.TRIANGLES_STRIP三角带一系列条带状的三角形
gl.TRIANGLES_FAN三角形飘带状三角形
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>多种图形绘制</title>
    <script src="../../lib/index.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        canvas {
            margin: 50px auto 0;
            display: block;
            background: yellow;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="400" height="400">
        此浏览器不支持webGL
    </canvas>
</body>
</html>

<script>
    const ctx = document.getElementById('canvas')

    const gl = ctx.getContext('webgl');

    //着色器
    //创建着色器源码
    const VERTEX_SHADER_SOURCE = `
        attribute vec4 aPosition;
        void main(){
            //要绘制的坐标
            gl_Position = aPosition;
            //要绘制的大小(着色器变量使用的是浮点型)
            gl_PointSize = 10.0;
        }
    `; //顶点着色器

    const FRAGMENT_SHADER_SOURCE = `
        void main(){
            //要绘制的颜色
            gl_FragColor = vec4(1.0,0.0,0.0,1.0);
        }
    `; //片元着色器

    const program =  initShader(gl,VERTEX_SHADER_SOURCE,FRAGMENT_SHADER_SOURCE)
    const aPosition = gl.getAttribLocation(program, 'aPosition')

    
    const points = new Float32Array([
        -0.5,-0.5,
        0.5,-0.5,
        0.0,0.5,
        -0.5,0.0
    ])

    const buffer = gl.createBuffer();
    
    gl.bindBuffer(gl.ARRAY_BUFFER,buffer);

    gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)


    gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,0,0);
    gl.enableVertexAttribArray(aPosition)

    
    gl.drawArrays(gl.TRIANGLE_STRIP,0,4)


</script>

在这里插入图片描述

四、矩阵组合实现图形的复合变换

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>复合变化</title>
    <script src="../../lib/index.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        canvas {
            margin: 50px auto 0;
            display: block;
            background: yellow;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="400" height="400">
        此浏览器不支持webGL
    </canvas>
</body>
</html>

<script>
    const ctx = document.getElementById('canvas')

    const gl = ctx.getContext('webgl');

    //着色器
    //创建着色器源码
    const VERTEX_SHADER_SOURCE = `
        attribute vec4 aPosition;
        //为什么要用uniform-因为要对所有的顶点实现同样的变换
        uniform mat4 translateMatrix;
        uniform mat4 scaleMatrix;
        uniform mat4 rotateMatrix;

        void main(){
            //要绘制的坐标
            gl_Position = translateMatrix * scaleMatrix * rotateMatrix * aPosition;
            //要绘制的大小(着色器变量使用的是浮点型)
            gl_PointSize = 10.0;
        }
    `; //顶点着色器

    const FRAGMENT_SHADER_SOURCE = `
        void main(){
            //要绘制的颜色
            gl_FragColor = vec4(1.0,0.0,0.0,1.0);
        }
    `; //片元着色器

    const program =  initShader(gl,VERTEX_SHADER_SOURCE,FRAGMENT_SHADER_SOURCE)

    const aPosition = gl.getAttribLocation(program, 'aPosition')
    const translateMatrix = gl.getUniformLocation(program, 'translateMatrix')
    const scaleMatrix = gl.getUniformLocation(program, 'scaleMatrix')
    const rotateMatrix = gl.getUniformLocation(program, 'rotateMatrix')

    const points = new Float32Array([
        -0.5,-0.5,
        0.5,-0.5,
        0.0,0.5,
    ])

    const buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
    gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)
    gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,0,0);
    gl.enableVertexAttribArray(aPosition)

    let deg = 0;
    let translateX = -1;
    let scaleX = 0.1;
    function animation(){
        deg += 0.1
        translateX += 0.1;
        scaleX += 0.1;

        if(translateX > 1){translateX = -1;} 
        if(scaleX > 1.5) {scaleX = 0.1;}


        const translate = getTranslateMatrix(translateX);
        const scale = getScaleMatrix(scaleX);
        const rotate = getRotateMatrix(deg);


        gl.uniformMatrix4fv(translateMatrix,false,translate)
        gl.uniformMatrix4fv(scaleMatrix,false,scale)
        gl.uniformMatrix4fv(rotateMatrix,false,rotate)

        gl.drawArrays(gl.TRIANGLES,0,3)

        requestAnimationFrame(animation);
    }

    animation();

</script>

在这里插入图片描述


原文地址:https://blog.csdn.net/gghhb12/article/details/142415500

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!