web-dev-qa-db-ja.com

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'

レンダーループが画像の読み込みが完了する前にテクスチャを使用しようとしているため、この警告が表示されます。それを修正するにはどうすればよいですか?

14
Remi Arnaud

これを修正する最も簡単な方法は、作成時に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など)のテクスチャが必要です。したがって、画像をロードするときは、これを正しく処理するようにフィルタリングを設定することをお勧めします。

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

この問題を修正するには、ブール値を使用して、画像が読み込まれたかどうかを確認します。

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

Cordovaを使用してHTML5/JSアプリをAndroid電話にデプロイしようとしたときに、この問題が発生しました。

最初、私の問題は、スプライトシート/テクスチャアトラスが大きすぎてモバイルGPUをロードできないことだと思いました。だから私は バッチはImageMagickのmogrifymogrify -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
0
James L.