WebGl - 只能绘制一个对象

发布于 2024-10-31 04:27:37 字数 20777 浏览 7 评论 0原文

我正在尝试编写一个立方体函数来从这个 示例 - 为什么当我多次调用 makeCube() 函数时只显示一个多维数据集。当我做推/弹出矩阵时,我有一种预感会发生一些奇怪的事情。我是 webgl 的新手,已经使用 canvas2d 编写了一个游戏,并且想使用网络浏览器进入 opengl。帮助!我保证你可以测试我的第一个 3d 游戏我做错了什么? (我的代码出现在下面)

        <html> 

        <head> 
        <title>Learning WebGL &mdash; lesson 4</title> 
        <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> 

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

        <script id="shader-fs" type="x-shader/x-fragment"> 
            #ifdef GL_ES
            precision highp float;
            #endif

            varying vec4 vColor;

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

        <script id="shader-vs" type="x-shader/x-vertex"> 
            attribute vec3 aVertexPosition;
            attribute vec4 aVertexColor;

            uniform mat4 uMVMatrix;
            uniform mat4 uPMatrix;

            varying vec4 vColor;

            void main(void) {
                gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
                vColor = aVertexColor;
            }
        </script> 


        <script type="text/javascript"> 

            var 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 WebGL, sorry :-(");
                }
            }


            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;
                }

                gl.shaderSource(shader, str);
                gl.compileShader(shader);

                if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
                    alert(gl.getShaderInfoLog(shader));
                    return null;
                }

                return shader;
            }

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

                shaderProgram = gl.createProgram();
                gl.attachShader(shaderProgram, vertexShader);
                gl.attachShader(shaderProgram, fragmentShader);
                gl.linkProgram(shaderProgram);

                if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
                    alert("Could not initialise shaders");
                }

                gl.useProgram(shaderProgram);

                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");
            }

            var mvMatrix = mat4.create();
            var mvMatrixStack = [];
            var pMatrix = mat4.create();

            function mvPushMatrix() {
                var copy = mat4.create();
                mat4.set(mvMatrix, copy);
                mvMatrixStack.push(copy);
            }

            function mvPopMatrix() {
                if (mvMatrixStack.length == 0) {
                    throw "Invalid popMatrix!";
                }
                mvMatrix = mvMatrixStack.pop();
            }

            function setMatrixUniforms() {
                gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
                gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
            }


            function degToRad(degrees) {
                return degrees * Math.PI / 180;
            }


            var pyramidVertexPositionBuffer;
            var pyramidVertexColorBuffer;
            var cubeVertexPositionBuffer;
            var cubeVertexColorBuffer;
            var cubeVertexIndexBuffer;

            function initBuffers() {
                pyramidVertexPositionBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexPositionBuffer);
                var vertices = [
                    // Front face
                     0.0,  1.0,  0.0,
                    -1.0, -1.0,  1.0,
                     1.0, -1.0,  1.0,

                    // Right face
                     0.0,  1.0,  0.0,
                     1.0, -1.0,  1.0,
                     1.0, -1.0, -1.0,

                    // Back face
                     0.0,  1.0,  0.0,
                     1.0, -1.0, -1.0,
                    -1.0, -1.0, -1.0,

                    // Left face
                     0.0,  1.0,  0.0,
                    -1.0, -1.0, -1.0,
                    -1.0, -1.0,  1.0
                ];
                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
                pyramidVertexPositionBuffer.itemSize = 3;
                pyramidVertexPositionBuffer.numItems = 12;

                pyramidVertexColorBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexColorBuffer);
                var colors = [
                    // Front face
                    1.0, 0.0, 0.0, 1.0,
                    0.0, 1.0, 0.0, 1.0,
                    0.0, 0.0, 1.0, 1.0,

                    // Right face
                    1.0, 0.0, 0.0, 1.0,
                    0.0, 0.0, 1.0, 1.0,
                    0.0, 1.0, 0.0, 1.0,

                    // Back face
                    1.0, 0.0, 0.0, 1.0,
                    0.0, 1.0, 0.0, 1.0,
                    0.0, 0.0, 1.0, 1.0,

                    // Left face
                    1.0, 0.0, 0.0, 1.0,
                    0.0, 0.0, 1.0, 1.0,
                    0.0, 1.0, 0.0, 1.0
                ];
                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
                pyramidVertexColorBuffer.itemSize = 4;
                pyramidVertexColorBuffer.numItems = 12;


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

                cubeVertexColorBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer);
                colors = [
                    [1.0, 0.0, 0.0, 1.0], // Front face
                    [1.0, 1.0, 0.0, 1.0], // Back face
                    [0.0, 1.0, 0.0, 1.0], // Top face
                    [1.0, 0.5, 0.5, 1.0], // Bottom face
                    [1.0, 0.0, 1.0, 1.0], // Right face
                    [0.0, 0.0, 1.0, 1.0]  // Left face
                ];
                var unpackedColors = [];
                for (var i in colors) {
                    var color = colors[i];
                    for (var j=0; j < 4; j++) {
                        unpackedColors = unpackedColors.concat(color);
                    }
                }
                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColors), gl.STATIC_DRAW);
                cubeVertexColorBuffer.itemSize = 4;
                cubeVertexColorBuffer.numItems = 24;

                cubeVertexIndexBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
                var cubeVertexIndices = [
                    0, 1, 2,      0, 2, 3,    // Front face
                    4, 5, 6,      4, 6, 7,    // Back face
                    8, 9, 10,     8, 10, 11,  // Top face
                    12, 13, 14,   12, 14, 15, // Bottom face
                    16, 17, 18,   16, 18, 19, // Right face
                    20, 21, 22,   20, 22, 23  // Left face
                ];
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
                cubeVertexIndexBuffer.itemSize = 1;
                cubeVertexIndexBuffer.numItems = 36;
            }


            var rPyramid = 0;
            var rCube = 0;

            function drawScene() {
              gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
              gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

              mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);

              mat4.identity(mvMatrix);

              mat4.translate(mvMatrix, [-1.5, 0.0, -8.0]);



              mvPushMatrix();
              mat4.rotate(mvMatrix, degToRad(rPyramid), [0, 1, 0]);

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

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

              setMatrixUniforms();
              gl.drawArrays(gl.TRIANGLES, 0, pyramidVertexPositionBuffer.numItems);

              mvPopMatrix();


              makeCube(
                 {'r':0.3,'g':0.3,'b':0.87,'a':1.0},  // color
                 {'x':3.5,'y':1.0,'z':2.0},       // position
                 {'x':0.0,'y':0.0,'z':0.0},       // rotation
                 0.5                     // length
              );
               makeCube(
                 {'r':0.9,'g':0.7,'b':0.17,'a':1.0},  // color
                 {'x':3.5,'y':1.0,'z':2.0},       // position
                 {'x':0.0,'y':0.0,'z':0.0},       // rotation
                 0.5                     // length
              );
               makeCube(
                 {'r':0.3,'g':0.3,'b':0.87,'a':1.0},  // color
                 {'x':3.5,'y':1.0,'z':2.0},       // position
                 {'x':0.0,'y':0.0,'z':0.0},       // rotation
                 0.1                     // length
              );
               makeCube(
                 {'r':0.3,'g':0.5,'b':0.87,'a':1.0},  // color
                 {'x':0.5,'y':3.0,'z':12.0},       // position
                 {'x':0.0,'y':0.0,'z':0.0},       // rotation
                 0.8                     // length
              );
               makeCube(
                 {'r':0.5,'g':0.3,'b':0.87,'a':1.0},  // color
                 {'x':0.1,'y':-3.0,'z':5.0},       // position
                 {'x':0.0,'y':0.0,'z':0.0},       // rotation
                 0.4                     // length
              );
            }

           var oCubeColorBuffer = null;
           function _makeCubeColorBuffer(aColor){


               oCubeColorBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ARRAY_BUFFER, oCubeColorBuffer);
                var aColors = [
                    [aColor.r, aColor.g, aColor.b, aColor.a], // Front face
                    [aColor.r, aColor.g, aColor.b, aColor.a], // Back face
                    [aColor.r, aColor.g, aColor.b, aColor.a], // Top face
                    [aColor.r, aColor.g, aColor.b, aColor.a], // Bottom face
                    [aColor.r, aColor.g, aColor.b, aColor.a], // Right face
                    [aColor.r, aColor.g, aColor.b, aColor.a]  // Left face
                ];
                var unpackedColors = [];
                for (var i in aColors) {
                    var color = aColors[i];
                    for (var j=0; j < 4; j++) {
                        unpackedColors = unpackedColors.concat(color);
                    }
                }
                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColors), gl.STATIC_DRAW);
                oCubeColorBuffer.itemSize = 4;
                oCubeColorBuffer.numItems = 24;        

              return oCubeColorBuffer;
           }

           var oCubePositionBuffer = null;    
           function _makeCubePositionBuffer(fLength){


              oCubePositionBuffer = gl.createBuffer();
              gl.bindBuffer(gl.ARRAY_BUFFER, oCubePositionBuffer);
              var aVertices = [
                 // Front face
                 -1.0*fLength, -1.0*fLength,  1.0*fLength,
                  1.0*fLength, -1.0*fLength,  1.0*fLength,
                  1.0*fLength,  1.0*fLength,  1.0*fLength,
                 -1.0*fLength,  1.0*fLength,  1.0*fLength,

                 // Back face
                 -1.0*fLength, -1.0*fLength, -1.0*fLength,
                 -1.0*fLength,  1.0*fLength, -1.0*fLength,
                  1.0*fLength,  1.0*fLength, -1.0*fLength,
                  1.0*fLength, -1.0*fLength, -1.0*fLength,

                 // Top face
                 -1.0*fLength,  1.0*fLength, -1.0*fLength,
                 -1.0*fLength,  1.0*fLength,  1.0*fLength,
                  1.0*fLength,  1.0*fLength,  1.0*fLength,
                  1.0*fLength,  1.0*fLength, -1.0*fLength,

                 // Bottom face
                 -1.0*fLength, -1.0*fLength, -1.0*fLength,
                  1.0*fLength, -1.0*fLength, -1.0*fLength,
                  1.0*fLength, -1.0*fLength,  1.0*fLength,
                 -1.0*fLength, -1.0*fLength,  1.0*fLength,

                 // Right face
                  1.0*fLength, -1.0*fLength, -1.0*fLength,
                  1.0*fLength,  1.0*fLength, -1.0*fLength,
                  1.0*fLength,  1.0*fLength,  1.0*fLength,
                  1.0*fLength, -1.0*fLength,  1.0*fLength,

                 // Left face
                 -1.0*fLength, -1.0*fLength, -1.0*fLength,
                 -1.0*fLength, -1.0*fLength,  1.0*fLength,
                 -1.0*fLength,  1.0*fLength,  1.0*fLength,
                 -1.0*fLength,  1.0*fLength, -1.0*fLength
              ];
              gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(aVertices), gl.STATIC_DRAW);
              oCubePositionBuffer.itemSize = 3;
              oCubePositionBuffer.numItems = 24;

              return oCubePositionBuffer;
           }

          var oCubeIndexBuffer = null;   
           function _makeCubeVertexIndexBuffer(){

                oCubeIndexBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, oCubeIndexBuffer);
                var cubeVertexIndices = [
                    0, 1, 2,      0, 2, 3,    // Front face
                    4, 5, 6,      4, 6, 7,    // Back face
                    8, 9, 10,     8, 10, 11,  // Top face
                    12, 13, 14,   12, 14, 15, // Bottom face
                    16, 17, 18,   16, 18, 19, // Right face
                    20, 21, 22,   20, 22, 23  // Left face
                ];
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
                oCubeIndexBuffer.itemSize = 1;
                oCubeIndexBuffer.numItems = 36;      
              return oCubeIndexBuffer;
           }





           function makeCube(aColor, aPosition, aRotation, fLength){
                 mvPushMatrix();
                mat4.translate(mvMatrix, [aPosition.x, aPosition.y, aPosition.z]);

               // mat4.rotate(mvMatrix, degToRad(rCube), [aRotation.x, aRotation.y, aRotation.z]);

                var oCubeVertexPositionBuffer = _makeCubePositionBuffer(fLength);
                gl.bindBuffer(gl.ARRAY_BUFFER, oCubeVertexPositionBuffer);
                gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, oCubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

                var oCubeVertexColorBuffer = _makeCubeColorBuffer(aColor);
                gl.bindBuffer(gl.ARRAY_BUFFER, oCubeVertexColorBuffer);
                gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, oCubeVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);

                var oCubeVertexIndexBuffer = _makeCubeVertexIndexBuffer();
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, oCubeVertexIndexBuffer);
                setMatrixUniforms();
                gl.drawElements(gl.TRIANGLES, oCubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

                mvPopMatrix();

           }





            var lastTime = 0;

            function animate() {
                var timeNow = new Date().getTime();
                if (lastTime != 0) {
                    var elapsed = timeNow - lastTime;

                    rPyramid += (90 * elapsed) / 1000.0;
                    rCube -= (75 * elapsed) / 1000.0;
                }
                lastTime = timeNow;
            }


            function tick() {
                requestAnimFrame(tick);
                drawScene();
                animate();
            }


            function webGLStart() {
                var canvas = document.getElementById("lesson04-canvas");
                initGL(canvas);
                initShaders()
                initBuffers();

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

                tick();
            }

        </script> 


        </head> 


        <body onload="webGLStart();"> 
            <a href="http://learningwebgl.com/blog/?p=370">&lt;&lt; Back to Lesson 4</a><br /> 

            <canvas id="lesson04-canvas" style="border: none;" width="500" height="500"></canvas> 

            <br/> 
            <a href="http://learningwebgl.com/blog/?p=370">&lt;&lt; Back to Lesson 4</a><br /> 

            <!-- Google Analytics stuff, please ignore - nothing to do with WebGL :-) --> 
            <script type="text/javascript"> 
                var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
                document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
            </script> 
            <script type="text/javascript"> 
                try {
                    var pageTracker = _gat._getTracker("UA-2240015-5");
                    pageTracker._trackPageview();
                } catch(err) {
                }
            </script> 

        </body> 

        </html> 

