2016/05/03(火) [n年前の日記]
#1 [prog] three.jsでSkybox
先日書いた、three.jsを使った一本道を延々走るソレを見ていて、なんだか背景が歪んでる気がしてきたり。背景は、正距円筒画像(equirectangular画像)を、巨大な球(THREE.SphereGeometry)に貼り付けて描画しているのだけど。もしかして何かやり方を間違ってるのかなと。
てなわけで、SkyboxだかCubemapだか、要は箱にテクスチャを貼りつけて背景とする方法と、球に正距円筒画像を貼り付けて背景とする方法を、それぞれ個別に書いてみて結果を確認してみようかなと。
ちなみに、Skyboxってのは、カメラを囲むように箱を作って、そこに背景テクスチャを貼りつける方法。
「箱の中から箱を見ても、箱にしか見えないのでは? それで背景になるの?」と思うかもしれないけど。90度の画角を持ったテクスチャを貼り付ければ、カメラの向きを変えても背景っぽく見えてくれるという。
対して、球に正距円筒画像を貼り付ける方法は、以下のような感じ。
てなわけで、SkyboxだかCubemapだか、要は箱にテクスチャを貼りつけて背景とする方法と、球に正距円筒画像を貼り付けて背景とする方法を、それぞれ個別に書いてみて結果を確認してみようかなと。
ちなみに、Skyboxってのは、カメラを囲むように箱を作って、そこに背景テクスチャを貼りつける方法。
対して、球に正距円筒画像を貼り付ける方法は、以下のような感じ。
◎ 結果。 :
_Skyboxタイプ。bg_test1.html (DEMO)
_球に正距円筒画像を貼り付けるタイプ。bg_test3.html (DEMO)
※ 表示後、マウスドラッグで向きを変えられます。
結果を眺めてみたけど…。あまり違いが分からないような…。
ということは、先日書いたソレも、別におかしなやり方をしていたわけではなさそうだなと。おそらく、背景に使ってるテクスチャの作り方、というか Vue 5 Easel で作った地形自体がマズかったんだろう…。
それはともかく。正距円筒画像のほうは、画像が荒れちゃってるなと。背景コンバータを使って、6方向の画像から1枚の正距円筒画像を作ってるわけだけど、変換処理をしてるから、どうしても画像が荒れてしまうのだろう…。
_球に正距円筒画像を貼り付けるタイプ。bg_test3.html (DEMO)
※ 表示後、マウスドラッグで向きを変えられます。
結果を眺めてみたけど…。あまり違いが分からないような…。
ということは、先日書いたソレも、別におかしなやり方をしていたわけではなさそうだなと。おそらく、背景に使ってるテクスチャの作り方、というか Vue 5 Easel で作った地形自体がマズかったんだろう…。
それはともかく。正距円筒画像のほうは、画像が荒れちゃってるなと。背景コンバータを使って、6方向の画像から1枚の正距円筒画像を作ってるわけだけど、変換処理をしてるから、どうしても画像が荒れてしまうのだろう…。
◎ Skyboxのやり方。 :
一応、ポイントとなる部分だけを抜き出してメモ。
THREE.ShaderLib[] てのがよく分からないけど、おそらく、頻繁に使うことになるシェーダーについては色々なタイプが定義してあって、ソレを流用すれば楽に記述できるようになってるんじゃないかなと。根拠のない勝手な推測だけど。
箱の各面に貼り付けるために、6枚の画像(6方向の画像)が必要になるけれど。ファイル名と向きは、以下のような配置になってるっぽい。
// テクスチャ読み込み var r = "images/skybox1/"; var urls = [ r + "posx.jpg", r + "negx.jpg", r + "posy.jpg", r + "negy.jpg", r + "posz.jpg", r + "negz.jpg", ]; var texCube = new THREE.CubeTextureLoader().load(urls); texCube.format = THREE.RGBFormat; texCube.mapping = THREE.CubeReflectionMapping; // skybox用のマテリアルを生成 var cubeShader = THREE.ShaderLib["cube"]; var cubeMat = new THREE.ShaderMaterial({ fragmentShader: cubeShader.fragmentShader, vertexShader: cubeShader.vertexShader, uniforms: cubeShader.uniforms, depthWrite: false, side: THREE.BackSide, }); cubeMat.uniforms["tCube"].value = texCube; // Skybox用ジオメトリ生成 var d = 10000; var cubeGeo = new THREE.BoxGeometry(d, d, d); cubeMesh = new THREE.Mesh(cubeGeo, cubeMat); scene.add(cubeMesh);箱用のテクスチャを読み込む際は、THREE.CubeTextureLoader() を使うらしい。
THREE.ShaderLib[] てのがよく分からないけど、おそらく、頻繁に使うことになるシェーダーについては色々なタイプが定義してあって、ソレを流用すれば楽に記述できるようになってるんじゃないかなと。根拠のない勝手な推測だけど。
箱の各面に貼り付けるために、6枚の画像(6方向の画像)が必要になるけれど。ファイル名と向きは、以下のような配置になってるっぽい。
┌──┐ │posy│ │ │ ┌──┼──┼──┬──┐ │negx│posz│posx│negz│ │ │ │ │ │ └──┼──┼──┴──┘ │negy│ │ │ └──┘このあたりは、 _Three.js : WebGL Cube テクスチャパノラマ背景の画像配置が解る表示 の実演が分かりやすいかもしれず。
◎ 球に貼り付けるやり方。 :
// テクスチャ読み込み var texEqu = new THREE.TextureLoader().load("images/bg.jpg"); texEqu.anisotropy = renderer.getMaxAnisotropy(); // texEqu.mapping = THREE.EquirectangularReflectionMapping; texEqu.mapping = THREE.UVMapping; // 背景用ジオメトリ生成 var d = 6000; var geo = new THREE.SphereGeometry(d, 32, 32); geo.scale(-1, 1, 1); // コレを指定しないと背景が左右反転してしまう var mat = new THREE.MeshBasicMaterial({ map: texEqu, fog: false, }); bgMesh = new THREE.Mesh(geo, mat); scene.add(bgMesh);
[ ツッコむ ]
以上です。