by Takumi Hasegawa / @tkm0125
Freelance
Front-end engineer / Technical director
WebGLを意識しなくてもWebGLコンテンツが作れるJavascriptライブラリ。作った人は天才。
カメラをマウスでグリグリ動かせる機能を提供
※ただし、デフォルトでは含まれないので、自分で読み込む必要がある。
// イニシャライズ (カメラを引数に)
var controls = new THREE.TrackballControls(camera);
// 描画ループ内で実行
controls.update();
// リサイズ時に実行
controls.handleResize();
BufferGeometryを使用して、
物体の形を自分で定義する。
attributes、indexの追加など、
わりと素のWebGLのAPIを意識しながら
Geometryを作れるクラス
シェーダと組み合わせるならこれを使う
BufferGeometryを拡張した
FloatingCharsGeometry(自作)を使用して
正方形をたくさん持ったGeometryを作りたい。
その前にFloatingCharsクラスについて説明。
THREE.Meshクラスを拡張したクラス。
完成形では、FloatingCharsGeometry
のインスタンスと
シェーダを適用したMaterialを
プロパティに持つ
要は、step1でmeshを作って
sceneに追加したように
FloatingCharsのインスタンスを
生成してsceneに追加して使う
FloatingCharsGeometryに話を戻します。
以下のそれぞれの情報が
羅列されている配列を生成
attributesは頂点ごとの情報なので、頂点を基準に考えるとわかりやすい。
正方形のインデックス (頂点が何個目の正方形に含まれるか)とたくさん作るとこんな感じになる。
ちなみに全ての正方形は同じ位置にあるindexはどの頂点を使って
ポリゴン(三角形)を形成するか
BufferAttributeのインスタンスを生成、
addAttributeメソッドでattributes
setIndeメソッドでindexを追加
// attributes
// THREE.BufferAttributeの第二引数は、
// 各頂点に対していくつデータを使うか
// positionなら3次元なので3, randomValuesも3次元のため3
// uvは2次元なので2, charIndexは1
this.addAttribute('position', new THREE.BufferAttribute(new Float32Array(this.vertices), 3));
this.addAttribute('randomValues', new THREE.BufferAttribute(new Float32Array(this.randomValues), 3));
this.addAttribute('charIndex', new THREE.BufferAttribute(new Uint16Array(this.charIndices, 1));
this.addAttribute('uv', new THREE.BufferAttribute(new Float32Array(this.uvs), 2));
// index
// THREE.BufferAttributeの第二引数は1
this.setIndex(new THREE.BufferAttribute(new Uint16Array(this.indices), 1));
computeVertexNormalsメソッドで自動計算
this.computeVertexNormals();
three.jsでは、画像・動画などを
Materialに適用することができる。
↓
Textureクラスのインスタンスを生成し、Materialに適用
var texture = new THREE.Texture();
var material = new THREE.MeshBasicMaterial({
map: texture
});
↓
Canvasにオフスクリーン描画したものを
テクスチャとして使用する
drawTextメソッドを使用する
CanvasのdrawTextメソッドでWebFontを使用する場合、WebFontのロードが完了しないと
描画できない
↓
以下のように記述
いろんなwebfontサービスに対応 (今回はgoogle)WebFont.load({
google: {
families: [ 'フォント名' ]
},
active: function(fontFamily, fontDescription) {
// ここにロード後の処理を記述
// このタイミングでcanvasにテキストを描画
}
});
最終的には1枚のCanvasに複数の文字を描画し
UV座標を調整して多数の正方形に異なる文字を
テクスチャとして反映させたい!
↓
ここはシェーダで何とかする!
続きは後ほど
GPGPU(General-purpose computing on graphics processing units; GPUによる汎用計算)とは、GPUの演算資源を画像処理以外の目的に応用する技術のことである
↓
RawShaderMaterialを使用する
※あらかじめ組み込みの値等が宣言されている
ShaderMaterialというのもある
// RawShaderMaterial生成
this.material = new THREE.RawShaderMaterial({
transparent: true, // 透過するかどうか
side: THREE.DoubleSide, // ポリゴンの両面を描画
uniforms: {
// 各種uniform変数を定義
},
vertexShader: "頂点シェーダのプログラムをテキストで渡す",
fragmentShader: "フラグメントシェーダのプログラムをテキストで渡す"
// (その他オプションあり)
});
uniformsのtypeはこちらを参照
頂点シェーダとフラグメントシェーダの内容は
jQueryを使用して、HTMLのscriptタグに
記述されている内容を取得
vertexShader: $('#vertexShader').text(),
fragmentShader: $('#fragmentShader').text()
three.jsでは、あらかじめ次のunform変数
が定義されているので、
これらはRawShaderMaterialの
uniformsで改めて定義しなくてよい
dat.guiを使うと
パラメータをいじれるので楽しい
座標(3次元)ベクトルの回転
vec3 rotateVec3(vec3 p, float angle, vec3 axis){
vec3 a = normalize(axis);
float s = sin(angle);
float c = cos(angle);
float r = 1.0 - c;
mat3 m = mat3(
a.x * a.x * r + c,
a.y * a.x * r + a.z * s,
a.z * a.x * r - a.y * s,
a.x * a.y * r - a.z * s,
a.y * a.y * r + c,
a.z * a.y * r + a.x * s,
a.x * a.z * r + a.y * s,
a.y * a.z * r - a.x * s,
a.z * a.z * r + c
);
return m * p;
}
数値の範囲変換
float map(float value, float inputMin, float inputMax, float outputMin, float outputMax, bool clamp) {
if(clamp == true) {
if(value < inputMin) return outputMin;
if(value > inputMax) return outputMax;
}
float p = (outputMax - outputMin) / (inputMax - inputMin);
return ((value - inputMin) * p) + outputMin;
}
HSVをRGBに変換
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}