zoukankan      html  css  js  c++  java
  • WebGL编程指南案例解析之多数据存储于一个缓冲区以及着色器通信

    //顶点着色器往片元着色器传值
    //多个参数值存于一个缓冲对象中
    
    
    var vShader = `
        attribute vec4 a_Position;
        attribute float a_PointSize;
        attribute vec4 a_Color;
        varying vec4 v_Color;
        void main(){
            gl_Position = a_Position;
            gl_PointSize = a_PointSize;
            v_Color = a_Color;
        }
    `;
    
    var fShader = `
    //设定默认精度
        precision mediump float;
        varying vec4 v_Color;
        void main(){
            gl_FragColor = v_Color;
        }
    `;
    
    
    
    function main(){
        //获取canvas元素
        var canvas = document.getElementById('webgl');
    
        //获取webgl上下文
        var gl = getWebGLContext(canvas);
    
        if(!gl){
            console.log('Failed to get the rendering context for WebGL!');
            return;
        }
    
        
    
        //初始化着色器
        if(!initShaders(gl,vShader,fShader)){
            console.log('Failed to initialize shaders.');
            return;
        }
    
    
        var n = initVertexBuffers(gl);
        if(n < 0){
            console.log('Failed to set the positions of the vertices!');
            return;
        }
    
        //用指定颜色填充webgl容器,就是设置背景
        gl.clearColor(0.4, 0.5, 0.0, 1.0);
        gl.clear(gl.COLOR_BUFFER_BIT);
    
    
    
        gl.drawArrays(gl.TRIANGLES,0,n);
    
    
    
        function initVertexBuffers(gl){
            var verticesSizes =  new Float32Array([
                0.0,0.5,10.0,1.0,0.0,0.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
            ]);
            var n = 3;//点的个数
    
            //创建缓冲区对象
            var vertexSizeBuffer = gl.createBuffer();
            if(!vertexSizeBuffer){
                console.log('Failed to create the buffer object!');
                return -1;
            }
    
            //将缓冲区对象绑定到目标ARRAY_BUFFER
            gl.bindBuffer(gl.ARRAY_BUFFER,vertexSizeBuffer);
            //往ARRAY_BUFFER
            gl.bufferData(gl.ARRAY_BUFFER,verticesSizes,gl.STATIC_DRAW);
    
    
            var fsize = verticesSizes.BYTES_PER_ELEMENT;
            console.log(fsize);
    
    
    
    
            //获取shaderProgram中attribute变量‘a_Position’的地址
            var a_Position = gl.getAttribLocation(gl.program,'a_Position');
            if (a_Position < 0) {
                console.log('Failed to get the storage location of a_Position');
                return -1;
            }
            //将缓冲区对象分配给a_Position变量
            gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,fsize * 6,0);
            //开启着色器对缓冲区数据的访问
            gl.enableVertexAttribArray(a_Position);
    
            var a_PointSize = gl.getAttribLocation(gl.program,'a_PointSize');
            if (a_PointSize < 0) {
                console.log('Failed to get the storage location of a_Position');
                return -1;
            }
            //将缓冲区对象分配给a_PointSize变量
            //这里的3表示每个顶点数据由3个float组成,所以两个点之间的字节量为fsize*3
            //偏移量为fsize*2,1表示只取1个数据
            //比如下面的数据表示从一个顶点中(0.0,0.5,10.0)顶点数据量为单个数据量字节长*3
            //从第fsize*2个字节开始取数据,取1个数据(数据长度为fsize)
            gl.vertexAttribPointer(a_PointSize,1,gl.FLOAT,false,fsize * 6,fsize * 2);
            //开启着色器对缓冲区数据的访问
            gl.enableVertexAttribArray(a_PointSize);
    
            var a_Color = gl.getAttribLocation(gl.program,'a_Color');
            if (a_Color < 0) {
                console.log('Failed to get the storage location of a_Color');
                return -1;
            }
            //将缓冲区对象分配给a_Color变量
            //这里的3表示每个顶点数据由3个float组成,所以两个点之间的字节量为fsize*3
            //偏移量为fsize*2,1表示只取1个数据
            //比如下面的数据表示从一个顶点中(0.0,0.5,10.0)顶点数据量为单个数据量字节长*3
            //从第fsize*2个字节开始取数据,取1个数据(数据长度为fsize)
            gl.vertexAttribPointer(a_Color,3,gl.FLOAT,false,fsize * 6,fsize * 3);
            //开启着色器对缓冲区数据的访问
            gl.enableVertexAttribArray(a_Color);
    
            return n;
        }
    }
    
    
    main();

    注意:

    ①首先顶点着色器接收三个外来数据,position、size、color(我们最终画一个三角形,所以这里的size其实是没用上的);

    ②我们将三个数据拼在一起作为一条数据,所以每6个数值为一个顶点携带的数据,所以我们每次读取6 * size 个字节;

    ③对于这6 * size个字节,根据(偏移量,数据长度)来为三个属性取值定位:

      a_Position:(size * 0 , 2);

      a_PointSize:(size * 2 , 1);

      a_Color:(size * 3 , 3)

    ④对于 varying vec4 v_Color 我们看到,两个着色器中都会有,在顶点着色器中该变量在main()方法中赋值之后,用于输出

    输出给谁用?当然是片元着色器咯,所以在片元着色器中该变量用于接收属性值。

    有一点需要注意,用于两种着色器自定义数据通信的变量,类型和名称都必须一样。

  • 相关阅读:
    CSS自学笔记(9):CSS拓展(二)
    CSS自学笔记(8):CSS拓展(一)
    给大家介绍几个常见的Android代码片段
    分享一个完美的新闻客户端(酷商城)Android源码
    Android dex ,xml 文件反编译方法
    Android宝宝点点乐游戏源码完整版
    Excel基础视频教程在线观看
    计算机二级考试Access教程
    程序员面试题目汇总讲解
    JAVA在线观看视频教程完整版
  • 原文地址:https://www.cnblogs.com/eco-just/p/10680179.html
Copyright © 2011-2022 走看看