WebGl - может рисовать только один объект - PullRequest
2 голосов
/ 10 апреля 2011

Я пытаюсь написать функцию куба для отключения от этого примера - почему появляется только один куб, когда я сделал несколько вызовов моей функции makeCube ().У меня есть предчувствие чего-то странного, когда я делаю матрицу push / pop.Я новичок в 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> 

1 Ответ

2 голосов
/ 10 апреля 2011

Все они на самом деле нарисованы.Первые три "друг на друга" означают, что они отображаются так, как если бы они были одним кубом.Последние два находятся вне области просмотра вашего окна просмотра.Попробуйте только следующие вызовы 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
      );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...