在 WebGL 中纹理金字塔

Texturing a pyramid in WebGL

我正在处理带纹理的金字塔,但收到了一些警告。我是按照书上的一步步做的"Beginning WebGL for HTML5" 还是不行

这是我的代码:

<!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>

我使用的纹理坐标是这样的:

这是纹理:

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

您的代码中有多个错误。

  1. 您的函数 loadTexture() 从未被调用,因此实际上从未加载纹理。
    initWebGL().

  2. 中将 setupTexture() 替换为 loadTexture()
  3. 您似乎也在使用 jQuery 从 DOM 检索图像,但您没有加载库。
    loadTexture().

  4. 中用 document.getElementById("troll") 替换 $("#troll").get(0)
  5. 纹理的尺寸需要是2的幂(128x32, 256x256, 512x1024, ...)
    您应该将图片大小调整为 256x256。

  6. 您打错了 texImage2D() 的其中一个参数。
    gl.texImage2D() 调用中将 gl.UNISGNED_BYTE 替换为 gl.UNSIGNED_BYTE

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

  8. 如果要渲染单个三角形,请在 gl.drawElements() 调用中将 gl.TRIANGLE_STRIP 替换为 gl.TRIANGLES

如果您修正了所有这些错误,您的代码将 运行 没有错误。