I'm trying to write a cube function to fork off from this example - why does only one cube show up when I've made several calls to my makeCube() function. I have a hunch something weird is going on with when I do push/pop matrix. I'm a new to webgl and have written a game already using canvas2d and would like to break into opengl with a web browser. Help! I promise you can beta test my 1st 3d game What am I doing wrong? (my code appears below)

        <html> 

        <head> 
        <title>Learning WebGL — lesson 4</title> 
        <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> 

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

        <script id="shader-fs" type="x-shader/x-fragment"> 
            #ifdef GL_ES
            precision highp float;
            #endif

            varying vec4 vColor;

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

        <script id="shader-vs" type="x-shader/x-vertex"> 
            attribute vec3 aVertexPosition;
            attribute vec4 aVertexColor;

            uniform mat4 uMVMatrix;
            uniform mat4 uPMatrix;

            varying vec4 vColor;

            void main(void) {
                gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
                vColor = aVertexColor;
            }
        </script> 


        <script type="text/javascript"> 

            var 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 WebGL, sorry :-(");
                }
            }


            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;
                }

                gl.shaderSource(shader, str);
                gl.compileShader(shader);

                if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
                    alert(gl.getShaderInfoLog(shader));
                    return null;
                }

                return shader;
            }

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

                shaderProgram = gl.createProgram();
                gl.attachShader(shaderProgram, vertexShader);
                gl.attachShader(shaderProgram, fragmentShader);
                gl.linkProgram(shaderProgram);

                if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
                    alert("Could not initialise shaders");
                }

                gl.useProgram(shaderProgram);

                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");
            }

            var mvMatrix = mat4.create();
            var mvMatrixStack = [];
            var pMatrix = mat4.create();

            function mvPushMatrix() {
                var copy = mat4.create();
                mat4.set(mvMatrix, copy);
                mvMatrixStack.push(copy);
            }

            function mvPopMatrix() {
                if (mvMatrixStack.length == 0) {
                    throw "Invalid popMatrix!";
                }
                mvMatrix = mvMatrixStack.pop();
            }

            function setMatrixUniforms() {
                gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
                gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
            }


            function degToRad(degrees) {
                return degrees * Math.PI / 180;
            }


            var pyramidVertexPositionBuffer;
            var pyramidVertexColorBuffer;
            var cubeVertexPositionBuffer;
            var cubeVertexColorBuffer;
            var cubeVertexIndexBuffer;

            function initBuffers() {
                pyramidVertexPositionBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexPositionBuffer);
                var vertices = [
                    // Front face
                     0.0,  1.0,  0.0,
                    -1.0, -1.0,  1.0,
                     1.0, -1.0,  1.0,

                    // Right face
                     0.0,  1.0,  0.0,
                     1.0, -1.0,  1.0,
                     1.0, -1.0, -1.0,

                    // Back face
                     0.0,  1.0,  0.0,
                     1.0, -1.0, -1.0,
                    -1.0, -1.0, -1.0,

                    // Left face
                     0.0,  1.0,  0.0,
                    -1.0, -1.0, -1.0,
                    -1.0, -1.0,  1.0
                ];
                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
                pyramidVertexPositionBuffer.itemSize = 3;
                pyramidVertexPositionBuffer.numItems = 12;

                pyramidVertexColorBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexColorBuffer);
                var colors = [
                    // Front face
                    1.0, 0.0, 0.0, 1.0,
                    0.0, 1.0, 0.0, 1.0,
                    0.0, 0.0, 1.0, 1.0,

                    // Right face
                    1.0, 0.0, 0.0, 1.0,
                    0.0, 0.0, 1.0, 1.0,
                    0.0, 1.0, 0.0, 1.0,

                    // Back face
                    1.0, 0.0, 0.0, 1.0,
                    0.0, 1.0, 0.0, 1.0,
                    0.0, 0.0, 1.0, 1.0,

                    // Left face
                    1.0, 0.0, 0.0, 1.0,
                    0.0, 0.0, 1.0, 1.0,
                    0.0, 1.0, 0.0, 1.0
                ];
                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
                pyramidVertexColorBuffer.itemSize = 4;
                pyramidVertexColorBuffer.numItems = 12;


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

                cubeVertexColorBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer);
                colors = [
                    [1.0, 0.0, 0.0, 1.0], // Front face
                    [1.0, 1.0, 0.0, 1.0], // Back face
                    [0.0, 1.0, 0.0, 1.0], // Top face
                    [1.0, 0.5, 0.5, 1.0], // Bottom face
                    [1.0, 0.0, 1.0, 1.0], // Right face
                    [0.0, 0.0, 1.0, 1.0]  // Left face
                ];
                var unpackedColors = [];
                for (var i in colors) {
                    var color = colors[i];
                    for (var j=0; j < 4; j++) {
                        unpackedColors = unpackedColors.concat(color);
                    }
                }
                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColors), gl.STATIC_DRAW);
                cubeVertexColorBuffer.itemSize = 4;
                cubeVertexColorBuffer.numItems = 24;

                cubeVertexIndexBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
                var cubeVertexIndices = [
                    0, 1, 2,      0, 2, 3,    // Front face
                    4, 5, 6,      4, 6, 7,    // Back face
                    8, 9, 10,     8, 10, 11,  // Top face
                    12, 13, 14,   12, 14, 15, // Bottom face
                    16, 17, 18,   16, 18, 19, // Right face
                    20, 21, 22,   20, 22, 23  // Left face
                ];
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
                cubeVertexIndexBuffer.itemSize = 1;
                cubeVertexIndexBuffer.numItems = 36;
            }


            var rPyramid = 0;
            var rCube = 0;

            function drawScene() {
              gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
              gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

              mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);

              mat4.identity(mvMatrix);

              mat4.translate(mvMatrix, [-1.5, 0.0, -8.0]);



              mvPushMatrix();
              mat4.rotate(mvMatrix, degToRad(rPyramid), [0, 1, 0]);

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

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

              setMatrixUniforms();
              gl.drawArrays(gl.TRIANGLES, 0, pyramidVertexPositionBuffer.numItems);

              mvPopMatrix();


              makeCube(
                 {'r':0.3,'g':0.3,'b':0.87,'a':1.0},  // color
                 {'x':3.5,'y':1.0,'z':2.0},       // position
                 {'x':0.0,'y':0.0,'z':0.0},       // rotation
                 0.5                     // length
              );
               makeCube(
                 {'r':0.9,'g':0.7,'b':0.17,'a':1.0},  // color
                 {'x':3.5,'y':1.0,'z':2.0},       // position
                 {'x':0.0,'y':0.0,'z':0.0},       // rotation
                 0.5                     // length
              );
               makeCube(
                 {'r':0.3,'g':0.3,'b':0.87,'a':1.0},  // color
                 {'x':3.5,'y':1.0,'z':2.0},       // position
                 {'x':0.0,'y':0.0,'z':0.0},       // rotation
                 0.1                     // length
              );
               makeCube(
                 {'r':0.3,'g':0.5,'b':0.87,'a':1.0},  // color
                 {'x':0.5,'y':3.0,'z':12.0},       // position
                 {'x':0.0,'y':0.0,'z':0.0},       // rotation
                 0.8                     // length
              );
               makeCube(
                 {'r':0.5,'g':0.3,'b':0.87,'a':1.0},  // color
                 {'x':0.1,'y':-3.0,'z':5.0},       // position
                 {'x':0.0,'y':0.0,'z':0.0},       // rotation
                 0.4                     // length
              );
            }

           var oCubeColorBuffer = null;
           function _makeCubeColorBuffer(aColor){


               oCubeColorBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ARRAY_BUFFER, oCubeColorBuffer);
                var aColors = [
                    [aColor.r, aColor.g, aColor.b, aColor.a], // Front face
                    [aColor.r, aColor.g, aColor.b, aColor.a], // Back face
                    [aColor.r, aColor.g, aColor.b, aColor.a], // Top face
                    [aColor.r, aColor.g, aColor.b, aColor.a], // Bottom face
                    [aColor.r, aColor.g, aColor.b, aColor.a], // Right face
                    [aColor.r, aColor.g, aColor.b, aColor.a]  // Left face
                ];
                var unpackedColors = [];
                for (var i in aColors) {
                    var color = aColors[i];
                    for (var j=0; j < 4; j++) {
                        unpackedColors = unpackedColors.concat(color);
                    }
                }
                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColors), gl.STATIC_DRAW);
                oCubeColorBuffer.itemSize = 4;
                oCubeColorBuffer.numItems = 24;        

              return oCubeColorBuffer;
           }

           var oCubePositionBuffer = null;    
           function _makeCubePositionBuffer(fLength){


              oCubePositionBuffer = gl.createBuffer();
              gl.bindBuffer(gl.ARRAY_BUFFER, oCubePositionBuffer);
              var aVertices = [
                 // Front face
                 -1.0*fLength, -1.0*fLength,  1.0*fLength,
                  1.0*fLength, -1.0*fLength,  1.0*fLength,
                  1.0*fLength,  1.0*fLength,  1.0*fLength,
                 -1.0*fLength,  1.0*fLength,  1.0*fLength,

                 // Back face
                 -1.0*fLength, -1.0*fLength, -1.0*fLength,
                 -1.0*fLength,  1.0*fLength, -1.0*fLength,
                  1.0*fLength,  1.0*fLength, -1.0*fLength,
                  1.0*fLength, -1.0*fLength, -1.0*fLength,

                 // Top face
                 -1.0*fLength,  1.0*fLength, -1.0*fLength,
                 -1.0*fLength,  1.0*fLength,  1.0*fLength,
                  1.0*fLength,  1.0*fLength,  1.0*fLength,
                  1.0*fLength,  1.0*fLength, -1.0*fLength,

                 // Bottom face
                 -1.0*fLength, -1.0*fLength, -1.0*fLength,
                  1.0*fLength, -1.0*fLength, -1.0*fLength,
                  1.0*fLength, -1.0*fLength,  1.0*fLength,
                 -1.0*fLength, -1.0*fLength,  1.0*fLength,

                 // Right face
                  1.0*fLength, -1.0*fLength, -1.0*fLength,
                  1.0*fLength,  1.0*fLength, -1.0*fLength,
                  1.0*fLength,  1.0*fLength,  1.0*fLength,
                  1.0*fLength, -1.0*fLength,  1.0*fLength,

                 // Left face
                 -1.0*fLength, -1.0*fLength, -1.0*fLength,
                 -1.0*fLength, -1.0*fLength,  1.0*fLength,
                 -1.0*fLength,  1.0*fLength,  1.0*fLength,
                 -1.0*fLength,  1.0*fLength, -1.0*fLength
              ];
              gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(aVertices), gl.STATIC_DRAW);
              oCubePositionBuffer.itemSize = 3;
              oCubePositionBuffer.numItems = 24;

              return oCubePositionBuffer;
           }

          var oCubeIndexBuffer = null;   
           function _makeCubeVertexIndexBuffer(){

                oCubeIndexBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, oCubeIndexBuffer);
                var cubeVertexIndices = [
                    0, 1, 2,      0, 2, 3,    // Front face
                    4, 5, 6,      4, 6, 7,    // Back face
                    8, 9, 10,     8, 10, 11,  // Top face
                    12, 13, 14,   12, 14, 15, // Bottom face
                    16, 17, 18,   16, 18, 19, // Right face
                    20, 21, 22,   20, 22, 23  // Left face
                ];
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
                oCubeIndexBuffer.itemSize = 1;
                oCubeIndexBuffer.numItems = 36;      
              return oCubeIndexBuffer;
           }





           function makeCube(aColor, aPosition, aRotation, fLength){
                 mvPushMatrix();
                mat4.translate(mvMatrix, [aPosition.x, aPosition.y, aPosition.z]);

               // mat4.rotate(mvMatrix, degToRad(rCube), [aRotation.x, aRotation.y, aRotation.z]);

                var oCubeVertexPositionBuffer = _makeCubePositionBuffer(fLength);
                gl.bindBuffer(gl.ARRAY_BUFFER, oCubeVertexPositionBuffer);
                gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, oCubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

                var oCubeVertexColorBuffer = _makeCubeColorBuffer(aColor);
                gl.bindBuffer(gl.ARRAY_BUFFER, oCubeVertexColorBuffer);
                gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, oCubeVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);

                var oCubeVertexIndexBuffer = _makeCubeVertexIndexBuffer();
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, oCubeVertexIndexBuffer);
                setMatrixUniforms();
                gl.drawElements(gl.TRIANGLES, oCubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

                mvPopMatrix();

           }





            var lastTime = 0;

            function animate() {
                var timeNow = new Date().getTime();
                if (lastTime != 0) {
                    var elapsed = timeNow - lastTime;

                    rPyramid += (90 * elapsed) / 1000.0;
                    rCube -= (75 * elapsed) / 1000.0;
                }
                lastTime = timeNow;
            }


            function tick() {
                requestAnimFrame(tick);
                drawScene();
                animate();
            }


            function webGLStart() {
                var canvas = document.getElementById("lesson04-canvas");
                initGL(canvas);
                initShaders()
                initBuffers();

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

                tick();
            }

        </script> 


        </head> 


        <body onload="webGLStart();"> 
            <a href="http://learningwebgl.com/blog/?p=370"><< Back to Lesson 4</a><br /> 

            <canvas id="lesson04-canvas" style="border: none;" width="500" height="500"></canvas> 

            <br/> 
            <a href="http://learningwebgl.com/blog/?p=370"><< Back to Lesson 4</a><br /> 

            <!-- Google Analytics stuff, please ignore - nothing to do with WebGL :-) --> 
            <script type="text/javascript"> 
                var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
                document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
            </script> 
            <script type="text/javascript"> 
                try {
                    var pageTracker = _gat._getTracker("UA-2240015-5");
                    pageTracker._trackPageview();
                } catch(err) {
                }
            </script> 

        </body> 

        </html> 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

