WebGL - 等待纹理加载 [英] WebGL - wait for texture to load

查看:738
本文介绍了WebGL - 等待纹理加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何测试 WebGLTexture 对象是否为'complete'?



目前我收到此消息:
[WebGLRenderingContext] RENDER警告:绑定到纹理单元0的纹理无法渲染。它可能不是2的权力,并且具有不兼容的纹理过滤,或者不是纹理完整



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

解决方案

最简单的方法解决方法是在创建时创建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图片((图片仅供参考,以图片形式显示) ); 
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);

//然后,如果图像使用2次方幂或者
,则生成mips //为2次幂的图像正确设置滤波。
setupTextureFilteringAndMips(img.width,img.height);

$ / code>

为了节省人们遇到下一个问题的麻烦,他们很可能会遇到,WebGL需要mips,或者它需要不需要mips的过滤。最重要的是,它需要尺寸为2的幂(即1,2,4,8,...,256,512等)的纹理才能使用mips。所以,在加载图片时,您最有可能需要设置过滤器来正确处理这个问题。

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

函数setupTextureFilteringAndMips(width,height){
if(isPowerOf2(width)&& isPowerOf2(height){
//尺寸是2的乘方因此产生mips并打开
//三线性过滤
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR_MIPMAP_LINEAR);
} else {
//至少有一个维度不是2的幂,所以设置过滤
//所以WebGL会渲染它
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 );
}
}


How do I test if the WebGLTexture object is 'complete' ?

Currently I get this message: [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'

I get this warning because the render-loop is trying to use the texture before its image has finished loading, so how to fix that?

解决方案

The easiest way to fix that is to make a 1x1 texture at creation time.

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

Then when the image loads you can replace the 1x1 pixel texture with the image. No flags needed and your scene will render with the color of your choice until the image has loaded.

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);
}

Just for the sake of saving people the trouble of running into the next problem they are most likely going to run into, WebGL requires mips or it requires filtering that doesn't require mips. On top of that it requires textures with dimensions that are a power of 2 (ie, 1, 2, 4, 8, ..., 256, 512, etc) to use mips. So, when loading an image you'll most likely want to setup the filtering to handle this correctly.

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);
  }
}

这篇关于WebGL - 等待纹理加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