マテリアルコンポーネントは、実体に外観を与えます。色、不透明度、テクスチャなどのプロパティを定義することができます。これは、形状を提供するジオメトリコンポーネントと対になっていることが多いです。

カスタムマテリアルを登録してマテリアルコンポーネントを拡張し、様々な視覚効果を提供することができます。

# Example

デフォルトの標準マテリアルを使用して赤いマテリアルを定義してみます。

<a-entity geometry="primitive: box" material="color: red"></a-entity>

別のマテリアルを使用した例です。

<a-entity geometry="primitive: box" material="shader: flat; color: red"></a-entity>

カスタムマテリアルを使用した例です。

<a-entity geometry="primitive: plane"
          material="shader: ocean; color: blue; wave-height: 10"></a-entity>

# プロパティ

マテリアルコンポーネントはいくつかの基本プロパティを持ちます。適用されるマテリアルタイプによって、さらに多くのプロパティを利用できます。

Property Description Default Value
alphaTest 透明度のアルファテスト閾値。 0
depthTest マテリアルのレンダリング時に深度テストが有効かどうか。 true
flatShading THREE.StandardShadingではなく、THREE.FlatShadingを使用する。 false
npot non-power-of-two (NPOT) テクスチャの設定を使用します。texture. false
offset 使用するテクスチャーのオフセット。 {x: 0, y: 0}
opacity 透明度の範囲。transparent プロパティが true でない場合、マテリアルは不透明のままとなり、opacity は色にのみ影響します。 1.0
repeat 使用するテクスチャの繰り返し。 {x: 1, y: 1}
shader 使用するマテリアルを指定します。デフォルトは標準マテリアルフラットマテリアルまたは登録されたカスタムシェーダーマテリアルに設定可能です。 standard
side メッシュのどの面をレンダリングするか。frontbackdoubleのいずれかを指定できます front
transparent マテリアルが透明かどうか。透明なエンティティは、透明でないエンティティの後にレンダリングされます。 false
vertexColors マテリアルのシェーディングに頂点カラーと面カラーのどちらを使用するか。nonevertexfaceのいずれかを指定します。
                                        | none          |

| visible | マテリアルが見えるかどうか。レイキャスターは不可視のマテリアルを無視します。 | true | | blending | WebGLRenderer に送信されるマテリアルの RGBAlpha のブレンディングモードです。nonenormaladditivesubtractivemultiply のいずれかを指定します。 | normal | | dithering | マテリアルをノイズでディザリングするかどうか。ライティングによるグラデーションのようなバンディングを除去します。 | true |

# イベント

イベント名 概要
materialtextureloaded テクスチャが素材に読み込まれた状態。
materialvideoloadeddata ビデオデータが読み込まれ、再生される。
materialvideoended 動画テクスチャの場合、動画が終了したときに発行されます(loop では動作しない場合があります)

# ビルトインマテリアル

A-Frameには、いくつかのマテリアルがビルトインされています。

# standard

スタンダードマテリアルは、デフォルトのマテリアルです。物理ベースのTHREE.MeshStandardMaterial (opens new window)を使用します。

# プロパティ

これらのプロパティは、基本的なマテリアルプロパティ上で利用可能です。

