Three.jsをはじめよう。マテリアルとテクスチャでリアルに【第3回】

前回は作成した立方体をマウスで自由に動かす事ができました。しかし、画面の中にあるのはまだ、無機質な「緑色の箱」ですよね。WEB制作でクライアントから求められるのは、「もっと商品の良さが質感や体験から伝わるように」というリアリティの追求です。

例えば、高級腕時計のサイトなら金属の輝きが、オーガニック化粧品のサイトなら清潔感のある容器の質感が不可欠です。これらを表現するのが、今回学ぶ「マテリアル(素材)」と「テクスチャ(模様)」です。

今回は、質感や体験が伝わるようなマテリアルとテクスチャの使い方について学んでいきましょう。

よく見るマテリアルBasicとStandard

Three.jsには多くのマテリアルが用意されていますが、まず覚えるべきは次の2つです。

MeshBasicMaterial(光を無視する素材)

第1回・第2回で私たちが使っていたのがこちらです。
ライトを無視したマテリアルで開発時にライトを無視して表示を確認したい際に役立ちます。

特徴
ライト(照明)がなくても色が見えます。
欠点
影や光の反射が一切ないため、のっぺりとした印象になり、立体感に欠けます。
使い所
背景パネルや、常に一定の発色をさせたいUI要素など。開発時の表示確認。

詳しい説明や使い方に関しては、公式ドキュメントの【MeshBasicMaterial】をご参照ください。

MeshStandardMaterial(光に反応する素材)

こちらは物理ベースレンダリングのマテリアルです。
光の反射や散乱など現実の物理法則に従った現象を再現します。

特徴
現実世界の物理法則(PBR: 物理ベースレンダリング)に基づいた計算を行います。
利点
光の当たり方によって影ができたり、金属のような反射をしたりします。
注意点
空間内に「ライト(照明)」を設置しないと、真っ黒になって何も見えません。

詳しい説明や使い方に関しては、公式ドキュメントの【MeshStandardMaterial】をご参照ください。

テクスチャで「質感」を作る

マテリアルが「素材の種類」だとしたら、テクスチャはそこに貼る「画像データ」です。単なる色の指定ではなく、木目やレンガ、ロゴマークなどの画像を貼ることで、質感を表現できます。

TextureLoader:画像読み込み担当

JavaScriptで画像を読み込むには、TextureLoader という機能を使います。

const textureLoader = new THREE.TextureLoader();
const colorTexture = textureLoader.load('/textures/brick_color.jpg');

このように読み込んだ画像を、マテリアルの map というプロパティに渡すだけで、物体に画像が貼り付けられます。

画像のサイズに注意

WEBサイトの表示速度を重視する私たちにとって、テクスチャのサイズは重要です。2Kや4Kの巨大な画像を使えば綺麗になりますが、サイトが重くなっては本末転倒です。

通常、WEB用であれば「2の累乗(512×512, 1024×1024など)」のサイズで作成するのが、GPU(グラフィックチップ)にとって最も効率が良く、よりスムーズなパフォーマンスが実現されます。

もっとリアルに!「マップ」の使い分け

実は、テクスチャは色(カラー)を塗るためだけのものではありません。複数の画像を重ね合わせることで、驚くほどのリアリティを生み出すことができます。これを「マルチマップ」と呼びます。

Color Map:表面に色を適用

Color Map(カラーマップ)は、物体の基本的な「色・模様」を決める画像です。

Normal Map:表面の凹凸をシミュレート

Normal Map(ノーマルマップ)は、画像の色情報を使って、表面の細かな「デコボコ感」を表現します。実際にモデルの形状を変えずに、光の反射だけを操作してデコボコに見せる為、処理を増やさずにリアルな表面のディテールを追加できます。

Roughness Map:表面の粗さを表現

Roughness Map(ラフネスマップ)は、「表面の粗さ」を制御します。この画像が黒い部分はツルツル(鏡のように反射)、白い部分はザラザラ(光を拡散)します。一つの物体の中に「ここは光るけど、ここは光らない」という差をつけたい時に重宝します。

UVマッピング:3D空間の「住所」

ここで、少しだけ専門的な「UVマッピング」という概念に触れておきましょう。
「2Dの平らな画像を、どうやって3Dの立体にピッタリ貼り付けているのか?」という疑問への答えです。

UV座標とは

3Dモデルの各頂点には、画像上のどの位置を指すかという
(u, v)
という座標が割り振られています。

  • Uは横方向の座標(0〜1)
  • Vは縦方向の座標(0〜1)

ミカンの皮の例え

よく例えられるのが「ミカンの皮」です。球体のミカンの皮を剥いて、平らに広げた状態がテクスチャ画像です。逆に、その皮を再び球体に合わせて包み直す作業がUVマッピングです。

もし、ロゴマークが変に伸びて表示される場合は、このUV設定がズレている可能性があります。

実際にリアルな質感を実装してみよう

では、第2回までのコードをベースに、輝きを感じる球体を作ってみましょう。
前回までと変わり球体へ変更してみました。色々試してみましょう。

// --- 1. ライトを追加(StandardMaterialを使うなら必須!) ---
const ambientLight = new THREE.AmbientLight(0xffffff, 0.7); // 全体を照らす光
scene.add(ambientLight);

const pointLight = new THREE.PointLight(0xffffff, 7, 50, 1.0); // 強いスポット光
pointLight.position.set(4, 4, 4);
scene.add(pointLight);

const pointLightHelper = new THREE.PointLightHelper(pointLight); // 照明がどこにあるか可視化
scene.add(pointLightHelper);

// --- 2. テクスチャの読み込み(テクスチャはambientcg.comを利用) ---
const textureLoader = new THREE.TextureLoader();
const earthTexture = textureLoader.load("Ice002_1K-JPG_Color.jpg");

// --- 3. マテリアルの設定 ---
const material = new THREE.MeshStandardMaterial({
    map: earthTexture,       // 地面の模様
    roughness: 0.4,          // ほどよいツヤ感
    metalness: 0.2           // ほんのり金属感
});

// --- 4. メッシュの作成 ---
const geometry = new THREE.SphereGeometry(1, 64, 64); // 滑らかな球体
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);

これで、光を受けて陰影ができる、立体的な球体が完成しました。

質感ひとつでストーリーが変わる

お疲れ様でした!「ただの箱」が、マテリアルとテクスチャによって質感や体験が伝わるプロセスを体感いただけたでしょうか。

最初は難しく感じるかもしれませんが、「このスライダーを動かしたらどう光るかな?」と実験を繰り返すことが、上達への一番の近道です。

今回の学びのポイント

マテリアル
色々なマテリアルを試して面白い!使える!を探しましょう。
TextureLoader
画像を読み込み、物体をよりリアルに。
マルチマップ
色だけでなく、デコボコやツヤも画像で制御する。
UV座標
2D画像を3Dに正しく貼るための地図。

さて、今の状態でもかなり綺麗になりましたが、実はまだ足りないものがあります。それは、物体が地面に落とす「影」です。

次回、第4回では3Dに立体感を持たせるために最も重要な「光と影の演出(ライティングとシャドウ)」について学びます。

それでは、また次回!