WebGL - drawElements:纹理是非二次幂纹理或非完整的mipmap

时间:2015-08-28 23:01:19

标签: javascript canvas webgl

我正在将<video>绘制到webgl画布上。我有它在chrome和firefox工作,但IE11似乎抛出错误。错误说明:

drawElements: The texture is a non-power-of-two texture or not mipmap complete 

并参考此特定行:

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

我正在运行requestAnimationFrame循环,正在更新我的画布。我读过这个错误可能是由于图像没有准备好或没有加载。这是我的循环:

(function loop()
{
  if (!$this.paused && !$this.ended)
  {

    gl.clear(gl.COLOR_BUFFER_BIT);

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, tex);

    if (!$this.paused && !$this.ended)
    {
      try
      {
        // update the video frame
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, player);
      }
      catch(e)
      {
        log(e);
      }
    }

    gl.bindBuffer(gl.ARRAY_BUFFER, vx);
    gl.vertexAttribPointer(vx_ptr, 2, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ix);
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
    window.requestAnimationFrame(loop);
  }
})();

这似乎是什么造成的?我一直在寻找没有运气。在循环运行之前,我使用以下代码设置webgl画布:

 $scope.prepWebGL = function()
 {
      // prepare visible WebGL
      vs = gl.createShader(gl.VERTEX_SHADER);
      gl.shaderSource(vs, "attribute vec2 vx;varying vec2 tx;void main(){gl_Position=vec4(vx.x*2.0-1.0,1.0-vx.y*2.0,0,1);tx=vx;}");
      gl.compileShader(vs);

      ps = gl.createShader(gl.FRAGMENT_SHADER);
      gl.shaderSource(ps, "precision mediump float;uniform sampler2D sm;varying vec2 tx;void main(){gl_FragColor=texture2D(sm,tx);}");
      gl.compileShader(ps);

      shader  = gl.createProgram();
      gl.attachShader(shader, vs);
      gl.attachShader(shader, ps);
      gl.linkProgram(shader);
      gl.useProgram(shader);

      vx_ptr = gl.getAttribLocation(shader, "vx");
      gl.enableVertexAttribArray(vx_ptr);
      gl.uniform1i(gl.getUniformLocation(shader, "sm"), 0);

      vx = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, vx);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0,0, 1,0, 1,1, 0,1]), gl.STATIC_DRAW);

      ix = gl.createBuffer();
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ix);
      gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0,1,2, 0,2,3]), gl.STATIC_DRAW);

      tex = gl.createTexture();
      gl.bindTexture(gl.TEXTURE_2D, tex);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T,     gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S,     gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
 };

3 个答案:

答案 0 :(得分:0)

如果问题实际上是未加载视频,您可以为视频添加标记,以表明视频已加载

player.loaded = false;
player.onload = function() {
    this.loaded = true;
}

然后检查视频是否已加载到循环中

if (!$this.paused && !$this.ended && player.loaded)
{
  try
  {
    // update the video frame
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, player);
  }
  catch(e)
  {
    log(e);
  }
}

答案 1 :(得分:0)

错误意味着您当前使用的纹理不是2的幂,而webgl限制了2纹理支持的非幂。特别是,您不能生成具有2个纹理的非幂的mip贴图,也不能在重复时设置它们。

奇怪的是,您正在使用gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);,假设您不使用mip地图,并且您也在使用gl.CLAMP_TO_EDGE。也许这是IE的错误?

答案 2 :(得分:0)

也许您会遇到一些比例问题,但您可能会使用512 * 512或1024 * 512这样的视频格式,这样可以解决您的兼容性问题,您也可以将视频包含在视频中,尺寸正确视频转换器或一些视频编辑工具。为了不丢失源视频的缩放比例