WebGL+JS流程

1.body中定义canvas元素 onload()function

引入的js

<script type="text/javascript" src="glMatrix-0.9.5.min.js"></script>
<script type="text/javascript" src="webgl-utils.js"></script>

声明onload()

<body onload="webGLStart()">
<canvas id="tooth-canvas" style="border: none" width="500" height="500"></canvas>
</body>

2.onload预加载函数

 function webGLStart() {
        var canvas = document.getElementById("tooth-canvas");
        //插入GL
        initGL(canvas);
        //插入shader
        initShaders();
        //插入buffer数据
        initBuffers();

        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);

//     This is the function that needs to be called regularly; it updates the scene’s animation state
// (eg. the triangle has moved from being 81 degrees rotated to 82 degrees) draws the scene,
// and also arranges for itself to be called again in an appropriate time
// . It’s the next function up in the file, so let’s look at it next.function tick() {
//        requestAnimFrame(tick);

        //函数需要经常被调用,它更新scene的动画状态(比如,三角形从81度旋转到82度)绘制scene  同时准备被随时调用
        tick();
    }

3.插入GL

 function initGL(canvas) {
        try {
            //获取上下文固定语句  否则会报错。
            gl = canvas.getContext("experimental-webgl");
            gl.viewportWidth = canvas.width;
            gl.viewportHeight = canvas.height;
        } catch (e) {

        }
        if (!gl) {
            alert("Could not initialise WegGL");
        }

    }

4.插入shader

1.定义shader
(1)fragment shader

<script id="shader-fs" type="x-shader/x-fragment">


    precision mediump float;

    varying vec4 vColor;

    void main(void) {
        gl_FragColor = vColor;
    }
</script>

(2)vertex shader

vertet attribute uniform varying 三种变量的声明:
http://blog.csdn.net/me_badman/article/details/56272803

<script id="shader-vs" type="x-shader/x-vertex">

    attribute vec3 aVertexPosition;
    attribute vec4 aVertexColor;
    //model view矩阵 projection矩阵(投影矩阵)
    uniform mat4 uMVMatrix;
    uniform mat4 uPMatrix;

    varying vec4 vColor;

    void main(void) {
    //准备好模型 视图坐标变换,投影坐标变换的各个矩阵。再具体一点,就是准备好各种坐标变换的矩阵,然后
    //相乘。将最终得到的矩阵传给WebGL的顶点着色器。
        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
        vColor = aVertexColor;
    }
</script>

2.gl中获取shader

//获取shader
    function getShader(gl, id) {
        var shaderScript = document.getElementById(id);
        if (!shaderScript) {
            return null;
        }

        var str = "";
        var k = shaderScript.firstChild;
        while (k) {
            if (k.nodeType == 3) {
                str += k.textContent;
            }
            k = k.nextSibling;
        }

        var shader;
        if (shaderScript.type == "x-shader/x-fragment") {
            shader = gl.createShader(gl.FRAGMENT_SHADER);
        } else if (shaderScript.type == "x-shader/x-vertex") {
            shader = gl.createShader(gl.VERTEX_SHADER);
        } else {
            return null;
        }
        //shaderSource
        gl.shaderSource(shader, str);
        //完成getShader()
        gl.compileShader(shader);
        //没有完成
        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            //打印出错误信息
            alert(gl.getShaderInfoLog(shader));
            return null;
        }
        return shader;
    }

3.插入shader

var shaderProgram;

    function initShaders() {
        var fragmentShader = getShader(gl, "shader-fs");
        var vertexShader = getShader(gl, "shader-vs");

        shaderProgram = gl.createProgram();
        //给shaderProgram连接shader
        gl.attachShader(shaderProgram,vertexShader);
        gl.attachShader(shaderProgram,fragmentShader);
        //gl连接program
        gl.linkProgram(shaderProgram);

        if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)){
            alert("Could not initialise shaders");
        }
        //使用Program
        gl.useProgram(shaderProgram);
        //声明progarm 的position和color属性  =gl.getAttribLocation(shaderProgram, vertex - shader的aVertexPosition aVertexColor)属性
        shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
        gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

        shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
        gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);

        shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
        shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");

    }

