のぐそんブログ

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

THREE.BufferGeometryの使い方を調べる

THREE.BufferGeometryの使い方の基礎的な部分をまとめたいと思います。

THREE.BufferGeometryとは

var geometry = new THREE.BufferGeometry();

BufferGeometryはピュアなWebGLAPIを扱うようにGeometryを作成できます。 BufferGeometryは作成時は何も情報を持たない為、頂点データ(attributeやindex)を定義する必要があります。

また、three.jsのBoxGeometryやSphereGeometryなどの基本のGeometryは、毎フレーム頂点データをGPUに送っていますが、 BufferGeometryは最初の1回だけ送っています。

大量の頂点データなどを扱う場合は、毎フレーム送信した場合負荷が高くなる為、BufferGeometryを利用するほうが良いようですし、 頂点データを自由に定義できるので、上手く扱えれば表現の自由度も高いです。

型付配列(TypedArray)

頂点データを扱う場合は型付配列を利用します。

JavaScriptからWebGLに値を渡す際に、JavaScriptの配列を使うより型付配列を使ったほうがパフォーマンスが向上します。 Float32ArrayUint8ArrayInt16Arrayなどを利用して、型指定をして配列を作成します。

クラス 説明
new Float64Array(n),new Float64Array(n) 浮動小数点型の配列
new Int32Array(n),new Int16Array(n) ,new Int8Array(n) 符号付き整数の配列
new Uint32Array(n),new Uint16Array(n) ,new Uint8Array(n) 符号なし整数の配列
var vertexPositions = [
    -1.0, -1.0, 1.0, //頂点0
     1.0, -1.0, 1.0, //頂点1
     1.0,  1.0, 1.0, //頂点2
    -1.0,  1.0, 1.0  //頂点0
];

var vertices = new Float32Array(vertexPositions);

注意しないといけないのが、型付配列に変換した場合配列の便利メソッドが使えなくなります。

var vertexPositions = [
    -1.0, -1.0, 1.0, //頂点0
     1.0, -1.0, 1.0, //頂点1
     1.0,  1.0, 1.0, //頂点2
    -1.0,  1.0, 1.0  //頂点0
];

var vertices = new Float32Array(vertexPositions);

console.log(vertices.splice(1,1));//エラーになる vertices.splice is not a function

THREE.BufferAttribute

型付配列に変換した頂点データはTHREE.BufferAttributeクラスでインスタンス化してBufferGeometryのattributesに追加します。

var geometry = new THREE.BufferGeometry();

var vertexPositions = [
    -1.0, -1.0, 1.0, //頂点0
     1.0, -1.0, 1.0, //頂点1
     1.0,  1.0, 1.0, //頂点2
    -1.0,  1.0, 1.0  //頂点0
];

var vertices = new Float32Array(vertexPositions);

//型付配列に変換した頂点座標データを、THREE.BufferAttributeのインスタンスにして追加
geometry.addAttribute('position',new THREE.BufferAttribute(vertices,3));

頂点のインデックスデータも同じようにattributesに追加できます。

var indices = new Uint16Array([
    0, 1, 2,//一つ目のポリゴン
    2, 3, 0 //二つ目のポリゴン
]);

geometry.setIndex(new THREE.BufferAttribute(indices,1));

他にも頂点色や、法線情報なども設定できます。

geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
geometry.addAttribute('size', new THREE.BufferAttribute(sizes, 1));

サンプル1

See the Pen VzzQbv by nogson (@satofaction) on CodePen.

サンプル2

100000ポリゴンでもスイスイ動きます。

See the Pen gxXNqo by nogson (@satofaction) on CodePen.

参考

three.jsでジェネラティブアートっぽいことするのに必要な知識

[JavaScript] ArrayBufferについて調べてみた