material
マテリアルコンポーネントは、実体に外観を与えます。色、不透明度、テクスチャなどのプロパティを定義することができます。これは、形状を提供するジオメトリコンポーネントと対になっていることが多いです。
カスタムマテリアルを登録してマテリアルコンポーネントを拡張し、様々な視覚効果を提供することができます。
# 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 | メッシュのどの面をレンダリングするか。front 、 back 、 double のいずれかを指定できます | front |
transparent | マテリアルが透明かどうか。透明なエンティティは、透明でないエンティティの後にレンダリングされます。 | false |
vertexColors | マテリアルのシェーディングに頂点カラーと面カラーのどちらを使用するか。none 、 vertex 、face のいずれかを指定します。 |
| none |
| visible | マテリアルが見えるかどうか。レイキャスターは不可視のマテリアルを無視します。 | true |
| blending | WebGLRenderer
に送信されるマテリアルの RGB
と Alpha
のブレンディングモードです。none
、 normal
、 additive
、 subtractive
、multiply
のいずれかを指定します。 | 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を使ってメッシュに追加することができます。
- ディスプレイスメントマップ - 高解像度でよりシンプルなモデルを歪ませ、よりディテールを表現します。これはメッシュのシルエットに影響を与えますが、コストがかかる場合があります。
- 法線マップ - その点でのサーフェイスの角度を定義します。モデルを歪ませることなく、複雑なジオメトリの外観を与えることができます。ジオメトリは変更されませんが、法線マップは安価です。
# 環境マップ
envMap
と sphericalEnvMap
プロパティは、マテリアルがどのような環境を反映するかを定義します。環境の反映の明瞭さは、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: false
と alphaTest: 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>
raw
をtrue
に設定すると、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)
);
}
これらの頂点シェーダとフラグメントシェーダを使うには、文字列vertexShader
とfragmentShader
に読み込んだ後、自作のシェーダを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>
テクスチャ付きの例 Remix this Texture Shader on Glitch (opens new window)
更に上級者向けの例, try Real-Time Vertex Displacement (opens new window).
# カスタムシェーダとコンポーネントを併用する
上記のリアルタイム頂点変位シェーダの例に、カメラの位置に応じたオフセットを適用する機能を追加してみましょう。このオフセットを一様な vec3 値 myOffset
として宣言します。
AFRAME.registerShader('displacement-offset', {
schema: {
timeMsec: {type: 'time', is: 'uniform'},
myOffset: {type: 'vec3', is: 'uniform'}
},
vertexShader: vertexShader,
fragmentShader: fragmentShader
});
このバーテックス(頂点)シェーダ (opens new window)で使用されます。では、バーテックスシェーダーが正しく動作するように、myOffset
をA-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
マテリアル(例:RawShaderMaterial
、ShaderMaterial
)を作成し、カスタムマテリアルを作ることをお勧めします。
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`.
}
});