three.js概論#6
2024/6/11
Shadow
three.jsには、影を実装するための組み込みのソリューションが用意されている。
仕組み
three.jsは、1つのレンダリングを行う際、まず影を落とすと想定されるライトごとにレンダリングを行う。これらのレンダリングは、ライトの見え方をカメラのようにシミュレートする。これらのライトのレンダリング中に、MeshDepthMaterial
がすべてのメッシュのマテリアルを置き換える。
結果はテクスチャとシャドウマップとして保存される。
シャドウマップは直接見ることはできないが、シャドウを受けるオブジェクトのマテリアルに適用され、ジオメトリに投影される。
シャドウマップのサンプル影を有効にする
まず、renderer
のshadowMap
プロパティを有効にする。
renderer.shadowMap.enabled = true;
そして、影を落とすオブジェクトにcastShadow
プロパティを、影を受けるオブジェクトにはreceiveShadow
プロパティを設定する。
mesh.castShadow = true;mesh.receiveShadow = true;
最後に、ライトのcastShadow
プロパティを設定する。
PointLight
, SpotLight
, DirectionalLight
の3つのライトのみが影をサポートしている。
directionalLight.castShadow = true;
シャドウマップの設定
three.jsは各ライトに対してシャドウマップを生成し、それを使用して影を描画する。
このシャドウマップには、ライトのshadow
プロパティを使ってアクセスすることができる。
directionalLight.castShadow = true;console.log(directionalLight.shadow);
レンダーサイズ
シャドウマップの解像度は、shadow.mapSize
プロパティのwidth
とheight
プロパティで設定できる。
デフォルトは512x512
で2のべき乗の値にする必要がある。
directionalLight.shadow.mapSize.width = 1024;directionalLight.shadow.mapSize.height = 1024;
Near/Far
シャドウマップのレンダリングにはカメラ使っており、このカメラは他のカメラと同じプロパティを持つので、near
とfar
プロパティを使って影がどこまで表示されるかを設定できる。
また、CameraHelperを、影のカメラに適用することで、影のカメラの位置やnear
、far
を確認することができる。
// カメラヘルパーを作成const directionalLightCameraHelper = new THREE.CameraHelper( directionalLight.shadow.camera,);scene.add(directionalLightCameraHelper);
// カメラヘルパーを非表示にする場合directionalLightCameraHelper.visible = false;
// シャドウマップのnear/farを設定directionalLight.shadow.camera.near = 1;directionalLight.shadow.camera.far = 6;
カメラの範囲
DirectionalLight
のシャドウカメラは、デフォルトでOrthographicCamera
を使用している。
そのため、left
, right
, top
, bottom
プロパティを使って、シャドウカメラの範囲を設定できる。
範囲が小さいほど、シャドウマップの解像度が高くなる。
directionalLight.shadow.camera.top = 2;directionalLight.shadow.camera.right = 2;directionalLight.shadow.camera.bottom = -2;directionalLight.shadow.camera.left = -2;
ぼかし
radius
プロパティを使って、シャドウマップのぼかしを設定できる。
directionalLight.shadow.radius = 10;
シャドウマップのアルゴリズム
シャドウマップには異なる種類のアルゴリズムを適用することができる。
BasicShadowMap
: デフォルトのシャドウマップ。速度が速いが、品質が低い。PCFShadowMap
: ピクセルごとのぼかしを適用することで、シャドウの品質を向上させる。PCFSoftShadowMap
:PCFShadowMap
よりもぼかしを強くすることで、より柔らかい影を描画する。VSMShadowMap
: バリアンスシャドウマップ。シャドウマップの品質を向上させる。
変更するには、shadowMap.type
プロパティを設定する。
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
Particle
three.jsにおけるパーティクルは、3Dグラフィックスのシーン内で小さな点や粒子のようなオブジェクトを大量に描画するために使用される。パーティクルは、煙、火花、星、雨などのエフェクトを表現するのに適しており、リアルなシミュレーションや視覚効果を作り出すために広く利用される。
パーティクルのメリットは、フレームレートを落とさずに画面上に何十万ものパーティクルを配置できること。
欠点は、各パーティクルを構成する平面が常にカメラに向かっているところ。
パーティクルの作成には、BufferGeometry
、PointsMaterial
、Points
を使用する。
Geometry
基本的なジオメトリを使用でき、この場合はジオメトリの各頂点がパーティクルになる。
const particlesGeometry = new THREE.SphereGeometry(1, 32, 32);
PointsMaterial
- PointsMaterial という特別なマテリアルを使用する。
PointsMaterial
は、パーティクルのサイズを制御するsize
や、パーティクルに遠近感を出すsizeAttenuation
などの、パーティクル専用の固有のプロパティが用意されている。
const particlesMaterial = new THREE.PointsMaterial({ size: 0.02, sizeAttenuation: true,});
Points
最後にMesh
と同じ方法で、Pointsクラスを使用して、パーティクルを作成する。
const particles = new THREE.Points(particlesGeometry, particlesMaterial);scene.add(particles);
Custom geometry
組み込みジオメトリではなく、カスタムジオメトリを作成するには、BufferGeometry
を使用し、position
属性を追加する。
const particlesGeometry = new THREE.BufferGeometry();const count = 500;
const positions = new Float32Arry(count * 3);
for (let i = 0; i < count * 3; i++) { //値が - 5.0から5.0になるように調整 positions[i] = (Math.random() - 0.5) * 10;}
particlesGeometry.setAttribute( "position", new THREE.BufferAttribute(positions, 3),);
Color, map, alpha map
PointsMaterial
には、パーティクルの色を設定するcolor
プロパティや、テクスチャを設定するmap
プロパティ、透明度を設定するalphaMap
プロパティなどがある。
// パーティクルの色を設定PointsMaterial.color = new THREE.Color("#ff88cc");
// パーティクルにテクスチャを設定const textureLoader = new THREE.TextureLoader();const particleTexture = textureLoader.load("hoge.png");particlesMaterial.transparent = true;particlesMaterial.alphaMap = particleTexture;
// パーティクルの深度書き込みを無効にして、他のパーティクルの後ろに隠れないようにするparticlesMaterial.depthWrite = false;
// パーティクルのブレンディングを設定particlesMaterial.blending = THREE.AdditiveBlending;
頂点カラー
各パーティクルに色を設定するには、color
属性を使用する。
const colors = new Float32Array(count * 3);for (let i = 0; i < count * 3; i++) { colors[i] = Math.random();}particlesGeometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));
// マテリアルの頂点カラーを有効にするparticlesMaterial.vertexColors = true;
パーティクルのアニメーション
Attributesを更新してアニメーションさせる
各頂点を更新するには、position
属性を更新する。
for (let i = 0; i < count; i++) { let i3 = i * 3;
const x = particlesGeometry.attributes.position.array[i3]; particlesGeometry.attributes.position.array[i3 + 1] = Math.sin( elapsedTime + x, );}
// ジオメトリの更新を通知particlesGeometry.attributes.position.needsUpdate = true;