Property 概要 デフォルト値
ambientOcclusionMap 環境に閉鎖されたマップ(アンビオエントオクルージョンマップ) メッシュに影をつけるために用いられます。<img>のセレクターやインラインURLに使います。UVの2番めのセットを必要とします(下を参考のこと) None
ambientOcclusionMapIntensity 環境に閉鎖されたマップ(アンビオエントオクルージョンマップ)の強度。0から1の間で設定します。 1
ambientOcclusionTextureRepeat 環境に閉鎖されたマップ(アンビオエントオクルージョンマップ)がXとY方向に何回繰り返されるかを指定します。 1 1
ambientOcclusionTextureOffset 環境に閉鎖されたテクスチャ(アンビオエントオクルージョンテクスチャ)がXとY方向に何回繰り返されるかを指定します。 0 0
color ベースの拡散色 #fff
displacementMap 変位マップ。メッシュを歪めるのに使います。<img>のセレクターやインラインURLに使います。 None
displacementScale ディスプレイスメントマップ効果の強度 1
displacementBias ディスプレースメントマップのゼロ点。 0.5
displacementTextureRepeat ディスプレースメントテクスチャが X と Y 方向に何回繰り返されるかを指定します。 1 1
displacementTextureOffset 変位テクスチャを x y 方向にどのようにオフセットするかを指定します。 0 0
emissive 発光する照明コンポーネントの色。 シーンの中で他の光源の影響を受けることなく、オブジェクトが光源を生成するのに使われます。 #000
emissiveIntensity 発光する照明コンポーネントの強度。 1
height ビデオテクスチャを定義する場合、ビデオの高さ(ピクセル単位) 360
envMap 反射のための環境Cubemapテクスチャ。<cube-map>のセレクターかコンマで区切られたURLのリストとして使用します。 None
fog 素材がの影響を受けるかどうか。. true
metalness 金属の質感。0から1の間で設定します。 0
normalMap 法線マップ。 複雑な詳細をごまかすために用います。<img>のセレクターやインラインURLに使います。 None
normalScale 法線マップのX方向、Y方向の効果の大きさ。 1 1
normalTextureRepeat 法線テクスチャがX と Y 方向に何回繰り返されるかを指定します。 1 1
normalTextureOffset 法線テクスチャx y 方向にどのようにオフセットするかを指定します。 0 0
repeat srcで指定されたテクスチャがX と Y 方向に何回繰り返されるかを指定します。 1 1
roughness マテリアルの粗さ。0から1の間で設定します。ラフなマテリアルであるほど、光を色んな方向へ拡散します。 0.5
sphericalEnvMap 反射のための環境球面テクスチャ。<img>のセレクターやインラインURLに使います。 None
width ビデオテクスチャを定義する場合、ビデオの幅(ピクセル単位) 640
wireframe ジオメトリの端のみをレンダリングするか false
wireframeLinewidth レンダリングする線幅 2
src 画像や映像のテクスチャマップ。<img><video>のセレクターやインラインURLに使います。 None

# 物理ベースシェーディング

物理ベースシェーディングは、照明条件に対する素材の振る舞いをリアルにすることを目的としたシェーディングモデルです。外観は、入射光と材料の特性との間の相互作用の結果である。

リアルさを実現するためには、材料の拡散色、金属性、粗さなどの特性を正確に制御する必要があり、多くの場合、実世界の材料研究に基づいています。さまざまな種類の素材について、現実的な値のチャートをまとめている人もいるので、それを参考にすることができます。

例えば、木の皮の素材であれば、試算として、次のように設定します。

<a-entity geometry="primitive: cylinder"
          material="src: treebark.png; color: #696969; roughness: 1; metalness: 0">
</a-entity>

# フォン・ベースド・シェーディング

フォンシェーディングは安価なシェーダーモデルで、標準マテリアルよりリアルさは劣りますが、フラットシェーディングよりは優れています。 使用するには、マテリアルでシェーダをフォンシェーディングphong に設定します。

<a-torus-knot position="0 3 0" material="shader:phong; reflectivity: 0.9; shininess: 30;"
  geometry="radius: 0.45; radiusTubular: 0.09">
</a-torus-knot>
Property 概要 デフォルト値
specular 素材の光沢の度合いとその色を定義します。 #111111
shininess スペキュラハイライトの輝度を指定します。 30
transparent マテリアルが透明かどうか false
combine 環境マップとマテリアルの混ざり具合。“mix(混合)”, “add(加算)” or “multiply(乗算)” のいずれか。 mix
reflectivity 環境マップがサーフェスに与える影響度 0.9
refract 定義した環境マップを屈折させるかどうか false
refractionRatio マテリアルの屈折率 0.98

