Hatena::Groupjavascript

JavaScriptで遊ぶよ

 | 

2011-09-30

WebGL のテクスチャーに任意のサイズの画像を使う

15:26

こちらも参考にしてください→JavaScript Advent Calendar/WebGLコース7日目・WebGLとOpenGLの相違点 - JavaScriptで遊ぶよ - g:javascript


WebGL のテクスチャーには、一片が2の整数乗の正方形の画像しか使えない。そうじゃないテクスチャーのところは真っ黒になってしまう。

テクスチャーを初期化するところはだいたいこんなふうになってると思うけど、

var myTexture = null;

function initTexture(image) {
  var texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

  // ... gl.texParameteri など ...

  return texture;
}

function loadImage(url) {
  var img = new Image;
  img.onload = function() {
    myTexture = initTexture(img); // ←ここを変える
  };
  img.src = url;
  return img;
}

これをこんなふうにすると

var myTexture = null;

function initTexture(image) {
  var texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

  // ... gl.texParameteri など ...

  return texture;
}
// ↑ここまで同じ

// ↓この関数を追加
function checkSize(img) {
  var w = img.naturalWidth, h = img.naturalHeight;
  var size = Math.pow(2, Math.log(Math.min(w, h)) / Math.LN2 | 0); // largest 2^n integer that does not exceed s
  if (w !== h || w !== size) {
    var canv = document.createElement('canvas');
    canv.height = canv.width = size;
    canv.getContext('2d').drawImage(img, 0, 0, w, h, 0, 0, size, size);
    img = canv;
  }
  return img;
}

function loadImage(url) {
  var img = new Image;
  img.onload = function() {
    myTexture = initTexture(checkSize(img)); // ←ここを変えた
  };
  img.src = url;
  return img;
}

これだけで任意のサイズの画像をテクスチャーに使える。


Math.pow(2, Math.log(Math.min(w, h)) / Math.LN2 | 0)

これが「画像の元サイズの幅と高さの小さい方を超えない最大の 2^n の形の整数」となり、そのサイズで canvas を作って 2D context の drawImage で画像を流し込んでる。

まあ普通はサーバー側でやると思うけど。

トラックバック - http://javascript.g.hatena.ne.jp/edvakf/20110930
 |