在WebGL中纹理金字塔

时间:2016-11-11 18:34:04

标签: javascript textures webgl

我正在制作一个纹理金字塔,但我收到了一些警告。我是从“使用HTML5开始WebGL”一书中逐步完成的,但它不起作用。

这是我的代码:

<!doctype html>
<html>
    <head>
        <title>Project 2</title>

        <script type="text/javascript" src="gl-matrix-min.js"></script>


        <style>
                 body{ background-color: grey; }
                 canvas{ background-color: white; }
        </style>
        <script id="shader-vs" type="x-shader/x-vertex">
                attribute vec4 aVertexPosition;
                attribute vec4 aVertexColor;
                attribute vec2 aVertexTextureCoord;

                varying highp vec2 vTextureCoord;
                varying vec4 vColor;
                /*

                Couting On GPU

                // Model matrix
                uniform mat4 uMVMatrix;
                // Projection matrix
                uniform mat4 uPMatrix;
                // View matrix
                uniform mat4 uVMatrix;

                */

                uniform mat4 uPVMatrix;

                void main(void) {
                    vColor = aVertexColor;
                    gl_Position = uPVMatrix * aVertexPosition;
                    vTextureCoord = aVertexTextureCoord;
                 //   gl_Position = uPMatrix * uVMatrix * uMVMatrix * aVertexPosition;
                }
        </script>
        <script id="shader-fs" type="x-shader/x-fragment">
            precision mediump float;
            varying vec4 vColor;
            varying highp vec2 vTextureCoord;
            uniform sampler2D uSampler;
                void main(void) {
                    gl_FragColor = texture2D(uSampler, vTextureCoord);
                }
        </script>
        <script>
                var gl = null,
                    canvas = null,
                    glProgram = null,
                    fragmentShader = null,
                    vertexShader = null;

                var coordinateArray = [], 
                    triangleVerticeColors = [],
                    verticesArray = [],
                    verticesIndexArray = [],
                    triangleTexCoords = [];

                var vertexPositionAttribute = null,
                    trianglesVerticeBuffer = null,
                    vertexColorAttribute = null,
                    trianglesColorBuffer = null,
                    triangleVerticesIndexBuffer = null,
                    vertexTexCoordAttribute = null, 
                    trianglesTexCoordBuffer = null;



                var P = mat4.create(),
                    V = mat4.create(),
                    M = mat4.create(),
                    VM = mat4.create(),
                    PVM = mat4.create();

                var uPVMMatrix;

                var texture;
                var textureImage = null;

                function initWebGL() {
                    canvas = document.getElementById("my-canvas");
                    try {
                        gl = canvas.getContext("webgl") ||
                        canvas.getContext("experimental-webgl");
                    }catch(e){ }
                    if(gl) {
                        setupWebGL();
                        initShaders();
                        setupTexture();
                        setupBuffers();

                        //getMatrixUniforms();
                        //setMatrixUniforms();
                        //animationLoop();
                        drawScene();
                    }else{
                        alert( "Error: Your browser does not appear to" + "support WebGL.");
                    }
                }

                function animationLoop() {
                    var R = mat4.create();
                    var angle = 0;
                    var i =0;

                    var loop = function() {
                        angle = performance.now() / 1000 / 6 * 2 * Math.PI;
                        i++;
                        mat4.rotate(PVM, R, angle, [0, 1, 0]);

                        gl.uniformMatrix4fv(uPVMMatrix, false, PVM);

                        gl.clearColor(0.0, 0.0, 0.0, 0.0);
                        gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
                        drawScene();
                        requestAnimationFrame(loop);
                    };
                    requestAnimationFrame(loop);
                }

                function setupWebGL() {
                    gl.enable(gl.DEPTH_TEST);
                    gl.enable(gl.CULL_FACE);
                    gl.frontFace(gl.CW);
                    gl.cullFace(gl.BACK);
                    gl.clearColor(0.0, 0.0, 0.0, 0.0);
                    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);



                    console.log(P);         
                    console.log(V);             
                    console.log(M);

                //  mat4.identity(M);
                    mat4.lookAt(V, [5, 0, -5], [0, 0, 0], [0, 1, 0]);
                    mat4.perspective(P, glMatrix.toRadian(45), canvas.width / canvas.height, 0.1, 1000.0);

                    mat4.multiply(VM,V,M);
                    mat4.multiply(PVM,P,VM);


                }

                function initShaders() {
                    var fs_source = document.getElementById('shader-fs').innerHTML,
                        vs_source = document.getElementById('shader-vs').innerHTML;

                    vertexShader = makeShader(vs_source, gl.VERTEX_SHADER);
                    fragmentShader = makeShader(fs_source, gl.FRAGMENT_SHADER);

                    glProgram = gl.createProgram();

                    gl.attachShader(glProgram, vertexShader);
                    gl.attachShader(glProgram, fragmentShader);
                    gl.linkProgram(glProgram);
                    if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) {
                        alert("Unable to initialize the shader program.");
                    }

                    gl.useProgram(glProgram);

                    uPVMMatrix = gl.getUniformLocation(glProgram, "uPVMatrix");
                    gl.uniformMatrix4fv(uPVMMatrix, false, PVM);

                }



                function loadTexture() {
                     textureImage = $("#troll").get(0);   
                     setupTexture(); 
                }

                function setupTexture() {
                    texture = gl.createTexture();
                    gl.bindTexture(gl.TEXTURE_2D, texture);
                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
                    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNISGNED_BYTE, textureImage);
                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);

                    glProgram.sampleUniform = gl.getUniformLocation(glProgram, "uSampler");
                    gl.uniform1i(glProgram.sampleUniform, 0);

                    if(!gl.isTexture(texture)) {
                        console.log("Error : Texture is invalid");
                    }
                }

                function makeShader(src, type) {
                    var shader = gl.createShader(type);

                    gl.shaderSource(shader, src);
                    gl.compileShader(shader);
                    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
                        alert("Error compiling shader: " + gl.getShaderInfoLog(shader));
                    }
                    return shader;
                }

                function setupBuffers() {
                    // n-sides polygon
                    var n = 6;
                    var radius = 1;
                    var angle = (Math.PI * 2) / n;
                    var xCoordinate = 0;
                    var yCoordinate = 0;
                    for(var i = 0 ; i < n ; i++) {

                        var a = angle * i;
                        var xNewCoordinate = xCoordinate + radius * Math.cos(a);
                        var yNewCoordinate = yCoordinate + radius * Math.sin(a);
                        var zNewCoordinate = 0;
                        coordinateArray.push(xNewCoordinate);
                        coordinateArray.push(yNewCoordinate);
                        coordinateArray.push(zNewCoordinate);

                    }

                    verticesArray = [

                        //Bottom Face
                        0.0, 0.0, 0.0,
                        0.0, 0.0, -1.0,
                        1.0, 0.0, -1.0,
                        0.0, 0.0, 0.0,
                        1.0, 0.0, -1.0,
                        1.0, 0.0, 0.0,

                        //Front Face
                        0.0, 0.0, 0.0,
                        1.0, 0.0, 0.0,
                        0.5, 1.0, -0.5,

                        //Right Face
                        1.0, 0.0, 0.0,
                        1.0, 0.0, -1.0,
                        0.5, 1.0, -0.5,

                        //Back Face
                        1.0, 0.0, -1.0,
                        0.0, 0.0, -1.0,
                        0.5, 1.0, -0.5,

                        //Left Face
                        0.0, 0.0, -1.0,
                        0.0, 0.0, 0.0,
                        0.5, 1.0, -0.5,
                    ];

                    trianglesVerticeBuffer = gl.createBuffer();
                    gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer);
                    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesArray), gl.STATIC_DRAW);

                    verticesIndexArray = [
                        0, 1, 2,
                        3, 4, 5,
                        6, 7, 8,
                        9, 10, 11,
                        12, 13, 14,
                        15, 16, 17,
                    ];

                    triangleVerticesIndexBuffer = gl.createBuffer();
                    triangleVerticesIndexBuffer.number_vertext_points = verticesIndexArray.length;
                    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleVerticesIndexBuffer);
                    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(verticesIndexArray), gl.STATIC_DRAW); 

                    triangleTexCoords = [
                        0.5000, 0.1910,
                        0.1910, 0.5000,
                        0.5000, 0.8090,
                        0.5000, 0.1910,
                        0.5000, 0.8090,
                        0.8090, 0.5000,

                        0.5000, 0.1910,
                        0.8090, 0.5000,
                        1.0000, 0.0000,

                        0.8090, 0.5000,
                        0.5000, 0.8090,
                        1.0000, 1.0000,

                        0.5000, 0.8090,
                        0.1910, 0.5000,
                        0.0000, 1.0000,

                        0.1910, 0.5000,
                        0.5000, 0.1910,
                        0.0000, 0.0000,
                    ];

                    trianglesTexCoordBuffer = gl.createBuffer();
                    gl.bindBuffer(gl.ARRAY_BUFFER, trianglesTexCoordBuffer);
                    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleTexCoords), gl.STATIC_DRAW);

                    triangleVerticeColors = [  
                        // Bottom quad
                        0.470, 0.796, 0.886,
                        0.470, 0.796, 0.886,
                        0.470, 0.796, 0.886,
                        0.470, 0.796, 0.886,
                        0.470, 0.796, 0.886,
                        0.470, 0.796, 0.886,

                        // Back triangle
                        0.772, 0.470, 0.886,
                        0.772, 0.470, 0.886,
                        0.772, 0.470, 0.886,

                        // Left triangle
                        0.886, 0.552, 0.470,
                        0.886, 0.552, 0.470,
                        0.886, 0.552, 0.470,

                        // Front triangle
                        0.886, 0.882, 0.470,
                        0.886, 0.882, 0.470,
                        0.886, 0.882, 0.470,

                        // Right triangle
                        0.470, 0.886, 0.505,
                        0.470, 0.886, 0.505,
                        0.470, 0.886, 0.505,
                    ];

                    trianglesColorBuffer = gl.createBuffer(); 
                    gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer); 
                    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVerticeColors), gl.STATIC_DRAW); 

                }

                // GPU

                function getMatrixUniforms() {

                    glProgram.mvMatrixUniform = gl.getUniformLocation(glProgram, "uMVMatrix");
                    glProgram.pMatrixUniform = gl.getUniformLocation(glProgram, "uPMatrix");
                    glProgram.vMatrixUniform = gl.getUniformLocation(glProgram, "uVMatrix");                

                }

                // GPU

                function setMatrixUniforms() {

                    gl.uniformMatrix4fv(glProgram.mvMatrixUniform, false, M);
                    gl.uniformMatrix4fv(glProgram.pMatrixUniform, false, P);
                    gl.uniformMatrix4fv(glProgram.vMatrixUniform, false, V);

                }

                function drawScene() {
                    vertexPositionAttribute = gl.getAttribLocation(glProgram, "aVertexPosition");
                    gl.enableVertexAttribArray(vertexPositionAttribute);
                    gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer);
                    gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);

                    vertexTexCoordAttribute = gl.getAttribLocation(glProgram, "aVertexTexCoord");
                    gl.enableVertexAttribArray(vertexTexCoordAttribute);
                    gl.bindBuffer(gl.ARRAY_BUFFER, trianglesTexCoordBuffer);
                    gl.vertexAttribPointer(vertexTexCoordAttribute, 2, gl.FLOAT, false, 0, 0);

                    /*vertexColorAttribute = gl.getAttribLocation(glProgram, "aVertexColor");    
                    gl.enableVertexAttribArray(vertexColorAttribute); 
                    gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer); 
                    gl.vertexAttribPointer(vertexColorAttribute, 3, gl.FLOAT, false, 0, 0);
                    */


                    gl.drawElements(gl.TRIANGLE_STRIP, triangleVerticesIndexBuffer.number_vertext_points,  gl.UNSIGNED_SHORT, 0);           
                }
        </script>
    </head>
    <body onload="initWebGL()">
        <canvas id="my-canvas" width="800" height="600">
            Your browser does not support the HTML5 canvas element.
        </canvas>
        <img src="./trollface.png" id="troll" /> 
    </body>
