2013-11-01 5 views
13

Как проверить, завершен ли объект WebGLTexture?WebGL - ждать загрузки текстуры

В настоящее время я получаю сообщение: [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'

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

+1

Спасибо, что спросили об этом, я жил с этими консольными сообщениями в своих экспериментах некоторое время. :-) –

ответ

18

Самый простой способ исправить это сделать 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); 
    } 
} 
+1

Это очень хороший трюк, избавиться от предупреждений, не добавляя test/boolean. Вопрос остается фактом, что происходит, если по какой-то причине текстура по какой-то причине не считается «полной». Возвращается из texImage2D достаточное условие, чтобы иметь «полную» текстуру? –

+0

Я не могу получить красный! Текстура всегда белая? см. http://jsfiddle.net/aXcs8/2/ –

+0

Мой плохой. Значение 1 пиксельной текстуры одного пикселя должно быть '[255, 0, 0, 255]' для красного. Исправлено. Что касается текстуры, я обновлю ответ – gman

1

Чтобы исправить эту проблему, используйте некоторое логическое значение, чтобы узнать, загружено ли изображение.

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 
    } 
} 
+1

Управление собственным булевым будет просто сказать мне, если был вызван набор API-интерфейсов, таких как texImage2D. Но он не скажет, удалось ли создать «полную» текстуру? Слежение за булерами отдельно может быть больно, поэтому вместо этого я изменил это, чтобы сохранить логическое значение в объекте текстуры WebGL -> texture.isLoaded = false; –

0

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

Во-первых, я думал, что мой вопрос в том, что мой атлас spritesheet/texture был слишком большим для загрузки мобильного 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 
Смежные вопросы