# ディストーションマップ

複雑なジオメトリを錯覚させる3つのプロパティがあります。

  • アンビエントオクルージョンマップ - アンビエントライトが少ないエリアに微妙なシャドウを適用します。ダイレクト(ポイント、ディレクショナル)ライトはアンビエントオクルージョンマップに影響を与えません。ベイクド・アンビエント・オクルージョンは、2つ目のUVセットを必要とし、モデリングソフトウェアまたはJavaScriptを使ってメッシュに追加することができます。
  • ディスプレイスメントマップ - 高解像度でよりシンプルなモデルを歪ませ、よりディテールを表現します。これはメッシュのシルエットに影響を与えますが、コストがかかる場合があります。
  • 法線マップ - その点でのサーフェイスの角度を定義します。モデルを歪ませることなく、複雑なジオメトリの外観を与えることができます。ジオメトリは変更されませんが、法線マップは安価です。

# 環境マップ

envMapsphericalEnvMapプロパティは、マテリアルがどのような環境を反映するかを定義します。環境の反映の明瞭さは、metalness金属性、およびroughness粗さのプロパティに依存します。

sphericalEnvMap プロパティは球状にマッピングされたテクスチャを1つだけ受け取ります。<a-sky> に割り当てられるようなものです。

テクスチャとは異なり、envMapプロパティはCubemap、つまり6つの画像を組み合わせて立方体を形成したものを受け取ります。このCubemapはメッシュを包み込み、テクスチャとして適用されます。

<a-scene>
  <a-assets>
    <a-cubemap id="sky">
      <img src="right.png">
      <img src="left.png">
      <img src="top.png">
      <img src="bottom.png">
      <img src="front.png">
      <img src="back.png">
    </a-cubemap>
  </a-assets>

  <a-entity geometry="primitive: box" material="envMap: #sky; roughness: 0"></a-entity>
</a-scene>

# フラット

フラットマテリアルは、THREE.MeshBasicMaterial (opens new window)を使用します。フラットなマテリアルは、シーンの照明条件に影響されません。これは、画像や動画といったものに有効です。シェーダーをflatに設定します。

<a-entity geometry="primitive: plane" material="shader: flat; src: #cat-image"></a-entity>

# プロパティ

Property 概要 デフォルト値
color ベースの拡散色 #fff
fog 素材がの影響を受けるかどうか。. true
height ビデオテクスチャを定義する場合、ビデオの高さ(ピクセル単位) 360
repeat テクスチャ(srcで定義します)がX と Y 方向に何回繰り返されるかを指定します。 1 1
src 画像や映像のテクスチャマップ。<img><video>のセレクターやインラインURLに使います。 None
width ビデオテクスチャを定義する場合、ビデオの幅(ピクセル単位) 640
wireframe ジオメトリの端のみをレンダリングするか false
wireframeLinewidth レンダリングする線幅 2

# テクスチャ

ビルトインマテリアルのうちのどれかのテクスチャをセットするにはsrcプロパティで特定します。 srcアセットマネジメントシステムの中の<img><video>のセレクターとして使います。

<a-scene>
  <a-assets>
    <img id="my-texture" src="texture.png">
  </a-assets>

  <a-entity geometry="primitive: box" material="src: #my-texture"></a-entity>
</a-scene>

src はインラインURLでも可能です。 この方法では、ブラウザのキャッシュやプリロードを取得できないことに注意してください。

<a-scene>
  <a-entity geometry="primitive: box" material="src: url(texture.png)"></a-entity>
</a-scene>

その他のプロパティのほとんどは、テクスチャと連動して動作します。例えば、colorプロパティは基本色として機能し、ピクセルごとにテクスチャと乗算されます。これを#fffに設定すると、テクスチャの元の色が維持されます。