5.插入buffer数据

主函数

    //三角形position
    var triangleVertexPositionBuffer;
    //三角形color
    var triangleVertexColorBuffer;
    //四边形position
    var squareVertexPositionBuffer;
    //四边形color
    var squareVertexColorBuffer;

    function initBuffers() {
        //创建gl的buffer空间
        triangleVertexPositionBuffer = gl.createBuffer();
        //给gl绑定buffer
        gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
        var vertices = [
            0.0,  1.0,  0.0,    //顶点
            -1.0, -1.0,  0.0,   //左下角
            1.0, -1.0,  0.0     //右下角
        ];
        //bufferData(1.array,vertices顶点数据,gl.STATIC_DRAW)
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
        //列和行
        triangleVertexPositionBuffer.itemSize = 3;
        triangleVertexPositionBuffer.numItems = 3;

        triangleVertexColorBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
        var colors = [
            //rgba  a:透明度 opacity
            1.0, 0.0, 0.0, 1.0, //红
            0.0, 1.0, 0.0, 1.0, //绿
            0.0, 0.0, 1.0, 1.0, //蓝
        ];
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
        //列和行
        triangleVertexColorBuffer.itemSize = 4;
        triangleVertexColorBuffer.numItems = 3;


        squareVertexPositionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
        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
        ];
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
        squareVertexPositionBuffer.itemSize = 3;
        squareVertexPositionBuffer.numItems = 4;

        squareVertexColorBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
        colors = []
        for (var i=0; i < 4; i++) {
            colors = colors.concat([0.5, 0.5, 1.0, 1.0]);
        }
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
        squareVertexColorBuffer.itemSize = 4;
        squareVertexColorBuffer.numItems = 4;
    }

6.绘制scene和animotion

1.tick()函数

 function tick() {
        //requestAnimFrame is a function in some Google-provided code that we’re including
        // into this web page with a <script> tag at the top, webgl-utils.js.
        // It gives us a browser-independent way of asking the browser to call us back next time it wants to repaint the
        // WebGL scene — for example, next time the computer’s display is refreshing itself.
        //requestAnimFrame是一个函数在页面中包含了 <script> webgl-utils.js标签的Google-provided代码
        //独立于浏览器 要求浏览器返回下次WebGL的场景  支持所有浏览器
        requestAnimFrame(tick);
        drawScene();
        animate();
    }

2.在drawScene之前 定义一些变量、方法

    var mvMatrix = mat4.create();//创建一个model-view  4*4矩阵
    var mvMatrixStack = [];//创建一个栈放入mv copy矩阵
    var pMatrix = mat4.create();//4*4矩阵

    function mvPushMatrix() {
        var copy = mat4.create();//创建一个4*4矩阵
        mat4.set(mvMatrix, copy);//Sets the values of this matrix to those of the specified matrix.
                                    //将mv矩阵值赋予新的copy矩阵中
        mvMatrixStack.push(copy);//将copy的矩阵放到栈中
    }

    function mvPopMatrix() {
        if (mvMatrixStack.length == 0) {
            throw "Invalid popMatrix!";
        }
        mvMatrix = mvMatrixStack.pop();//取出栈顶的元素
    }

    //设置全局的矩阵  在这里 将shaderProgram的值给mv矩阵和p矩阵
    function setMatrixUniforms() {
        //将创建的pMatrix矩阵给 设置的shaderProgram.pMatrixUniform全局矩阵
        gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
        gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
    }
    //红色的旋转度数
    function degToRad(degrees) {
        return degrees * Math.PI / 180;
    }
