【问题标题】:WebGL - wait for texture to loadWebGL - 等待纹理加载
【发布时间】:2013-11-12 09:17:48
【问题描述】:

如何测试WebGLTexture 对象是否“完整”?

目前我收到此消息: [WebGLRenderingContext]RENDER WARNING: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'

我收到此警告是因为渲染循环在其图像完成加载之前尝试使用纹理,那么如何解决这个问题?

【问题讨论】:

  • 感谢您提出这个问题,我在实验中一直使用这些控制台消息有一段时间了。 :-)

标签: html textures webgl


【解决方案1】:

解决此问题的最简单方法是在创建时制作 1x1 纹理。

var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
              new Uint8Array([255, 0, 0, 255])); // red

然后,当图像加载时,您可以用图像替换 1x1 像素纹理。无需任何标志,您的场景将使用您选择的颜色进行渲染,直到图像加载完毕。

var img = new Image();
img.src = "http://someplace/someimage.jpg";
img.onload = function() {
   gl.bindTexture(gl.TEXTURE_2D, tex);
   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);

   // then either generate mips if the image uses power-of-2 dimensions or 
   // set the filtering correctly for non-power-of-2 images.
   setupTextureFilteringAndMips(img.width, img.height);
}

只是为了让人们免于遇到他们最有可能遇到的下一个问题的麻烦,WebGL 需要 mips 或者它需要不需要 mips 的过滤。最重要的是,它需要尺寸为 2 次方(即 1、2、4、8、...、256、512 等)的纹理才能使用 mips。因此,在加载图像时,您很可能希望设置过滤以正确处理此问题。

function isPowerOf2(value) {
  return (value & (value - 1)) == 0;
};

function setupTextureFilteringAndMips(width, height) {
  if (isPowerOf2(width) && isPowerOf2(height) {
    // the dimensions are power of 2 so generate mips and turn on 
    // tri-linear filtering.
    gl.generateMipmap(gl.TEXTURE_2D);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
  } else {
    // at least one of the dimensions is not a power of 2 so set the filtering
    // so WebGL will render it.
    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);
  }
}

【讨论】:

  • 这是一个非常好的技巧,无需添加测试/布尔值即可消除警告。问题仍然是如果由于某种原因纹理不被认为是“完整的”会发生什么。从 texImage2D 返回是否具有“完整”纹理的充分条件?
  • 我的错。 1 像素一像素纹理的值应该是[255, 0, 0, 255] 为红色。把它固定在上面。至于纹理完成我会更新答案
  • 多么壮举!这已经停止了几天的搜索......但是 - 我想使用透明黑色([0,0,0,0]),这不起作用,可能是因为我仍然收到“WebGL:INVALID_ENUM:texImage2D:无效纹理类型”在 Chrome 31.0 中。我确定我通过了 gl.TEXTURE_2D - 仍在寻找原因
【解决方案2】:

要解决这个问题,请使用一些布尔值来判断图像是否已加载。

var loaded = false,
    texture,
    img = new Image();

img.onload = function() {
    texture = gl.createTexture();
    // . . . 
    loaded = true;
};
img.src = "path/myimage.jpg";

// render-loop
function render() {
    if(loaded) {
        // use texture
    }
    else {
        // not loaded yet
    }
}

【讨论】:

  • 管理我自己的布尔值只会告诉我是否调用了一组 API,例如 texImage2D。但它不会告诉它是否成功地创建了一个“完整”的纹理?单独跟踪布尔值可能会很痛苦,所以我修改了它以将布尔值存储在 WebGL 纹理对象中 -> texture.isLoaded=false;
【解决方案3】:

我在尝试使用 Cordova 将我的 HTML5/JS 应用程序部署到 Android 手机时遇到了这个问题。

起初,我认为我的问题是我的精灵表/纹理图集太大而无法加载移动 GPU。所以我batch shrank all the images using ImageMagick's mogrify (mogrify -resize 256x256 *.png),但仍然有问题。这一步仍然是必要的(因为我的8000x8000 .png 对手机来说太多了)。

然后我使用console.log(navigator.userAgent) 检查我的浏览器版本,发现使用的 Chromium 比我的浏览器旧。所以我重新安装了Crosswalk plugin,一切正常。

cordova plugin rm cordova-plugin-crosswalk-webview
cordova plugin add cordova-plugin-crosswalk-webview

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-08
    • 2018-11-18
    • 1970-01-01
    • 2016-08-28
    • 2016-02-06
    • 2017-02-27
    • 2023-04-02
    相关资源
    最近更新 更多