のぐそんブログ

暗いおじさんがシコシコ書くブログです。

THREE.DataTextureメモ

THREE.DataTexture

THREE.DataTextureを利用することで、配列データからテクスチャを作ることができます。 GPGPUなどでテクスチャをデータの格納場所として使う場合に使えそうなので、少し調べてみたいと思います。

基本的な使い方

new THREE.DataTexture( 
    data, //ArrayBufferもしくは配列
    width, 
    height, 
    format, //THREE.LuminanceFormatとか、THREE.RGBFormatとか
    type,//THREE.UnsignedByteTypeとかTHREE.FloatTypeとか
    mapping, 
    wrapS,
    wrapT,
    magFilter,
    minFilter,
    anisotropy
)

一部抜粋ですが、実際に使う場合はこんな感じ。

var w = 32;

var l = Math.pow(w, 2);
var data = new Uint8Array(l);

for (var i = 0; i < l; i++) {
  data[i] = Math.random() * 255;
}

var dataTex = new THREE.DataTexture(data, w, w, THREE.LuminanceFormat, THREE.UnsignedByteType);

dataTex.magFilter = THREE.NearestFilter;
dataTex.needsUpdate = true;//必ず必要

var geometry = new THREE.PlaneBufferGeometry(1, 1);
var material = new THREE.MeshBasicMaterial({
  map: dataTex,
  side: THREE.DoubleSide
});
var mesh = new THREE.Mesh(geometry, material);

RGBデータを入れてみる

rgbそれぞれ値を設定してみます。 ポイントは、データ配列の長さを3倍にしているところです。

var w = 32;

var l = Math.pow(w, 2);
//幅は同じだが、配列の数を3倍にする
var data = new Uint8Array(l * 3);

for (var i = 0; i < l; i++) {

  let stride = i * 3;
  //RGBそれぞれに設定する
  data[stride] = Math.random() * 256;//R
  data[stride + 1] = Math.random() * 256;//G
  data[stride + 2] = Math.random() * 256;//B
}

var dataTex = new THREE.DataTexture(data, w, w, THREE.RGBFormat, THREE.UnsignedByteType);

dataTex.magFilter = THREE.NearestFilter;
dataTex.needsUpdate = true;

var geometry = new THREE.PlaneBufferGeometry(1, 1);
var material = new THREE.MeshBasicMaterial({
  map: dataTex,
  side: THREE.DoubleSide
});
var mesh = new THREE.Mesh(geometry, material);

1テクセルにRGBの値が入ったテクスチャができあがりました。

RGBAデータを入れてみる

アルファをつかする場合はデータの配列を四倍します。

var w = 32;

var l = Math.pow(w, 2);
var data = new Uint8Array(l * 4);

for (var i = 0; i < l; i++) {

  let stride = i * 4;

  data[stride] = Math.random() * 256;
  data[stride + 1] = Math.random() * 256;
  data[stride + 2] = Math.random() * 256;
  data[stride + 3] = Math.random() * 256;
}

var dataTex = new THREE.DataTexture(data, w, w, THREE.RGBAFormat, THREE.UnsignedByteType);

dataTex.magFilter = THREE.NearestFilter;
dataTex.needsUpdate = true;

var geometry = new THREE.PlaneBufferGeometry(1, 1);
var material = new THREE.MeshBasicMaterial({
  map: dataTex,
  side: THREE.DoubleSide
});
var mesh = new THREE.Mesh(geometry, material);

GPGPUで使う場合

GPGPUのデータ格納場所として使う場合は、Uint8Arrayだと8バイトの整数(符号なし)しか使えないので、Float32Arrayを利用したほうがよさそうです。

こんな感じです。

var w = 32;
var l = Math.pow(w, 2);
var dataTex = new Float32Array(l * 4);
var dataTex = new THREE.DataTexture( data, w, h, THREE.RGBAFormat, THREE.FloatType );

ただし、画像として利用する場合は符号などは必要ないので8バイトで十分です。 あくまで、データ受け渡し用のテクスチャになります。