A-Frameはテクスチャをキャッシュし、冗長なテクスチャをGPUにプッシュしないようにします。

# ビデオテクスチャ

ビデオテクスチャがループするかオートプレイするかは、テクスチャの作成に使用されたビデオエレメントに依存します。video 要素を作成して渡す代わりに、単に URL を渡すと、テクスチャはデフォルトでループし、自動再生されます。そうでない場合は、アセット管理システムで video 要素を作成し、id 属性にセレクタを渡します(例: #my-video)。

動画の自動再生ポリシーはますます厳しくなっており、ルールはブラウザによって異なる場合があります。ユーザー ジェスチャーの強制は、現在では一般的に実施されています。最大限の互換性を確保するために、ユーザーがクリックして動画再生を開始できる (opens new window)ボタンを提供することができます。簡単なサンプルコード (opens new window)がdocsにあります。特に、play-on-click component (opens new window)に注意してください。

<a-scene>
  <a-assets>
    <!-- No loop. -->
    <video id="my-video" src="video.mp4" autoplay="true"></video>
  </a-assets>

  <a-entity geometry="primitive: box" material="src: #my-video"></a-entity>
</a-scene>

# ビデオのテクスチャを制御する

一時停止やシークといったメディア再生の制御 (opens new window).を行うには、video 要素を使用することができます。例えば

var videoEl = document.querySelector('#my-video');
videoEl.currentTime = 122;  // Seek to 122 seconds.
videoEl.pause();

これは、インラインURLを渡す場合にはうまくいきません。その場合、A-Frameは、内部でvideo要素を作成します。video 要素を扱うには、<a-assets>video 要素を定義する必要があります。

# キャンバステクスチャ

<canvas>をテクスチャソースとして使用することができます。canvas が変更された場合は、ここ (opens new window)に示す例に従ったコードを使用してテクスチャを更新する必要があります。

<script>
  AFRAME.registerComponent('draw-canvas', {
    schema: {default: ''},

    init: function () {
      this.canvas = document.getElementById(this.data);
      this.ctx = this.canvas.getContext('2d');

      // Draw on canvas...
    }
  });
</script>

<a-assets>
  <canvas id="my-canvas" crossorigin="anonymous"></canvas>
</a-assets>

<a-entity geometry="primitive: plane" material="src: #my-canvas"
          draw-canvas="my-canvas"></a-entity>

# テクスチャを繰り返す

タイルのテクスチャを伸縮させるのではなく、繰り返したい場合があります。repeatプロパティは、テクスチャを繰り返すことができます。

<a-entity geometry="primitive: plane; width: 100"
          material="src: carpet.png; repeat: 100 20"></a-entity>

# 透明度の問題

3Dグラフィックスにおいて、透明度とアルファチャンネルは厄介な存在です。前景の透明なマテリアルが背景のマテリアルの上に正しく合成されないという問題がある場合、その問題はおそらく OpenGL コンポジター(WebGL はその API)の基本設計に起因していると思われます。

理想的なシナリオでは、開発者が3D空間のどこにエンティティを配置するか、またはマークアップで要素を定義する順序に関係なく、A-Frameの透明性は「ただ動く」でしょう。しかし、前景のエンティティが背景のエンティティを覆い隠してしまうということがしばしば起こります。これは、混乱と望ましくない視覚的な不具合を引き起こします。

この問題を回避するには、HTML内のエンティティの順序を変更してみてください。

PNG画像を切り抜きやマスクとして使用する場合(画像の一部が完全に透明で、残りの部分が完全に不透明である必要がある)、透明度の問題を解決するために、transparent: falsealphaTest: 0.5 のように設定してみてください。アルファテストの値で遊んでみてください。

# レンダーオーダーコンポーネント

[render-order コンポーネント]を使用すると、透明オブジェクトを深さでソートするようにレンダーに指示したり、名前付きレイヤーを介して HTML 内のエンティティのレンダー順序を手動で定義することができます。透明度の順序付けの問題がある場合、このコンポーネントを使用してください。

# カスタムシェーダーマテリアルの登録

AFRAME.registerShaderを使って、外観や効果用のカスタムシェーダーマテリアルを登録することができます。

CodePenの例 (opens new window)を見ながら、ステップバイステップで解説していきましょう。いつものように、A-Frameのスクリプトを入れる必要があります。

<script2 src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>

次に、A-Frame スクリプトの後、シーン宣言の前に、必要なコンポーネントやシェーダを定義します。ここでは、my-customシェーダを開始します。スキーマでは、シェーダーのパラメータを宣言します。

<script>
AFRAME.registerShader('my-custom', {
  schema: {
    // ...
  }
});
</script>

通常、色と不透明度のプロパティをサポートしたいです。 is: 'uniform' は、このプロパティがシェーダー上で均一な値として表示されるようにA-Frameに指示します。

<script>
AFRAME.registerShader('my-custom', {
  schema: {
    color: {type: 'color', is: 'uniform', default: 'red'},
    opacity: {type: 'number', is: 'uniform', default: 1.0}
  }
});
</script>

rawtrueに設定すると、ShaderMaterial (opens new window)の代わりにTHREE.RawShaderMaterial (opens new window) を使用するので、ビルトインのユニフォームやアトリビュートがシェーダーコードに自動的に追加されることはありません。ここでは、GLSL定数などの通常の接頭辞を含めたいので、falseのままにしておきます。

  raw: false,

ここでは、vertexShaderを省略してデフォルトのバーテックスシェーダーを使用することにします。フラグメントシェーダがテクスチャ座標を気にする場合、バーテックスシェーダはフラグメントシェーダで使用する様々な値を設定する必要があることに注意してください。

WebVR 対応のほぼすべてのブラウザは ES6 をサポートしているので、フラグメントシェーダを複数行の文字列として定義します。

  fragmentShader:
`
  // Use medium precision.
  precision mediump float;

  // This receives the color value from the schema, which becomes a vec3 in the shader.
  uniform vec3 color;

  // This receives the opacity value from the schema, which becomes a number.
  uniform float opacity;

  // This is the shader program.
  // A fragment shader can set the color via gl_FragColor,
  // or decline to draw anything via discard.
  void main () {
    // Note that this shader doesn't use texture coordinates.
    // Set the RGB portion to our color,
    // and the alpha portion to our opacity.
    gl_FragColor = vec4(color, opacity);
  }
`
});
</script>

