Подтвердить что ты не робот

WebGL - дождитесь загрузки текстуры

Как проверить, завершен ли объект 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'

Я получаю это предупреждение, потому что рендер-цикл пытается использовать текстуру до того, как ее изображение закончит загрузку, и как это исправить?

4b9b3361

Ответ 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. Кроме того, для использования mips требуются текстуры с размерами, которые имеют мощность 2 (то есть 1, 2, 4, 8,..., 256, 512 и т.д.). Таким образом, при загрузке изображения вы, скорее всего, захотите настроить фильтрацию для правильной обработки.

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

Ответ 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
    }
}

Ответ 3

У меня возникла эта проблема при попытке развернуть приложение HTML5/JS на Android-телефоне с помощью Cordova.

Сначала я подумал, что моя проблема в том, что мой аттрибут spritesheet/texture слишком велик для загрузки мобильного GPU. Поэтому я пакет сократил все изображения с помощью ImageMagick mogrify (mogrify -resize 256x256 *.png), но все еще имел проблемы. Этот шаг все еще был необходим (поскольку мой 8000x8000 .png был слишком большим для телефонов).

Затем я использовал console.log( navigator.userAgent ), чтобы проверить версию моего браузера и увидел, что используемый Chromium был старше моего браузера, Поэтому я снова установил плагин Crosswalk, и все отлично передает.

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