錯遇了你 2024-11-07 04:27:37

它们实际上都是被绘制的。前三个是“彼此重叠”,这意味着它们渲染得就像一个立方体一样。最后两个位于视口视锥体之外。尝试对 makeCube() 进行以下调用,您将看到两个:

      makeCube(
         {'r':0.3,'g':0.3,'b':0.87,'a':1.0},  // color
         {'x':3.5,'y':1.0,'z':2.0},       // position
         {'x':0.0,'y':0.0,'z':0.0},       // rotation
         0.5                     // length
      );
      makeCube(
         {'r':0.3,'g':0.3,'b':0.87,'a':1.0},  // color
         {'x':1.5,'y':1.0,'z':2.0},       // position
         {'x':0.0,'y':0.0,'z':0.0},       // rotation
         0.5                     // length
      );

They are all actually being drawn. The first three are "on top of each other" meaning that they render as if they are one cube. The last two are outside the viewing frustum of your viewport. Try just the following calls to makeCube() and you will see two:

      makeCube(
         {'r':0.3,'g':0.3,'b':0.87,'a':1.0},  // color
         {'x':3.5,'y':1.0,'z':2.0},       // position
         {'x':0.0,'y':0.0,'z':0.0},       // rotation
         0.5                     // length
      );
      makeCube(
         {'r':0.3,'g':0.3,'b':0.87,'a':1.0},  // color
         {'x':1.5,'y':1.0,'z':2.0},       // position
         {'x':0.0,'y':0.0,'z':0.0},       // rotation
         0.5                     // length
      );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文