Three.jsのMeshPhysicalMaterialを使って、ガラスのマテリアルを作りながら、ガラスの破片が舞い落ちるSampleDemoにあるようなものを作って行こうかと思います。
MeshPhysicalMaterialの備忘録も兼ねてブログにしてみました。もしよろしければチャレンジしてみてください。
【Sample Demo】https://misora.main.jp/glass2/
【作品サイト】https://misora.main.jp/glass/
1.Glass Material (MeshPhysicalMaterial)
Three.jsのMeshPhysicalMaterialを使って、反射を再現していきます。MeshPhysicalMaterialには、リファレンスにあるように、さまざまなパラメータがあるので、パラメータを調整できるデモサイトを作りました。ぜひご利用ください。
MeshPhysicalMaterial – threejs.orgthree.js docs
sbcode.netMeshPhysicalMaterial - Three.js Tutorials
反射素材としてHDRIを使用します。以下のサイトなどから、HDRI素材のダウンロードをお願いします。サイズは1Kで十分だと思います。
Poly Haven • Poly HavenThe Public 3D Asset Librarypolyhaven.comIndustrial Sunset (Pure Sky) HDRI • Poly HavenDownload this free HDRI from Poly Haven
three.js
HDRIの設定(反射に使用します)
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
const scene = new THREE.Scene()
scene.background = new THREE.Color('#222');
// HDRI
new RGBELoader().setPath( './' ).load( 'industrial_sunset_puresky_1k.hdr', function ( texture ) {
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.background = texture;
scene.environment = texture; // <= 必須
});
MeshPhysicalMaterial(ガラス素材なのでtransmission=1.0)
const material = new THREE.MeshPhysicalMaterial({
//envMap: new THREE.TextureLoader().load("sample.png"),
color: 0xffffff,
//
roughness: 0.0,
metalness: 0.0,
//クリアコート層の強度
clearcoat: 1.0, // Default:0.0, max:1.0
clearcoatRoughness: 1.0, // Default:0.0, max:1.0
//clearcoatMap : new THREE.TextureLoader().load("sample.png"),
//非金属材料の屈折率
ior: 1.1, //from 1.0 to 2.333. Default is 1.5
//
reflectivity: 0.01, // Default:0.0, max:1.0
//
iridescence: 1.0, // 強度 Default:0.0, max:1.0
iridescenceIOR: 1.0, // 虹の屈折率 Default is 1.3 1.0~2.33 1.3
//光沢層の強度、
sheen: 1.0, // Default:0.0 max:1.0 0.1
sheenRoughness: 0.0,
sheenColor : 0xFFFFFF,
//鏡面強度
specularIntensity : 10.0, // 1.0
specularColor : 0xFFFFFF,
//specularColorMap :new THREE.TextureLoader().load("sample.png"),
// 厚み
thickness:10.00, //
//thicknessMap: new THREE.TextureLoader().load("sample.png"),
//伝搬
transmission: 1.0, // <= ガラス
//transmissionMap: new THREE.TextureLoader().load("sample.png"),
//
transparent: true,
opacity: 1.0,
wireframe: false,
});
テスト用のBoxGeometryの作成
const geometry = new THREE.BoxGeometry( 3, 3, 0.1 );
const cube = new THREE.Mesh( geometry, material );
cube.position.set(0,0,0);
scene.add( cube );
画像にあるようなサイトができると思います。マテリアルの微調整は、デモサイトから数値を調整する等で、お好みなものに調整してください。
2.Broken Glass Object
Blenderを使って、下のような割れたガラスのようなオブジェクトを作成します。
Blender のアドオン「Cell Fracture」を有効化
Blenderのアドオンの「Cell Fracture」を使って作成します。まずアドオンを有効にしましょう。
ガラスのように薄いCubeを作成する
編集モードで細分化します。横・縦にのみ、幅には細分化しないでください。
Cell Fractureで分割
オブジェクト > クイックエフェクト > Cell Fracture で起動
ノイズ:1、再帰:1 でOKを押す。(実行)
giTFで出力
Three.jsで使えるように、.glbファイル(glass.glb)で出力しましよう。(圧縮で出力するとDRACOLoaderが必要になります)
出力できれば、OKです!(glass.glb)
3.Three.jsで表示させる(マテリアルと組み合わせる)
three.jsでガラスオブジェクトの.glbファイル(glass.glb)を読み込んで、マテリアルを適用させていきましょう
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
// import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
let modelSet = false; //モデルの読み込みが完了したかのフラグ
let GlassObject;
const loader = new GLTFLoader();
loader.load( 'glass.glb', function ( gltf ) {
const model = gltf.scene;
let num = 0;
model.traverse((object) => { //モデルの構成要素をforEach的に走査
if(object.isMesh) { //その構成要素がメッシュだったら
object.number = num;
object.material = material.clone();
// 番号付ける
num++;
}
})
GlassObject = model;
GlassObject.scale.set(3.5, 3.5, 3.5);
scene.add(GlassObject);
modelSet = true;
})
ガラス片が、バラバラに上から落ちてきて、ループするアニメーションを作成しましょう。
let modelSet = false; //モデルの読み込みが完了したかのフラグ
let GlassObject;
const loader = new GLTFLoader();
loader.load( 'glass.glb', function ( gltf ) {
const model = gltf.scene;
let num = 0;
model.traverse((object) => { //モデルの構成要素をforEach的に走査
if(object.isMesh) { //その構成要素がメッシュだったら
object.number = num;
object.material = material.clone();
//位置をバラけさせる
object.position.set(
(Math.random()-0.5)*3,
(Math.random()-0.5)*8,
(Math.random()-0.5)*3
);
//回転を加える
object.rotation.set(
(Math.random()-0.5)*Math.PI*2,
(Math.random()-0.5)*Math.PI*2,
(Math.random()-0.5)*Math.PI*2,
);
// 落下のランダムスピードを付ける
object.speedY = 1.0 + Math.random();
// 番号付ける
num++;
}
})
GlassObject = model;
GlassObject.scale.set(3.5, 3.5, 3.5);
scene.add(GlassObject);
modelSet = true;
})
AnimationLoop
const clock = new THREE.Clock();
function renderLoop() {
stats.begin();//stats計測
const delta = clock.getDelta();//animation programs
if(modelSet){
GlassObject.children.forEach((element, index) => {
// 落下させる
element.position.y -= element.speedY * delta * 0.2;
// y軸が-4以下になったら上に再表示させる
if(element.position.y < -4){
element.position.x = (Math.random()-0.5)*3;
element.position.y = 4;
element.position.z = (Math.random()-0.5)*3;
}
// 回転させる
element.rotation.x += delta * 0.1;
element.rotation.y += delta * 0.1;
element.rotation.z += delta * 0.1;
});
}
renderer.render(scene, camera) // render the scene using the camera
requestAnimationFrame(renderLoop) //loop the render function
stats.end();//stats計測
}
renderLoop() //start rendering
4.完成!
簡単でしたね!
【Sample Demo】https://misora.main.jp/glass2/
【MeshPhysicalMaterialパラメータサイト】https://misora.main.jp/physicalm/
【作品サイト】https://misora.main.jp/glass/
作品のサイトでは、scene.backgroundをNoneにして暗い空間に、ガラスのMaterialパラメータでreflectivity=1.0、などにしています。あとPostEffectsのUnrealBloomPassで強調つつ、雰囲気を作りをしました。
これからも、いろいろなところで必須になると思いますので、ぜひ参考にしてみてください。
以上、記事が良かったらXのフォロー、また、もう一つ私の記事をご覧ください。