</html>

我使用的纹理坐标如下所示:

UV map

这是纹理:

texture

警告是关于超出范围的数组以及未加载的图像。

1 个答案:

答案 0 :(得分:1)

您的代码中有多处错误。

  1. 永远不会调用您的函数loadTexture(),因此实际上从未加载纹理 将setupTexture()替换为loadTexture()内的initWebGL()

  2. 您似乎也在使用jQuery从DOM中检索图像,但是您没有加载库。
    $("#troll").get(0)替换为document.getElementById("troll")内的loadTexture()

  3. 纹理的尺寸需要为2的幂(128x32,256x256,512x1024,...)
    您应该将图像大小调整为256x256。

  4. 您使用texImage2D()的其中一个参数输入了拼写错误 将gl.UNISGNED_BYTE替换为gl.UNSIGNED_BYTE来电中的gl.texImage2D()

  5. 您的gl.getAttribLocation()调用与顶点着色器代码之间的纹理坐标属性名称不匹配。
    aVertexTexCoord替换为aVertexTextureCoord来电中的gl.getAttribLocation()

  6. 如果您要渲染单个三角形,请在gl.TRIANGLE_STRIP来电中将gl.TRIANGLES替换为gl.drawElements()

  7. 如果你修复了所有这些错误,你的代码就会毫无错误地运行。