そして、マテリアルコンポーネントからシェーダーを使用します。

<!-- A box using our shader, not fully opaque and blue. -->
<a-box material="shader: my-custom; color: blue; opacity: 0.7; transparent: true" position="0 0 -2"></a-box>

# registerShader

コンポーネントと同様に、カスタムマテリアルにもスキーマとライフサイクルハンドラがあります。

Property 概要
fragmentShader フラグメントシェーダーを含むオプションの文字列。省略された場合、単純なデフォルトが使用されます。
init シェーダーの初期化中に一度だけ呼ばれるオプションのライフサイクルハンドラ。マテリアルを作成するために使用されます。
raw オプション。true の場合、シェーダーをそのまま受け入れるために THREE.RawShaderMaterial を使用します。false(デフォルト)の場合、THREE.ShaderMaterial を使用します。
schema マテリアルコンポーネントを拡張するためにシェーダーが使用するプロパ ティ、ユニフォーム、アトリビュートを定義します。
update オプションのライフサイクルハンドラで、シェーダーの初期化時およびデータの更新時に 1 回呼び出されます。マテリアルやシェーダを更新するときに使用します。
vertexShader バーテックスシェーダを含むオプションの文字列。省略された場合は、単純なデフォルトが使用されます。

# スキーマ

コンポーネントプロパティと同じように、マテリアルプロパティを定義することができます。このデータは、マテリアルを作成するために使用するデータとして機能します。

