WebGL:简单的纹理渲染问题("绘制到比视口矩形小的目标矩形。")

时间:2016-05-15 15:45:56

标签: webgl rendering texture2d

我目前正在尝试使用WebGL渲染一个简单的纹理。 这基本上是普通系统OpenGL的端口。 它似乎不起作用,我真的不知道出了什么问题,因为调试这些东西似乎也很困难。

我在Firefox上遇到错误: "错误:WebGL:drawElements:绘制到比视口rect小的目标rect。 (此警告仅提供一次)"

视口/投影矩阵/位置似乎是正确的,为什么我会收到该错误?

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>Test</title>
  <style>
  .canstyle {
    width: 800px;
    height: 600px;
  }
  </style>
</head>
<body>
  <canvas id="canvas0" class="canstyle">
  </canvas>
  <script type='text/javascript'>
  var vertexShaderSrc = `
            precision mediump float;

            attribute vec2 aVertexPosition;
            attribute vec2 aTextureCoord;

            uniform mat3 projectionMatrix;

            varying vec2 vTextureCoord;

            void main() {
               gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
               vTextureCoord = aTextureCoord;
            }
  `;

  var fragmentShaderSrc = `

          precision mediump float;

          varying vec2 vTextureCoord;

          uniform sampler2D uSampler;

          void main() {
            gl_FragColor = texture2D(uSampler, vTextureCoord);
          }
  `;

  var img1 = new Image(); // HTML5 Constructor
  img1.src = 'bunny.png';
  img1.alt = 'alt';
  img1.onload = function() {
    render();
  }

  function render() {
    var canvas = document.getElementById("canvas0");
    var gl = canvas.getContext("webgl", {
      alpha: false,
      depth: false,
      stencil: true,
      premultipliedAlpha: false
    });

    var funcs = Object.getOwnPropertyNames(gl.__proto__).filter(function(p) {
      return typeof gl[p] === 'function';
    });

    function HookFunction(func, callback) {
      return function() {
        var res = func.apply(this, arguments);
        callback(arguments);
        return res;
      };
    }

    var endFrame = false;
    var afterFrame = 8;
    funcs.forEach(function(funcName) {
      gl[funcName] = HookFunction(gl[funcName], function(args) {
        if (endFrame) {
          if (afterFrame == 0) {
            return;
          }
          afterFrame -= 1;
        }
        if (funcName == "drawElements") {
          endFrame = true;
        }
        var KK = [];
        var dumpArr = [];
        for (var item in args) {
          var arg = args[item];
          if (arg === null) {
            KK.push("null");
          } else if (arg instanceof ArrayBuffer || arg instanceof Float32Array || arg instanceof Uint8Array || arg instanceof Uint16Array) {
            dumpArr.push(new Uint8Array(arg.buffer));
          } else {
            KK.push(arg);
          }
        }
        console.log("WebGL Interceptor: ", funcName, "(", KK.join(', '), ")");
        if (dumpArr.length) {
          console.log(dumpArr);
        }

      });
    });

    gl.disable(gl.DEPTH_TEST);
    gl.disable(gl.CULL_FACE);
    gl.disable(gl.STENCIL_TEST);
    gl.enable(gl.BLEND);
    gl.enable(gl.SCISSOR_TEST);

    gl.bindFramebuffer(gl.FRAMEBUFFER, null);

    gl.viewport(0, 0, 800, 600);
    gl.scissor(0, 0, 800, 600);

    gl.clearColor(0.06274509803921569, 0.6, 0.7333333333333333, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);

    var vertexDataCount = 4;
    var vertexByteSize = vertexDataCount * 4;
    var BatchSize = 2000;

    var totalIndices = BatchSize * 6;

    var vertices = new ArrayBuffer(BatchSize * vertexByteSize * 4);
    var indices = new ArrayBuffer(totalIndices * 2);

    var indicesUint16View = new Uint16Array(indices);
    var verticesFloat32View = new Float32Array(vertices);

    var j = 0;
    for (var i = 0; i < totalIndices; i += 6, j += 4) {
      indicesUint16View[i + 0] = j + 0;
      indicesUint16View[i + 1] = j + 1;
      indicesUint16View[i + 2] = j + 2;
      indicesUint16View[i + 3] = j + 0;
      indicesUint16View[i + 4] = j + 2;
      indicesUint16View[i + 5] = j + 3;
    }

    var indexBuffer = gl.createBuffer();
    var vertexBuffer = gl.createBuffer();

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indicesUint16View, gl.STATIC_DRAW);

    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, verticesFloat32View, gl.DYNAMIC_DRAW);

    function compileShader(shaderSource, shaderType) {
      var shader = gl.createShader(shaderType);
      gl.shaderSource(shader, shaderSource);
      gl.compileShader(shader);
      var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
      if (!success) {
        throw "could not compile shader:" + gl.getShaderInfoLog(shader);
      }
      return shader;
    }

    function createProgram(vertexShader, fragmentShader) {
      var program = gl.createProgram();
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);
      var success = gl.getProgramParameter(program, gl.LINK_STATUS);
      if (!success) {
        throw ("program filed to link:" + gl.getProgramInfoLog(program));
      }
      return program;
    }

    var vertexShad = compileShader(vertexShaderSrc, gl.VERTEX_SHADER);
    var fragShad = compileShader(fragmentShaderSrc, gl.FRAGMENT_SHADER);

    var shaderProg = createProgram(vertexShad, fragShad);
    gl.useProgram(shaderProg);

    var vertLoc = gl.getAttribLocation(shaderProg, "aVertexPosition");
    var texCoordLoc = gl.getAttribLocation(shaderProg, "aTextureCoord");

    gl.enableVertexAttribArray(vertLoc);
    gl.enableVertexAttribArray(texCoordLoc);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);

    gl.vertexAttribPointer(vertLoc, 2, gl.FLOAT, false, vertexByteSize, 0);
    gl.vertexAttribPointer(texCoordLoc, 2, gl.FLOAT, false, vertexByteSize, 2 * 4);


    var currIndex = 0;
    verticesFloat32View[currIndex++] = 174; // pos
    verticesFloat32View[currIndex++] = 113; // pos
    verticesFloat32View[currIndex++] = 0; // UV
    verticesFloat32View[currIndex++] = 0; // UV

    verticesFloat32View[currIndex++] = 226; // pos
    verticesFloat32View[currIndex++] = 113; // pos
    verticesFloat32View[currIndex++] = 1; // UV
    verticesFloat32View[currIndex++] = 0; // UV

    verticesFloat32View[currIndex++] = 226; // pos
    verticesFloat32View[currIndex++] = 187; // pos
    verticesFloat32View[currIndex++] = 1; // UV
    verticesFloat32View[currIndex++] = 1; // UV

    verticesFloat32View[currIndex++] = 174; // pos
    verticesFloat32View[currIndex++] = 187; // pos
    verticesFloat32View[currIndex++] = 0; // UV
    verticesFloat32View[currIndex++] = 1; // UV

    gl.bufferSubData(gl.ARRAY_BUFFER, 0, verticesFloat32View);

    // | 2 / Width | 0          | -1
    // | 0         | 2 / Height | -1
    // | 0         | 0          | 1
    var rawProjectionMat = new Float32Array([
      0.00249999994, 0, 0, 0, -0.00333333341, 0, -1, 1, 1
    ]);

    gl.uniformMatrix3fv(gl.getUniformLocation(shaderProg, "projectionMatrix"), false, rawProjectionMat);

    gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
    gl.activeTexture(gl.TEXTURE0);

    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);

    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img1);

    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);

  }
  </script>
</body>
</html>

编辑: 我使用以下图像: https://raw.githubusercontent.com/pixijs/examples/gh-pages/_assets/bunny.png

1 个答案:

答案 0 :(得分:3)

我只是猜测问题不在于你在哪里设置了canvas元素内容的大小。

canvas元素中的实际像素数默认为300x150。您可以使用

在HTML中进行设置
<canvas width="800" height="600"></canvas>

或者您可以使用

在JavaScript中进行设置
someCanvasElement.width = 800;
someCanvasElement.height = 600;

Firefox警告您将视口设置为800x600,但它比画布(300x150)大,这非常不寻常,警告是为了帮助您发现问题。

仅供参考:gl.viewport只做两件事。它设置从剪辑空间到屏幕空间(或在本例中为画布空间)的转换,并设置顶点的剪切区域。 “剪裁顶点”表示它不会剪切像素,因此在视口设置的边缘绘制gl_PointSize = 10.0点将在视口设置之外绘制。

要剪辑像素,请使用剪刀测试。我看到你正在设置一个剪刀测试但是因为你显然想要画到画布的边缘,你根本不需要设置剪刀。