//定义两个变量(三角形度数和四边形度数)  matrix根据其值  旋转(rotate)
    var rTri = 0;
    var rSquare = 0;

3.drawScene

function drawScene() {
        //gl以(0,0)开始整个canvas的大小
        gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
        //clear表示要清除的缓冲区   color depth   清楚颜色和深度缓冲区
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        //透视投影
        //mat4.perspective=function(a,b,c,d,e){a=c*Math.tan(a*Math.PI/360);b=a*b;return                  //        mat4.frustum(-b,b,-a,a,c,d,e)}

        //mat4.frustum=function(a,b,c,d,e,g,f){
        // f||(f=mat4.create());
        // var h=b-a,i=d-c,j=g-e;
        // f[0]=e*2/h;f[1]=0;f[2]=0;f[3]=0;f[4]=0;f[5]=e*2/i;f[6]=0;f[7]=0;
        // f[8]=(b+a)/h;f[9]=(d+c)/i;f[10]=-(g+e)/j;f[11]=-1;f[12]=0;f[13]=0;f[14]=-(g*e*2)/j;f[15]=0;return f}
        mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);

        mat4.identity(mvMatrix);

//        mvPushMatrix puts the matrix onto a stack, and mvPopMatrix gets rid of the current matrix,
//            takes one from the top of the stack, and restores it.
//            Using a stack means that we can have any number of bits of nested drawing code,
//            each of which manipulates the model-view matrix and then restores it afterwards.
//            So once we’ve finished drawing our rotated triangle,
//            we restore the model-view matrix with mvPopMatrix so that this code:
//            mat4.translate(mvMatrix, [-1.5, 0.0, -7.0]);

//        mvPushMatrix 将mvmatrix   copy并放到栈上,mvPopMatrix摆脱当前矩阵,从栈顶获取出
//        mvPushMatrix()放入栈之后进行旋转 绑定等操作  结束后mvPopMatrix从栈顶取出

        //变换坐标原点   tarnslate(mvMatrix,[x,y,scale])
        mat4.translate(mvMatrix, [-1.5, 0.0, -7.0]);

        mvPushMatrix();
        //改变当前状态时,model-view矩阵根据rTri度数旋转
        //degToRad(degree) 是将角度转换为弧度。
        //第一个参数  mv矩阵  第二个参数 弧度(角度) 第三个参数旋转围绕的垂直轴(y轴)
        mat4.rotate(mvMatrix, degToRad(rTri), [0, 1, 0]);
        //triangleVertexPositionBuffer顶点position的buffer
        //triangleVertexColorBuffer顶点color的buffer
        //绑定buffer中vertexPositionAttribute的数据并传给shaderProgram.vertexPositionAttribute shaderProgram.vertexColorAttribute
        //即给vertex-shader中的aVertexPosition    aVertexColor赋值
        gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
        gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

        gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
        gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, triangleVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
        //设置全局矩阵 shaderProgram.pMatrixUniform shaderProgram.pMatrixUniform
        setMatrixUniforms();
        gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);
        mvPopMatrix();

        mat4.translate(mvMatrix, [3.0, 0.0, 0.0]);

        mvPushMatrix();
        //改变当前状态时,model-view矩阵根据rSquare
        mat4.rotate(mvMatrix, degToRad(rSquare), [0, 1, 0]);

        gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
        gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

        gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
        gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, squareVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);

        setMatrixUniforms();
        gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);

        mvPopMatrix();
    }

4.根据animate函数改变定义的角度的值

 var lastTime = 0;
    //根据时间改变 角度
    function animate() {
        var timeNow = new Date().getTime();
        if (lastTime != 0) {
            var elapsed = timeNow - lastTime;

            rTri += (90 * elapsed) / 1000.0;
            rSquare += (75 * elapsed) / 1000.0;
        }
        lastTime = timeNow;
    }

示例来源:http://learningwebgl.com/blog/?p=239

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值