zoukankan      html  css  js  c++  java
  • WebGL笔记(二):顶点着色

    一、加载Shader

    本文的Shader脚本与上一篇不同,首先做一下修改:

    Vertex:

       1:  <script id="shader-vs" type="x-shader/x-vertex">  
       2:      attribute vec3 aVertexPosition;  
       3:      attribute vec4 aVertexColor;
       4:      uniform mat4 uMVMatrix;  
       5:      uniform mat4 uPMatrix; 
       6:      varying lowp vec4 vColor;
       7:      void main(void) {  
       8:          gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);  
       9:          vColor = aVertexColor;  
      10:      }  
      11:  </script> 

    第2、6、9行为新增的内容。

    Fragment:

       1:  <script id="shader-fs" type="x-shader/x-fragment">  
       2:      varying lowp vec4 vColor;
       3:      void main(void) {  
       4:          gl_FragColor = vColor;  
       5:      }  
       6:  </script>

    第2行为新增,第4行原来为定值。

    以上script中的代码主要是为了便于对比查看。还是延续上一篇的做法,本例直接将代码赋值到js变量中:

    var testVertexCode = '\
        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;\
        }',
        testFragmentCode = '\
        varying lowp vec4 vColor;\
        void main(void){\
            gl_FragColor=vColor;\
        }';

    以下为流水账:

    1、创建Shader对象

    var vertShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertShader, testVertexCode);
    gl.compileShader(vertShader);
     
    var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragShader, testFragmentCode);
    gl.compileShader(fragShader);

    2、创建Program对象并附加Shader

    var program = gl.createProgram();
    gl.attachShader(program, vertShader);
    gl.attachShader(program, fragShader);

    3、引用Program对象

    gl.linkProgram(program);
    gl.useProgram(program);

    4、关联gl与Shader脚本中的变量

    var vertexPosAttr = gl.getAttribLocation(program, 'aVertexPosition');
    gl.enableVertexAttribArray(vertexPosAttr);
     
    var colorPosAttr = gl.getAttribLocation(program, 'aVertexColor');
    gl.enableVertexAttribArray(colorPosAttr);

    上面这一步在撰写本文例子的时候又有点新的心得。getAttribLocation方法的第二个参数对应Shader脚本中已定义的变量名,自己则返回一个int值,根据名称猜测,该返回值应该是变量句柄之类的东西。enableVertexAttribArray方法应该是根据这个句柄来启用WebGL和Shader之间的某种关联关系。

    二、创建定点及颜色

    本例需要一组顶点数据和一组颜色数据,如下:

    var vertices = [  
         1.0,   1.0,   0.0,  
        -1.0,   1.0,   0.0,  
         1.0,  -1.0,   0.0,  
        -1.0,  -1.0,   0.0
    ];
    var colors = [  
        1.0,  1.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  
    ];

    下面将它们附加到gl中:

    var squareVerticesBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    gl.vertexAttribPointer(vertexPosAttr, 3, gl.FLOAT, false, 0, 0);
     
    var squareVerticesColorBuffer = gl.createBuffer();  
    gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer);  
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); 
    gl.vertexAttribPointer(colorPosAttr, 4, gl.FLOAT, false, 0, 0); 

    请注意vertexAttribPointer方法的第2个参数,单个定点(XYZ)定义为3个float值,单个色彩(RGBA)定义为4个float值,上次提到,貌似这个参数应为分组数据的个数。

    三、设置位置

    再赘述一下MatrixHelper对象:

    function MatrixHelper(){ this.matrix = Matrix.I(4); }
    MatrixHelper.prototype = {
        /* makePerspective */
        make : function(fovy, aspect, znear, zfar){
            this.ppm = makePerspective(fovy, aspect, znear, zfar);
        },
        /* multMatrix */
        mult : function(m){
            this.matrix = this.matrix.x(m);
        },
        /* mvTranslate */
        trans : function(v){
            this.mult(Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4());
        },
        /* setMatrixUniforms */
        set : function(gl, sProg){
            if(!!this.ppm){
                  gl.uniformMatrix4fv(gl.getUniformLocation(sProg, "uPMatrix")
                    , false, new Float32Array(this.ppm.flatten()));
            }
            if(!!this.matrix){
                  gl.uniformMatrix4fv(gl.getUniformLocation(sProg, "uMVMatrix")
                    , false, new Float32Array(this.matrix.flatten())); 
            }
        }
    }

    设置位置之前,需要在页头中引用MDN提供的两个包,我已上传到我的空间里:

    sylvester.js

    glUtils.js

    这两个文件会提供一个Matrix对象来简化位置状态的设置,MatrixHelper只是重新封装了一下,下面使用它设置位置:

    var matrix = new MatrixHelper();
    matrix.trans([0.0, 0.0, -5.0]);
    matrix.make(45, 640 / 480, 0.1, 100.0);
    matrix.set(gl, program);

    四、绘制

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

    好了,大功告成。不出意外的话,你的屏幕上应该出现类似下图的内容:

    捕获

    好像有点意思了,至少比一个白方块强哈。本文与上一篇相比没有太多新东西。附代码:

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>WebGL Step 02</title>
    <style type="text/css">
    canvas{ background-color:#666; }
    </style>
    <script type="text/ecmascript" src="sylvester.js"></script>
    <script type="text/ecmascript" src="glUtils.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> 
     
    <script type="text/ecmascript">
    function MatrixHelper(){ this.matrix = Matrix.I(4); }
    MatrixHelper.prototype = {
        /* makePerspective */
        make : function(fovy, aspect, znear, zfar){
            this.ppm = makePerspective(fovy, aspect, znear, zfar);
        },
        /* multMatrix */
        mult : function(m){
            this.matrix = this.matrix.x(m);
        },
        /* mvTranslate */
        trans : function(v){
            this.mult(Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4());
        },
        /* setMatrixUniforms */
        set : function(gl, sProg){
            if(!!this.ppm){
                  gl.uniformMatrix4fv(gl.getUniformLocation(sProg, "uPMatrix")
                    , false, new Float32Array(this.ppm.flatten()));
            }
            if(!!this.matrix){
                  gl.uniformMatrix4fv(gl.getUniformLocation(sProg, "uMVMatrix")
                    , false, new Float32Array(this.matrix.flatten())); 
            }
        }
    }
    </script>
     
    </head>
     
    <body>
     
    <canvas id="glcanvas" width="640" height="480">看来您的浏览器不支持<code>&lt;canvas&gt;</code>标记</canvas>
     
    <script type="text/ecmascript">
    var testVertexCode = '\
        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;\
        }',
        testFragmentCode = '\
        varying lowp vec4 vColor;\
        void main(void){\
            gl_FragColor=vColor;\
        }';
        
    var vertices = [  
         1.0,   1.0,   0.0,  
        -1.0,   1.0,   0.0,  
         1.0,  -1.0,   0.0,  
        -1.0,  -1.0,   0.0
    ];
    var colors = [  
        1.0,  1.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  
    ];
          
    var canvas = document.getElementById('glcanvas');
    var gl = canvas.getContext('experimental-webgl');
     
    var vertShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertShader, testVertexCode);
    gl.compileShader(vertShader);
     
    var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragShader, testFragmentCode);
    gl.compileShader(fragShader);
     
    var program = gl.createProgram();
    gl.attachShader(program, vertShader);
    gl.attachShader(program, fragShader);
     
    gl.linkProgram(program);
    gl.useProgram(program);
     
    var vertexPosAttr = gl.getAttribLocation(program, 'aVertexPosition');
    gl.enableVertexAttribArray(vertexPosAttr);
     
    var colorPosAttr = gl.getAttribLocation(program, 'aVertexColor');
    gl.enableVertexAttribArray(colorPosAttr);
     
    var squareVerticesBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    gl.vertexAttribPointer(vertexPosAttr, 3, gl.FLOAT, false, 0, 0);
     
    var squareVerticesColorBuffer = gl.createBuffer();  
    gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer);  
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); 
    gl.vertexAttribPointer(colorPosAttr, 4, gl.FLOAT, false, 0, 0); 
     
    var matrix = new MatrixHelper();
    matrix.trans([0.0, 0.0, -5.0]);
    matrix.make(40, 640 / 480, 0.1, 100.0);
    matrix.set(gl, program);
     
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
     
    </script>
    </body>
    </html>

    代码中装载Shaper脚本的script标记只是为了方便观瞻,不必纠结。

  • 相关阅读:
    jsbeautifier + JScript.NET/JavaScript 编程实现 JavaScript、HTML、CSS 代码格式化脚本命令行工具 并集成到 EditPlus
    EasyTimer
    HttpTaskAsyncHandler IHttpAsyncHandler
    ConcurrentAsyncQueue 20120721
    HttpProxyHandler
    SocketAsyncDataHandler SocketAsyncEventArgs echo server
    DateTimeHelper R2
    managedwifi.codeplex.com
    最广泛报表数据源模型
    报表的发布
  • 原文地址:https://www.cnblogs.com/muse/p/2269346.html
Copyright © 2011-2022 走看看