飴屋

WebGL/構成

Three.jsを使って何か出力してみる

ポリゴンを使った3DCG表現は手を変え品を変えいろいろやってきたので、詳細を調べなくても何となくわかっちゃうことが多いです。私の最初のポリゴン経験なんだろ。ファミコンの最末期に出たレースゲームか、BASICのコードとか載ってるパソコン雑誌にマシン語でポリゴン描画したコードが載ってたのをわけもわからず打ち込んでみたときかな?DirectX、Java3D、Flash3Dと思ったよりチョコチョコ手を出してきましたが、もしかしたらOpenGLは本で読んだくらいで何か作ったことなかったかも。結構、PC側のスペックが今よりも大事で相性とかいろいろあったよな~とか昔を思い出したり。(しみじみ)

とりあえずWebGLはCanvasに描画するAPIらしいので、htmlファイルにcanvasを置きます。

<canvas id="canvas"></canvas>

そして、レンダラーとやらを作ってcanvasを渡してやるらしいです。描画する主体なんでしょうね、レンダラー。レンダラーに描画対象のサイズやピクセル密度をしてやると、canvasの世話もしてっくれるようです。

const width = 800;
const height = 600;
const renderer = new THREE.WebGLRenderer({
  canvas: document.getElementById('canvas')
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);

続いて、シーンを用意します。シーンってなんて説明しよう。撮影現場みたいなものですかね。このシーンの中に「役者」でも「舞台セット」でも「小道具」でも配置していくわけですね。

const scene = new THREE.Scene();

そしてカメラを配置します。カメラはシーンの中でどこを撮影するか決定する役割があります。カメラの位置や向き、レンズの種類で構図が極まるわけです。サンプルにあったPerspectiveCameraっていうカメラが多分人間でいう目に近くてとっつきやすいでしょうね。

const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
camera.position.set(0, 0, 500);

カメラに渡した4つの引数がそれぞれ以下の感じです。

fov
カメラの画角
aspect
カメラ画面の縦横比
near
撮影範囲の近い方の距離
far
撮影範囲の遠い方の距離

PerspectiveCameraは人間の目のように遠くのものを小さく移すので、遠くのものほど視界に入りやすいわけです。無限に遠くのものが視界に入ったら全部描画するのが大変なので、どこまで遠いものをカメラに映すか決められます。逆に近いものは大きく映るので、カメラの目の前に何かあったら視界はそれで埋まってしまいます。なので、どこまで近いものを映すかも調整できるようになっています。

カメラの画角、すなわち視界の角度が決まると描画対象を決める錐形ができ、遠近の限界が決まって、四角いキャンバスに視野を投影することが決まると、描画対象は台形みたいな方形(方体?)に収まることになります。この方形をcanvasに合わせて変形するのが要するにレンダリングと呼ばれている操作になるわけですね。

とりあえず、シーンに被写体を追加してみましょう。Three.jsのドキュメントのGeometriesの項目に箱のジオメトリがあったのでシーンに追加します。ジオメトリは基本的な形を表すものですね。何でもかんでもポリゴンで表現する必要はなく、高さ、幅、奥行きの3つの数字があれば箱は表現できるってことですね。三角ポリゴンで箱を書こうとすると最低でも12枚分の位置情報が必要なわけで、そんなのやりたくないよねってことです。

const geometry = new THREE.BoxGeometry(100, 100, 100);
const material = new THREE.MeshNormalMaterial();
const box = new THREE.Mesh(geometry, material);
scene.add(box);

ジオメトリにはマテリアルを指定します。今は詳細な説明はしませんが、マテリアルは物体の材質を表すものです。ジオメトリが形状、マテリアルが材質、どっちが欠けても絵に描けなくなっちゃいますね。両者を合わせてメッシュにしました。メッシュはなんて説明しよう。直訳すると「網目」でポリゴンがたくさん並んで形状を作っている様がメッシュと呼ばせていると思いますが、もうちょっと複雑な情報をメッシュは含んでますね。具体的にはどのポリゴンの何番目の点が「どの位置」で「どんな色」なのか、その点は「どの点とつながっているのか」みたいな、描画計算のための情報が詰まっているのでした。なんなら、テクスチャのUV座標位置とか、法線の向きとか描画に必要ならなんでも持たされてるかもしれません。(まだ仕様を把握してないからわかんないけど)

メッシュをシーンに追加(add)したらあとはレンダラーに描画を頼むだけですね。

renderer.render(scene, camera);

カメラとシーンを渡せばいいだけですね。逆に複数台のカメラを設置して1カメ、2カメとか呼んでスイッチングするのも簡単、引数を変えればいいだけです。シーンもあっという間に切り替えられる。現実の撮影ではできないことです。ありがたやー。

ざっと、動くとこまでやってみて、箱が画面の中央に出てきました。一面しかこっちを向いてないので正方形があるだけですが。三頂点が赤青緑な三角ポリゴンの方があるある感があってよかったかな?見栄えがするんですよね、アレ。いまのところシェーダーを自分で書かなくても動いちゃいましたね。すごい、Three.js便利!

Last-Modified