AFRAME.registerShader('custom', {
  schema: {
    emissive: {default: '#000'},
    wireframe: {default: false}
  }
});

データ値を一様な値としてシェーダに渡すには、定義に: 'uniform' を含めます。

AFRAME.registerShader('my-custom', {
  schema: {
    color: {type:'color', is:'uniform', default:'red'},
    opacity: {type:'number', is:'uniform', default:1.0}
  },
  ...

# サポートされているユニフォームタイプ

A-Frameがサポートするユニフォームの種類は、以下の表にまとめられています。timeは、多くの場合、tick()ハンドラを不要にすることができることに注意してください。

A-Frame Type THREE Type GLSL Shader Type
array v3 vec3
color v3 vec3
int i int
number f float
map t map
time f float (milliseconds)
vec2 v2 vec2
vec3 v3 vec3
vec4 v4 vec4

# Example - GLSL and Shaders

よりカスタマイズされた視覚効果を得るためには、GLSLシェーダーを記述し、それをA-Frameエンティティに適用することができます。

注:シェーダを書くための構文であるGLSLは、最初はちょっと怖く感じるかもしれません。優しい(そして無料の!)入門書としては、The Book of Shaders (opens new window)をお勧めします。

ここでは、使用する頂点シェーダとフラグメントシェーダを紹介します。

// vertex.glsl

varying vec2 vUv;

void main() {
  vUv = uv;
  gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
// fragment.glsl

varying vec2 vUv;
uniform vec3 color;
uniform float timeMsec; // A-Frame time in milliseconds.

void main() {
  float time = timeMsec / 1000.0; // Convert from A-Frame milliseconds to typical time in seconds.
  // Use sin(time), which curves between 0 and 1 over time,
  // to determine the mix of two colors:
  //    (a) Dynamic color where 'R' and 'B' channels come
  //        from a modulus of the UV coordinates.
  //    (b) Base color.
  //
  // The color itself is a vec4 containing RGBA values 0-1.
  gl_FragColor = mix(
    vec4(mod(vUv , 0.05) * 20.0, 1.0, 1.0),
    vec4(color, 1.0),
    sin(time)
  );
}

これらの頂点シェーダとフラグメントシェーダを使うには、文字列vertexShaderfragmentShaderに読み込んだ後、自作のシェーダをA-Frameに登録します。

// shader-grid-glitch.js

AFRAME.registerShader('grid-glitch', {
  schema: {
    color: {type: 'color', is: 'uniform'},
    timeMsec: {type: 'time', is: 'uniform'}
  },

  vertexShader: vertexShader,
  fragmentShader: fragmentShader
});

そしてHTMLにマークアップします。

<a-sphere material="shader:grid-glitch; color: blue;" radius="0.5" position="0 1.5 -2"></a-sphere>

5093034e-97f2-40dc-8cb9-28ca75bfd75b-8043-00000dbc2e00268d


テクスチャ付きの例 Remix this Texture Shader on Glitch (opens new window)

textureShaderPreview

更に上級者向けの例, try Real-Time Vertex Displacement (opens new window).

b19320eb-802a-462a-afcd-3d0dd9480aee-861-000004c2a8504498

# カスタムシェーダとコンポーネントを併用する

上記のリアルタイム頂点変位シェーダの例に、カメラの位置に応じたオフセットを適用する機能を追加してみましょう。このオフセットを一様な vec3 値 myOffset として宣言します。

AFRAME.registerShader('displacement-offset', {
  schema: {
    timeMsec: {type: 'time', is: 'uniform'},
    myOffset: {type: 'vec3', is: 'uniform'}
  },
  vertexShader: vertexShader,
  fragmentShader: fragmentShader
});

このバーテックス(頂点)シェーダ (opens new window)で使用されます。では、バーテックスシェーダーが正しく動作するように、myOffsetA-Frameからのカメラ位置に更新するにはどうすればよいでしょうか。A-Frameでこれを行う典型的な方法は、必要な機能を持つコンポーネントを作成し、それを適切なエンティティにアタッチすることです。

シェーダのプロパティはマテリアルコンポーネントを通して公開されるので、setAttribute()の形式を使って目的のプロパティを1つだけ変更することに注意しましょう。パフォーマンス上の理由から、ゴミを作らないようにすることがベストプラクティスです。

  • 第二引数にオブジェクトを取る setAttribute の形式は使わないでください。
  • オフセットを保持するコンポーネントプロパティを作成し、tick ごとに新しい THREE.Vector3 が作成されないようにします。
AFRAME.registerComponent('myoffset-updater', {
  init: function () {
    this.offset = new THREE.Vector3();
  },

  tick: function (t, dt) {
    this.offset.copy(this.el.sceneEl.camera.el.getAttribute('position'));
    this.offset.y = 0;
    this.el.setAttribute('material', 'myOffset', this.offset);
  }
});

次に、このコンポーネントをカスタムシェーダーを持つエンティティに適用します。

<a-scene>
  <a-sphere
    animation="property: scale; dir: alternate; dur: 5000; loop: true; to: 4 4 4"
    geometry="radius: 0.2"
    material="shader: displacement-offset"
    myoffset-updater
    position="0 1.5 -2">
  </a-sphere>
  <a-box color="#CCC" width="3" depth="3" height="0.1" position="0 0 -2"></a-box>
</a-scene>

Voila!

コンポーネントを使用してシェーダ値を設定するもう一つの良い例が、A-Frame Shaders の例 (opens new window)です。このコンポーネントは、スカイシェーダで使用するsunPositionベクトルを計算することによって、id orbitを持つ要素への回転の更新に反応します。

AFRAME.registerComponent('sun-position-setter', {
  init: function () {
    var skyEl = this.el;
    var orbitEl = this.el.sceneEl.querySelector('#orbit');

    orbitEl.addEventListener('componentchanged', function changeSun (evt) {
      var sunPosition;
      var phi;
      var theta;

      if (evt.detail.name !== 'rotation') { return; }

      sunPosition = orbitEl.getAttribute('rotation');

      if(sunPosition === null) { return; }

      theta = Math.PI * (- 0.5);
      phi = 2 * Math.PI * (sunPosition.y / 360 - 0.5);
      skyEl.setAttribute('material', 'sunPosition', {
        x: Math.cos(phi),
        y: Math.sin(phi) * Math.sin(theta),
        z: -1
      });
    });
  }
});

In addition, there are components developed by the A-Frame developer community that allow the use of existing shaders from repositories such as ShaderToy (opens new window) and ShaderFrog (opens new window).

また、A-Frame開発者コミュニティによって開発されたコンポーネントがあり、ShaderToy (opens new window)ShaderFrog (opens new window)などのリポジトリにある既存のシェーダーを利用することができます。

ただし、これらのシェーダーは計算能力やグラフィックス能力がかなり高く、より複雑なシェーダーはスマートフォンなどの低性能なデバイスではうまく機能しない場合があることに注意してください。

# コンポーネントからマテリアルを作る

registerShader APIに必要な機能がない場合(例:tickハンドラがない、ユニフォームの種類がいくつかない)、コンポーネント内にthree.jsマテリアル(例:RawShaderMaterialShaderMaterial)を作成し、カスタムマテリアルを作ることをお勧めします。

AFRAME.registerComponent('custom-material', {
  schema: {
    // Add properties.
  },

  init: function () {
    this.el.addEventListener("loaded", e => { // when using gltf models use "model-loaded" instead
      this.material = this.el.getObject3D('mesh').material = new THREE.ShaderMaterial({
      // ...
      });
    });
  },

  update: function () {
    // Update `this.material`.
  }
});