この記事はthree.jsについてのシリーズ記事の一つです。 最初の記事はThree.jsの基礎知識です。 まだ読んでない人は、そちらから先に読んでみるといいかもしれません。
Three.jsはいくつかの種類のマテリアルを提供しています。 これらは、オブジェクトがどのようにシーンに表示されるかを定義します。 どのマテリアルを使うべきかは、皆さんが何をしたいかによります。
マテリアルの属性の設定方法は、だいたい2つです。 一つは、表示される前の作成時です。
const material = new THREE.MeshPhongMaterial({ color: 0xFF0000, // red (can also use a CSS color string here) flatShading: true, });
もう一つは作成後です。
const material = new THREE.MeshPhongMaterial(); material.color.setHSL(0, 1, .5); // red material.flatShading = true;
THREE.Color
型の属性は設定方法が複数あることに注意してください。
material.color.set(0x00FFFF); // same as CSS's #RRGGBB style material.color.set(cssString); // any CSS color, eg 'purple', '#F32', // 'rgb(255, 127, 64)', // 'hsl(180, 50%, 25%)' material.color.set(someColor) // some other THREE.Color material.color.setHSL(h, s, l) // where h, s, and l are 0 to 1 material.color.setRGB(r, g, b) // where r, g, and b are 0 to 1
作成時に、16進数かCSS文字列を渡すことができます。
const m1 = new THREE.MeshBasicMaterial({color: 0xFF0000}); // red const m2 = new THREE.MeshBasicMaterial({color: 'red'}); // red const m3 = new THREE.MeshBasicMaterial({color: '#F00'}); // red const m4 = new THREE.MeshBasicMaterial({color: 'rgb(255,0,0)'}); // red const m5 = new THREE.MeshBasicMaterial({color: 'hsl(0,100%,50%)'}); // red
では、three.jsのマテリアルの設定の説明をしましょう。
MeshBasicMaterial
は光源の影響を受けません。
MeshLambertMaterial
は頂点でのみ光を計算します。
一方で、MeshPhongMaterial
は全てのピクセルで光を計算します。
MeshPhongMaterial
は、specularによるハイライトもサポートします。
MeshPhongMaterial
のshininess
設定は特定のハイライトの輝きを決めます。デフォルトは30です。
MeshLambertMaterial
かMeshPhongMaterial
のどちらかで、colorに対してemissive
属性を設定し、
色を黒(phongならshininess
を0)に設定すると、ちょうどMeshBasicMaterial
のように見えることに注意してください。
MeshPhongMaterial
はMeshBasicMaterial
やMeshLambertMaterial
と同じようにできるのに、なぜ3種もあるのでしょうか。
理由は、より洗練されたマテリアルは、描写するのにGPUパワーを必要とするためです。
携帯電話といった、遅いGPCでは、より簡単なマテリアルを使うことで、描画に必要なGPUパワーを削減できるかもしれません。
また、余計な機能を必要としないなら、一番シンプルなマテリアルを使用するとよいです。
光源やspecularによるハイライトが不要なら、MeshBasicMaterial
を使うこともできます。
MeshToonMaterial
はMeshPhongMaterial
に似ていますが、一点大きな違いがあります。
連続的にシェーディングするのではなく、グラデーションマップ(X×1のテクスチャ)を使ってシェーディングの方法を決めます。
デフォルトは明るさの始まりが70%、終わりが100%のグラデーションマップを適用しますが、自分で決めたグラデーションマップを適用することもできます。
これにより、まるでアニメのようなツートーンになります。
続いて2つの物理ベースレンダリングのマテリアルがあります。 物理ベースレンダリングはよくPBRと略します。
上記のマテリアルは、3Dに見えるマテリアルを簡単な数学で作っていますが、 これは現実世界で本当に起きている現象にのっとっていません。 2つのPBRマテリアルはもっと複雑な数学を使い、現実世界に近づいています。
一つ目はMeshStandardMaterial
です。MeshPhongMaterial
とMeshStandardMaterial
の
最大の違いは、異なるパラメータを使っていることです。
MeshPhongMaterial
はshininess
設定があります。
MeshStandardMaterial
はroughness
とmetalness
の2つの設定があります。
基本的に、roughness
はshininess
の逆です。
野球ボールがほとんど反射しないように、とても粗いのものがある一方で、
とても光沢があるビリヤード玉のように、粗くないものもあります。
roughnessは0から1の間をとります。
もう一つの設定で、metalness
は、マテリアルの金属っぽさです。
金属は非金属と異なった振る舞いをします。
0は非金属で、1は金属です。
ここに、MeshStandardMaterial
のサンプルがあります。
右に行くにつれて、roughness
は0から1に変わります。
下に行くにつれて、metalness
は0から1に変わります。
MeshPhysicalMaterial
は、MeshStandardMaterial
と同様ですが、
clearcoat
パラメータが追加されています。このパラメータは、0から1につれて、
clearcoat光沢層が適用されます。
また、clearCoatRoughness
パラメータも追加されていて、これは光沢層の粗さを決定します。
ここに、上と同じmetalness
とroughness
のグリッドがあります。
ただし、clearcoat
とclearCoatRoughness
の設定が付いています。
様々な標準のマテリアルのうち、高速なものから低速なものを並べると、
MeshBasicMaterial
➡ MeshLambertMaterial
➡ MeshPhongMaterial
➡
MeshStandardMaterial
➡ MeshPhysicalMaterial
になります。
低速なマテリアルは、より現実味のある見た目のシーンを作ることができますが、
パワーが低いデバイスやモバイル端末では、より高速なマテリアルを使うようにコードを設計する必要があります。
続いて、特別な用途に使う3つのマテリアルがあります。
ShadowMaterial
は影から作られたデータを得るのに使われます。
まだ影については説明していませんでしたね。
その際には、このマテリアルを使って、シーンの裏で何が起きているのか、のぞいてみたいと思います。
MeshDepthMaterial
は各ピクセルの深度を描写します。
カメラの負のnear
にあるピクセルは0、負のfar
にあるピクセルは1です。
また別の機会に、特定の特殊効果がこのデータを使うかもしれません。
MeshNormalMaterial
はジオメトリの法線を表示します。
法線は、特定の三角形かピクセル表面の方向です。
MeshNormalMaterial
は見えている空間の法線を描画します(法線はカメラに依存します)。
xは赤、 yは緑そして zは青なので、 物体の右側はpink、 左側はaqua、 上側はlight green、 下側はpurple、 そして画面側はlavenderになるでしょう。
ShaderMaterial
は、three.jsのシェーダーシステムを使ったカスタムマテリアルを作るためのものです
RawShaderMaterial
は、three.jsの補助なしで、完全に独自シェーダーを作るためのものです。
これらのトピックはどちらも大きいため、後ほど説明します。
全てのマテリアルはMaterial
によって決められた設定を共有しています。
それらはドキュメントを見てください。けれども、最も一般的に使われる2つの属性について説明しましょう。
flatShading
:物体の面が分割されて見えるか、滑らかに見えるか。デフォルトはfalse
です。
side
:三角形の両面を表示するか。デフォルトはTHREE.FrontSide
です。
ほかのオプションは THREE.BackSide
とTHREE.DoubleSide
(両面)です。
threeで描写されるほとんどの3Dオブジェクトは、たぶん不透明な固体です。
そのため、裏面(固体の内側を向いている面)は描画する必要はありません。
side
を設定する最も一般的な理由は、平面やほかの固体ではないオブジェクトのためです。
これらは、三角形の裏面を見ることが普通だからです。
ここに、THREE.FrontSide
とTHREE.DoubleSide
で描画された6つの平面があります。
マテリアルについては、本当にたくさん考えることがあり、実際にはもっとたくさんの説明したいパラメータがあります。 特に、私たちは多くのオプションの話につながる、テクスチャをほとんど無視していました。 テクスチャを説明する前に、休憩を取って、開発環境のセットアップを説明する必要があります。