Three JS:MeshPhongMaterialを極める-環境マッピング編-
今回はMeshPhongMaterialの環境マッピングに関してです。と言っても、環境マッピングに関しては他のMeshBasicMaterial、MeshLambertMaterialでも共通で使えます。あまり使う機会は多くないかもしれませんが、環境マップを加えるとガラスや鏡面などの表面をとってもリアルに表現することが出来ます。
ちなみに2016年3月現在、three.jsのバージョンはr74です。
環境マッピングとは
環境マッピングを使用すると、周りの環境(風景)をモデル(物体)の表面に映りこませたり透過屈折させたりすることが出来ます。
表面が鏡面のモデルを表現したり
ガラスのようなモデルを表現したり、
することが出来ます。
ただ、これらは実際に周りの風景を反射・透過させているのではなく、予めモデルに風景用のテクスチャを指定しています。
素材を用意しよう
環境マッピングをするには、周りの風景用の画像が必要です。一般的には下のようなキューブマップと呼ばれる上下左右前後の6面の画像を別々に用意して使用することが多いです。
画像はcubemapやskyboxで検索すると探しやすいです。今回は下記サイトよりフリーの画像を使用しております。
http://opengameart.org/content/clouds-skybox-1
テクスチャを読み込もう
前章で用意したキューブマップ用テクスチャを読み込むにはTHREE.CubeTextureLoaderを使用します。
配列に6枚のテクスチャのパスを格納して、loadメソッドの引数に指定すれば読み込めます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | var imgPath = 'テクスチャのパス'; var urls = [ imgPath+'right.jpg', imgPath+'left.jpg', imgPath+'up.jpg', imgPath+'down.jpg', imgPath+'front.jpg', imgPath+'back.jpg' ]; //読み込み後に処理する場合 var cubeLoader = new THREE.CubeTextureLoader(); cubeLoader.load( urls, function( cubeTexture){ //テクスチャ読み込み後の処理 }); //読み込みとは非同期に処理をする場合 //var cubeLoader = new THREE.CubeTextureLoader(); //var cubeTexture = cubeLoader.load(urls); |
配列に画像を格納する順番は前章の画像に書かれている順番通り右・左・上・下・前・後ろです。
反射マッピングを実装しよう
それでは環境マッピングの中でも表面を鏡面のようにできる反射マッピングを実装してみましょう。使用するのはマテリアル生成時のenvMapオプションとreflectivityオプションのみです。envMapプロパティには読み込んだテクスチャ(cubeTexture)を、reflectivityオプションには映り込みの量を0~1で指定します。
前章のテクスチャ読み込み後の処理のコードが下記です。今回はドーナツ型のジオメトリー(TorusGeometry)にしています。
1 2 3 4 5 6 7 8 | var geometry = new THREE.TorusGeometry( 6, 3, 60, 60); var material = new THREE.MeshPhongMaterial({ color: 0xCCCCCC, envMap: cubeTexture, reflectivity: 0.9 }); mesh = new THREE.Mesh( geometry, material); scene.add(mesh); |
下の画像のように周りの風景が反射しているようなモデルが表示されます。
屈折マッピングを実装しよう
次は環境マッピングの中でも表面をガラスのようにさせて奥の風景を屈折透過しているように見せる屈折マッピングを実装してみましょう。使用するのは反射マッピングと同じようにマテリアル生成時のenvMapオプションとreflectivityオプション、さらにrefractionRatioです。refractionRatioは直訳すると屈折率です。例えば牛乳瓶の底の様に厚いガラスの場合、屈折率が高く歪んで見えます。その歪みの大きさを0~1で指定します。デフォルト値は0.98です。
また、1行目のcubeTexture.mapping = THREE.CubeRefractionMappingにより屈折マッピングを使うことを指定します。デフォルト値はTHREE.CubeReflectionMappingで前章の反射マッピングになっています。
1 2 3 4 5 6 7 8 9 10 | cubeTexture.mapping = THREE.CubeRefractionMapping; var geometry = new THREE.TorusGeometry( 6, 3, 60, 60); var material = new THREE.MeshPhongMaterial({ color: 0xCCCCCC, envMap: cubeTexture, refractionRatio: 0.98, reflectivity: 1 }); mesh = new THREE.Mesh( geometry, material); scene.add(mesh); |
下の画像のように奥の風景が屈折透過しているようなモデルが表示されます。
風景を表示させよう
周りの風景は一般的にスカイボックスと呼ばれています。少し複雑な話になってしまうため、今回はコードの紹介のみにさせていただきます。テクスチャ読み込み後のコードが下記です。モデルと同じキューブマップ用テクスチャを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 | var cubeShader = THREE.ShaderLib[ 'cube' ]; cubeShader.uniforms[ 'tCube' ].value = cubeTexture; var skyBoxMaterial = new THREE.ShaderMaterial({ fragmentShader: cubeShader.fragmentShader, vertexShader: cubeShader.vertexShader, uniforms: cubeShader.uniforms, depthWrite: false, side: THREE.BackSide }); var skyMesh = new THREE.Mesh( new THREE.BoxGeometry( 400, 400, 400, 1, 1, 1 ), skyBoxMaterial); scene.add( skyMesh ); |
デモ
数値をブラウザ上のパラメーターによって動的に変更できるdat.GUIを使用したDEMOを用意しました。右上のパラメーターで色々と数値をいじって確認してみてください。反射マップの場合、refractionRatioの値は無効になります。
別ページで同じものを用意しました。
大きいサイズで確認する場合は以下のボタンからどうぞ。
まとめ
いかがでしたでしょうか。環境マッピングはテクスチャを用意するのが少し大変ですが、実装自体はとても簡単です。
ただ、あくまでもこの環境マッピングで表示されるのは静的なテクスチャです。周りの風景が動画であったり、他のモデルがあったとしてももちろん反映されません。そこを解決するのは動的にテクスチャを作成しなければいけないため、かなり大変です。。いつか紹介できればとは思っています。。。
また、前回のテクスチャマップやバンプマップと組み合わせることも出来るので、マテリアルの表現の幅がグッと広がりますね!!