Three.jsを使って、作ってみた

プログラミング関連の事を色々書いています(^^) 週末はレストランやコンビニのお菓子のことを書いています。

Three.js  影の描画(シャドウマッピング)

今回は、Three.jsの「影」について、書きます。


今回の内容は「シャドウマッピング」と専門的には言うのかな?
Three.jsの場合、影をつけるには、4つの準備が必要です。

  1. レンダラー・・・shadowMapEnabled = true
  2. 光源・・・castShadow = true
  3. 物体1・・・castShadow = true
  4. 物体2(地面など)・・・receiveShadow = true

この4つのオブジェクトのプロパティに「影(シャドウマッピング)の有効化」を設定する必要があります。

ややこしいのが物体の影の設定です。
影を受ける物体には、「receiveShadow = true」にして、影を作る物体には、「castShadow = true」にします。
写真で、解説するとこんな感じです。
f:id:gupuru:20131212202402p:plain
写真の場合だと、影を作っているのは、青い球です。なので青い球に「castShadow = true」を設定します。地面であるピンク色の物体は、影を受けているので、「receiveShadow = true」を設定します。

地面は「receiveShadow = true」、それ以外の物体は「castShadow = true」と覚えとくと、いいと思います。


で、実際のコードはコチラです。

①レンダラー

//レンダラーオブジェクトの生成
var renderer = new THREE.WebGLRenderer({antialias: true});   

//影の有効化(レンダラー)
renderer.shadowMapEnabled = true; 

②光源

//光源(DirectionalLight)の生成
var light = new THREE.DirectionalLight(0xcccccc,1.6);   
       
//影の有効化(光源) 
light.castShadow = true;     

③物体1

//球の生成
var sphere = new THREE.Mesh(                                  
                  new THREE.SphereGeometry(50, 100, 100),    
                  new THREE.MeshPhongMaterial({                          
                     color: 0x0000ff                                     
                       }));

//影の有効化         
sphere.castShadow = true;  
//シーンオブジェクトに追加 
scene.add(sphere);                  

④物体2

//地面(PlaneGeometry)の生成
var plane =  new THREE.Mesh(                                       
             new THREE.PlaneGeometry(1000, 1000, 1, 1),
              new THREE.MeshLambertMaterial({                       
                side: THREE.DoubleSide,                       
                 color: 0xCD5C5C                             
                }));                      

//影の有効化          
plane.receiveShadow = true;
//シーンオブジェクトに追加 
scene.add(plane);                 

実行すると、こんな感じです。
f:id:gupuru:20131212200728p:plain

で、上の影をよく見ると、少しギザギザです。
もっと綺麗に影を描画する方法は、このようにします。

//DirectionalLight
var light = new THREE.DirectionalLight(0xcccccc,1.6);          
//影の有効化   
light.castShadow = true;  
//影の高細密化
light.shadowMapWidth = 2048;     //追加
light.shadowMapHeight = 2048;   //追加

光源を生成している所に、「shadowMapWidth」と「shadowMapHeight」を追加すれば、綺麗な影が描画されます。
実行すると、こうなります。
f:id:gupuru:20131212201420p:plain
綺麗な影が出ています。

デフォルトでは、「shadowMapWidth」と「shadowMapHeight」は、それぞれの値は「512」となっています。
「shadowMapWidth」と「shadowMapHeight」の値が大きいほど、処理は重くなります。当然ですが(笑)


最後に、影を受けるのは、地面だけでは、ありません。
他の物体も影を受ける時があります。
f:id:gupuru:20131212203811p:plain
上の写真のように、「赤色の球の影」を「青い球」が受けています。(赤色の枠線で囲った所です。
このようにするには、青い球に「receiveShadow = true」を追加すれば、出来ます。
実際のコードは、これです。

//青い球の生成
var sphere = new THREE.Mesh(                                  
                  new THREE.SphereGeometry(50, 100, 100),    
                  new THREE.MeshPhongMaterial({                          
                     color: 0x0000ff                                     
                       }));

//影の有効化         
sphere.castShadow = true;  
sphere.receiveShadow = true; //追加
//シーンオブジェクトに追加 
scene.add(sphere);                  

//赤い球の生成
var sphere2 = new THREE.Mesh(                                  
                  new THREE.SphereGeometry(50, 100, 100),                           
                  new THREE.MeshPhongMaterial({                          
                     color: 0xFF0000                                         
                       }));
      
sphere2.castShadow = true;     
scene.add(sphere2);                

//地面(PlaneGeometry)の生成
var plane =  new THREE.Mesh(                                       
             new THREE.PlaneGeometry(1000, 1000, 1, 1),
              new THREE.MeshLambertMaterial({                       
                side: THREE.DoubleSide,                       
                 color: 0xCD5C5C                             
                }));                      

//影の有効化          
plane.receiveShadow = true;
//シーンオブジェクトに追加 
scene.add(plane);                 


Three.jsの影は、今回書いたこと以外にも、細かい設定が色々あります。
その辺は、また今度書きます。


これで終わりです。
ご不明な点などがありましたら、遠慮なくご質問ください。
ありがとうございました!

広告を非表示にする