zoukankan      html  css  js  c++  java
  • WebGL笔记(四):初步封装

    第一篇笔记曾经提到过WebGLHelper对象,但是实际后续的篇幅中并没有使用这个Helper。为了封装的需要,现在我们需要开始讨论并完善这个对象。在这两天的封装过程中,经过删改,WebGLHelper最终形态如下:

    /*
    * WebGLHelper
    * 管理WebGL的辅助对象
    */
    var WebGLHelper = {
        /* 根据ID定位DOM元素 */
        $ : function(id){
            return typeof id == 'string' ? document.getElementById(id) : id;
        },
        /* 获取canvas标记的WebGL对象 */
        $$ : function(canvas){
            if(!(canvas = this.$(canvas))
                || canvas.nodeType != 1
                || canvas.nodeName.toLowerCase() != 'canvas'
                ){
                return null;
            } else {
                try{
                    return canvas.getContext('experimental-webgl');
                } catch(ex){ return null; }
            }
        },
        /* 获取script标记中的代码 */
        getShaderScript : function(script){
            if(!(script = this.$(script))) return null;
            var source = '', child = script.firstChild;
            while(!!child){
                if(child.nodeType == 3){
                    source += child.textContent;
                }
                child = child.nextSibling; 
            }
            child = script = null;
            return source;
        },
        /* 获取所有x-shader代码节点 */
        allScripts : function(){
            var arr = [], els = document.getElementsByTagName('script'), i = 0, len = els.length;
            for(; i < len; i++){
                if(!!els[i].type && els[i].type.toLowerCase().indexOf('x-shader/') >= 0){
                    arr.push(els[i]);
                }
            }
            els = i = len = null;
            if(arr.length < 1){
                return arr = null
            } else {
                return arr;
            }
        },
        /*
        * 从所有代码节点中理出vertex和fragment两种代码
        * 返回一个对象{ vs:string, fs:string }
        * 如果有两个相同type的shader-script,较靠后的节点的内容会作为最终赋值
        */
        documentShaders : function(){
            var scripts = this.allScripts(), i = 0, len = scripts.length
                shaders = {};
                ;
            for(; i < len; i++){
                switch(scripts[i].type){
                    case 'x-shader/x-fragment':
                        shaders.fs = this.getShaderScript(scripts[i]);
                        break;
                    case 'x-shader/x-vertex':
                        shaders.vs = this.getShaderScript(scripts[i]);
                        break;
                }
            }
            return shaders;
        }
    }

    为了减少代码,现在只保留了可能用到的方法。在以后有可能根据情况再作删改。

    综合这两天的代码,另外创建了iWebGL对象。嗯,加个i是为了赶时髦的,但是加上以后这名字也的确平添了不少亲和力有木有?

    下面是对前例的修改,使用iWebGL后的感觉思路比较清晰了:

    /*
    创建WebGL对象
    第一个参数是canvas节点id
    参数大于1个的时候,会调用clear方法,后面的参数将传递给clear方法
    所以参数0为clear参数的第一个参数r,即背景色的红色数量
    这里是为了在构造函数中调用clear
    也可以
    var igl = new iWebGL('glcanvas');
    igl.clear();
    */
    var igl = new iWebGL('glcanvas', 0);
    /*
    调用Shader脚本
    可接受参数类型为两种情况
    1.无参数.这时会在页面中搜寻script标记并加载.
    2.两个参数,即shader形参方式 
    void shader(vert, frag);
    分别加载vertex和fragment两种代码字符串
    */
    igl.shader();
    //定位Shader的参数并对其赋值
    igl.paramVertices('aVertexPosition').define(vertices);
    igl.paramColors('aVertexColor').define(generatedColors);
    igl.paramVerticesIndex().define(cubeVertexIndices);
     
    //设置场景
    igl.matrix.trans([0.0, 0.0, -8.0]);
    igl.matrix.make(40, 640 / 480, 0.1, 100.0);
    //动画函数
    var animate = function(){
        igl.matrix.rotate(1, [1, 0, 1]);
        igl.drawCube();;
    }
    //转吧
    setInterval(animate, 40);

    归纳为三步:

    1. 初始化,(获取)定义对象的相关属性;
    2. 加载Shader并传递数据;
    3. 设置场景;
    4. 绘制物体。

    从本例开始,Shader沿用MDN的做法,混写在html中了。Js写换行字符串比较难看。

    另外说明一下,为了不污染window域,我对glUtils.js文件做了一点修改,将makePerspective等几个function挪到Matrix下了,并更名为glUtils_mod.js。这两个文件都已上传。

    在Chrome15和FF8下运行通过

    捕获2捕获3


    相关文件列表:

    文件

    说明

    glUtils_mod.js 

    这个是改过的

    glUtils.js

    这个是原文件,但是本文木有用

    iWebGL_beta.js 

    iWebGL对象

    sylvester.js

    Matrix对象基础

    代码全文:

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>WebGL Step 04</title>
    <style type="text/css">
    canvas{ background-color:#f1f1f1; }
    </style>
    <script type="text/ecmascript" src="https://files.cnblogs.com/muse/sylvester.js"></script>
    <script type="text/ecmascript" src="https://files.cnblogs.com/muse/glUtils_mod.js"></script>
    <script type="text/ecmascript" src="https://files.cnblogs.com/muse/iWebGL_beta.js"></script>
     
    <script id="shader-vs" type="x-shader/x-vertex">  
    attribute vec3 aVertexPosition;  
    attribute vec4 aVertexColor;  
     
    uniform mat4 uMVMatrix;  
    uniform mat4 uPMatrix;
     
    varying lowp vec4 vColor;  
     
    void main(void) {  
        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);  
        vColor = aVertexColor;  
    }
    </script>
     
    <script id="shader-fs" type="x-shader/x-fragment">  
    varying lowp vec4 vColor;  
    void main(void) { gl_FragColor = vColor; }
    </script>
     
    </head>
    <body>
     
    <canvas id="glcanvas" width="640" height="480">看来您的浏览器不支持<code>&lt;canvas&gt;</code>标记</canvas>
    <script type="text/ecmascript">
    var vertices = [
        // Front face
        -1.0, -1.0,  1.0,
         1.0, -1.0,  1.0,
         1.0,  1.0,  1.0,
        -1.0,  1.0,  1.0,
        
        // Back face
        -1.0, -1.0, -1.0,
        -1.0,  1.0, -1.0,
         1.0,  1.0, -1.0,
         1.0, -1.0, -1.0,
        
        // Top face
        -1.0,  1.0, -1.0,
        -1.0,  1.0,  1.0,
         1.0,  1.0,  1.0,
         1.0,  1.0, -1.0,
        
        // Bottom face
        -1.0, -1.0, -1.0,
         1.0, -1.0, -1.0,
         1.0, -1.0,  1.0,
        -1.0, -1.0,  1.0,
        
        // Right face
         1.0, -1.0, -1.0,
         1.0,  1.0, -1.0,
         1.0,  1.0,  1.0,
         1.0, -1.0,  1.0,
        
        // Left face
        -1.0, -1.0, -1.0,
        -1.0, -1.0,  1.0,
        -1.0,  1.0,  1.0,
        -1.0,  1.0, -1.0
    ];
     
    var cubeVertexIndices = [
        0,  1,  2,      0,  2,  3,    // front
        4,  5,  6,      4,  6,  7,    // back
        8,  9,  10,     8,  10, 11,   // top
        12, 13, 14,     12, 14, 15,   // bottom
        16, 17, 18,     16, 18, 19,   // right
        20, 21, 22,     20, 22, 23    // left
    ]
     
    var colorGroups = [  
        [1.0,  0.0,  1.0,  1.0],    // white  
        [1.0,  0.0,  0.0,  1.0],    // red  
        [0.0,  1.0,  0.0,  1.0],    // green  
        [0.0,  0.0,  1.0,  1.0],    // blue
        [0.0,  1.0,  1.0,  1.0],
        [1.0,  1.0,  0.0,  1.0]
    ];
    var generatedColors = [];
    for(var i = 0; i < 6; i++){
        for(var j = 0; j < 4; j++){
            generatedColors = generatedColors.concat(colorGroups[i]);
        }
    }
    /*
    创建WebGL对象
    第一个参数是canvas节点id
    参数大于1个的时候,会调用clear方法,后面的参数将传递给clear方法
    所以参数0为clear参数的第一个参数r,即背景色的红色数量
    这里是为了在构造函数中调用clear
    也可以
    var igl = new iWebGL('glcanvas');
    igl.clear();
    */
    var igl = new iWebGL('glcanvas', 0);
    /*
    调用Shader脚本
    可接受参数类型为两种情况
    1.无参数.这时会在页面中搜寻script标记并加载.
    2.两个参数,即shader形参方式 
    void shader(vert, frag);
    分别加载vertex和fragment两种代码字符串
    */
    igl.shader();
    //定位Shader的参数并对其赋值
    igl.paramVertices('aVertexPosition').define(vertices);
    igl.paramColors('aVertexColor').define(generatedColors);
    igl.paramVerticesIndex().define(cubeVertexIndices);
     
    //设置场景
    igl.matrix.trans([0.0, 0.0, -8.0]);
    igl.matrix.make(40, 640 / 480, 0.1, 100.0);
    //动画函数
    var animate = function(){
        igl.matrix.rotate(1, [1, 0, 1]);
        igl.drawCube();;
    }
    //转吧
    setInterval(animate, 40);
    </script>
    </body>
    </html>

    预告一下:下一步封装顶顶点和颜色等这类大数组。

  • 相关阅读:
    vue-router 动态路由匹配
    vue-router $route
    vuex mapActions
    vuex mapMutations 使用
    ES6 动态计算属性名
    vuex Payload 荷载
    vuex mapGetters
    vuex mapState使用
    Vue 引入ElementUI 2.0.11:依赖未发现的问题
    vuex 深入理解
  • 原文地址:https://www.cnblogs.com/muse/p/2271846.html
Copyright © 2011-2022 走看看