advanced-rendering について
advanced-renderingは、Decentralandの開発でSDKの描画コンポーネントを使い、3D表現を設定するスキルです。テキスト、カメラ向きのエンティティ、マテリアル、モデルノードの上書き、表示切り替え、テクスチャアニメーションを扱い、main-entities.tsでの記述方法も示します。
主な機能
- 01Billboardでカメラ向きのエンティティを作成
- 02TextShapeで3Dテキストを描画
- 03PBRマテリアルとテクスチャを設定
- 04エンティティの表示を切り替え
- 05GLTFノードのマテリアルを上書き
- 06マテリアルのテクスチャ移動をアニメーション
活用シーン
- 01オブジェクト上に浮動ラベルを追加
- 02発光または透明な表面を作成
- 03条件に応じてエンティティを非表示
- 04水面やコンベヤーのテクスチャをスクロール
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dcl-regenesislabs/ opendcl --skill advanced-renderingインストール後、Claude Code で/advanced-renderingを入力して読み込まれたか確認します。
詳細
Decentraland の高度なレンダリング
作成の分担
Billboard、TextShape、Material、MeshRenderer、GltfContainer、VisibilityComponent、GltfNodeModifiersは、すべてmain-entities.tsでサポートされています。ビジュアルエンティティ(看板、ラベル、ビルボード、発光する小道具、ノードごとの上書きを適用したモデル)は、ビジュアルコンポーネントとともにすべてmain-entities.tsで宣言してください。以下にあるengine.addEntity()の後にTransform.createとMeshRenderer/Billboard/TextShapeが続く例は、main-entities.ts導入前のパターンです。エンティティの宣言をmain-entities.tsに移し、実行時の変更(例:VisibilityComponent.getMutable(entity).visible = false)だけをsrc/index.tsに残してください。
// Example: floating label
// main-entities.ts
shop_label: {
components: {
Transform: { position: { x: 8, y: 3, z: 8 } },
TextShape: { text: 'OPEN', fontSize: 4, textColor: { r: 1, g: 1, b: 1, a: 1 } },
Billboard: { billboardMode: 7 } // BM_ALL
}
}
レンダリング機能の選び方
| 必要なこと | コンポーネント | 使用する場面 |
|---|---|---|
| エンティティをカメラに向ける | Billboard | ネームタグ、看板、スプライト風のオブジェクト |
| 3D ワールド内のテキスト | TextShape | ラベル、看板、エンティティの上に浮かぶテキスト |
| マテリアルの外観をカスタマイズする | Material.setPbrMaterial | 金属、粗い表面、透明な表面、発光する表面 |
| 削除せずに表示/非表示を切り替える | VisibilityComponent | LOD システム、オブジェクトの切り替え、条件付き表示 |
| GLTF モデルのノードを変更する | GltfNodeModifiers | 特定のメッシュノードのマテリアルまたはシャドウキャストを上書きする |
選択の流れ:
- 画面上にテキストを表示する必要がありますか?→ 代わりにbuild-ui(React-ECS Label)を使用します
- 3D 空間にテキストを表示する必要がありますか?→
TextShape(カメラに向けるにはBillboardも使用) - 発光/透明なマテリアルが必要ですか?→ 発光/透明度を設定した
Material.setPbrMaterialを使用します - モデルノードのマテリアルを上書きする必要がありますか?→
modifiers配列を指定したGltfNodeModifiersを使用します
Billboard(カメラに向ける)
エンティティを常にプレイヤーのカメラに向けます。
import { engine, Transform, Billboard, BillboardMode, MeshRenderer } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'
const sign = engine.addEntity()
Transform.create(sign, { position: Vector3.create(8, 2, 8) })
MeshRenderer.setPlane(sign)
// Rotate only on Y axis (most common — stays upright)
Billboard.create(sign, {
billboardMode: BillboardMode.BM_Y
})
Billboard のモード
BillboardMode.BM_Y // Rotate on Y axis only (stays upright) — most common
BillboardMode.BM_ALL // Rotate on all axes (fully faces camera)
BillboardMode.BM_X // Rotate on X axis only
BillboardMode.BM_Z // Rotate on Z axis only
BillboardMode.BM_NONE // No billboard rotation
- ほとんどの用途では
BM_ALLよりBM_Yを優先してください。より自然に見え、レンダリングコストも低くなります。 BM_ALLは、常にカメラの真正面を向く必要があるパーティクルやエフェクトに便利です。
TextShape(3D テキスト)
テキストを3D空間に直接レンダリングします。
import { engine, Transform, TextShape, TextAlignMode } from '@dcl/sdk/ecs'
import { Vector3, Color4 } from '@dcl/sdk/math'
const label = engine.addEntity()
Transform.create(label, { position: Vector3.create(8, 3, 8) })
TextShape.create(label, {
text: 'Hello World!',
fontSize: 24,
textColor: Color4.White(),
outlineColor: Color4.Black(),
outlineWidth: 0.1,
textAlign: TextAlignMode.TAM_MIDDLE_CENTER
})
テキストの配置オプション
TextAlignMode.TAM_TOP_LEFT
TextAlignMode.TAM_TOP_CENTER
TextAlignMode.TAM_TOP_RIGHT
TextAlignMode.TAM_MIDDLE_LEFT
TextAlignMode.TAM_MIDDLE_CENTER
TextAlignMode.TAM_MIDDLE_RIGHT
TextAlignMode.TAM_BOTTOM_LEFT
TextAlignMode.TAM_BOTTOM_CENTER
TextAlignMode.TAM_BOTTOM_RIGHT
浮遊ラベル(Billboard + TextShape)
BillboardとTextShapeを組み合わせて、常にプレイヤーの方を向くラベルを作成します。
const floatingLabel = engine.addEntity()
Transform.create(floatingLabel, { position: Vector3.create(8, 4, 8) })
TextShape.create(floatingLabel, {
text: 'NPC Name',
fontSize: 16,
textColor: Color4.White(),
outlineColor: Color4.Black(),
outlineWidth: 0.08,
textAlign: TextAlignMode.TAM_BOTTOM_CENTER
})
Billboard.create(floatingLabel, {
billboardMode: BillboardMode.BM_Y
})
高度な PBR マテリアル
金属度と粗さ
import { engine, Transform, MeshRenderer, Material, MaterialTransparencyMode } from '@dcl/sdk/ecs'
import { Color4, Color3 } from '@dcl/sdk/math'
// Shiny metal
Material.setPbrMaterial(entity, {
albedoColor: Color4.create(0.8, 0.8, 0.9, 1),
metallic: 1.0,
roughness: 0.1
})
// Rough stone
Material.setPbrMaterial(entity, {
albedoColor: Color4.create(0.5, 0.5, 0.5, 1),
metallic: 0.0,
roughness: 0.9
})
透明度
// Alpha blend — smooth transparency
Material.setPbrMaterial(entity, {
albedoColor: Color4.create(1, 0, 0, 0.5), // 50% transparent red
transparencyMode: MaterialTransparencyMode.MTM_ALPHA_BLEND
})
// Alpha test — cutout (binary visible/invisible based on threshold)
Material.setPbrMaterial(entity, {
texture: Material.Texture.Common({ src: 'assets/cutout.png' }),
transparencyMode: MaterialTransparencyMode.MTM_ALPHA_TEST,
alphaTest: 0.5
})
発光(グロー効果)
// Glowing material (emissiveColor uses Color3, not Color4)
Material.setPbrMaterial(entity, {
albedoColor: Color4.create(0, 0, 0, 1),
emissiveColor: Color3.create(0, 1, 0), // Green glow
emissiveIntensity: 2.0
})
// Emissive with texture
Material.setPbrMaterial(entity, {
texture: Material.Texture.Common({ src: 'assets/diffuse.png' }),
emissiveTexture: Material.Texture.Common({ src: 'assets/emissive.png' }),
emissiveIntensity: 1.0,
emissiveColor: Color3.White()
})
テクスチャマップ
Material.setPbrMaterial(entity, {
texture: Material.Texture.Common({ src: 'assets/diffuse.png' }),
bumpTexture: Material.Texture.Common({ src: 'assets/normal.png' }),
emissiveTexture: Material.Texture.Common({ src: 'assets/emissive.png' })
})
GltfContainer の可視性マスク
衝突マスクを使用して、GLTFモデル内の特定のメッシュレイヤーの可視性と衝突を制御します。
import { engine, Transform, GltfContainer, ColliderLayer } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'
const model = engine.addEntity()
Transform.create(model, { position: Vector3.create(4, 0, 4) })
GltfContainer.create(model, {
src: 'models/myModel.glb',
visibleMeshesCollisionMask: ColliderLayer.CL_PHYSICS | ColliderLayer.CL_POINTER,
invisibleMeshesCollisionMask: ColliderLayer.CL_PHYSICS
})
VisibilityComponent
エンティティを削除せずに表示または非表示にします。
import { engine, VisibilityComponent } from '@dcl/sdk/ecs'
// Hide an entity
VisibilityComponent.create(entity, { visible: false })
// Toggle visibility
const visibility = VisibilityComponent.getMutable(entity)
visibility.visible = !visibility.visible
// Useful for LOD (Level of Detail)
function lodSystem() {
const playerPos = Transform.get(engine.PlayerEntity).position
for (const [entity, transform] of engine.getEntitiesWith(Transform, MeshRenderer)) {
const distance = Vector3.distance(playerPos, transform.position)
if (distance > 30) {
VisibilityComponent.createOrReplace(entity, { visible: false })
} else {
VisibilityComponent.createOrReplace(entity, { visible: true })
}
}
}
engine.addSystem(lodSystem)
ノードごとのモディファイア(GltfNodeModifiers)
GLTFモデル内の特定のノードのマテリアルまたはシャドウキャストを上書きします。main-entities.tsでサポートされています。
// main-entities.ts
armored_knight: {
components: {
Transform: { position: { x: 8, y: 0, z: 8 } },
GltfContainer: { src: 'models/knight.glb' },
GltfNodeModifiers: {
modifiers: [
{
path: 'RootNode/Armor', // GLTF hierarchy path
castShadows: false // disable shadows for this node
}
]
}
}
}
モデル全体への上書き:path: ''(空文字列)を渡すと、モデル内のすべてのノードにモディファイアが適用されます。単一のマテリアル置換でモデル全体のスキンを変更する場合に便利です。
red_team_unit: {
components: {
Transform: { position: { x: 4, y: 0, z: 8 } },
GltfContainer: { src: 'models/unit.glb' },
GltfNodeModifiers: {
modifiers: [
{
path: '',
material: {
material: {
$case: 'pbr',
pbr: { albedoColor: { r: 1, g: 0, b: 0, a: 1 } }
}
}
}
]
}
}
}
テクスチャのトゥイーン(マテリアルテクスチャのアニメーション)
マテリアルのテクスチャオフセット/タイリングを時間経過とともにアニメーションさせます。水、溶岩、コンベヤーベルト、スクロールする背景などに便利です。Tweenコンポーネントはmain-entities.tsでサポートされています。
// main-entities.ts — continuous texture scroll
conveyor: {
components: {
Transform: { position: { x: 8, y: 1, z: 8 } },
MeshRenderer: { mesh: { $case: 'plane', plane: { uvs: [] } } },
Material: { material: { $case: 'pbr', pbr: { texture: { tex: { $case: 'texture', texture: { src: 'images/belt.png' } } } } } },
Tween: {
duration: 2000,
easingFunction: 0, // EF_LINEAR
mode: {
$case: 'textureMoveContinuous',
textureMoveContinuous: { direction: { x: 1, y: 0 }, speed: 0.5 }
// movementType defaults to 0 = TMT_OFFSET; use 1 = TMT_TILING to scale instead
}
}
}
}
テクスチャを有限の範囲で始点から終点まで移動させるには、durationとともに{ $case: 'textureMove', textureMove: { start: { x: 0, y: 0 }, end: { x: 1, y: 0 }, movementType: 0 } }を使用します。
実行時ヘルパー(src/index.ts内):Tween.setTextureMove(entity, from, to, durationMs)およびTween.setTextureMoveContinuous(entity, direction, speed)。
アバターテクスチャ
プレイヤーのアバターからテクスチャを生成します。
Material.setPbrMaterial(portraitFrame, {
texture: Material.Texture.Avatar({ userId: '0x...' })
})
テクスチャモード
テクスチャのフィルタリングとラップ方法を制御します。
import { TextureFilterMode, TextureWrapMode } from '@dcl/sdk/ecs'
Material.setPbrMaterial(entity, {
texture: Material.Texture.Common({
src: 'images/pixel-art.png',
filterMode: TextureFilterMode.TFM_POINT, // crisp pixels (no smoothing)
wrapMode: TextureWrapMode.TWM_REPEAT // tile the texture
})
})
フィルターモード:TFM_POINT(ピクセル化)、TFM_BILINEAR(滑らか)、TFM_TRILINEAR(最も滑らか)。
ラップモード:TWM_REPEAT(タイル状に繰り返す)、TWM_CLAMP(端を引き伸ばす)、TWM_MIRROR(タイル状に反転して繰り返す)。
ベストプラクティス
BM_ALLの代わりにBillboardMode.BM_Yを使用してください。より自然に見え、描画も高速ですfontSizeは読みやすいサイズにしてください(ワールド内のテキストでは 16~32)- どのような背景でも読みやすくなるように、TextShape に
outlineColorとoutlineWidthを追加してください - 最大限の発光効果を得るには、暗い
albedoColorとemissiveColorを組み合わせてください MTM_ALPHA_TESTはMTM_ALPHA_BLENDより負荷が低いため、滑らかな透明度が不要な場合はカットアウトを使用してください- Billboard と TextShape を組み合わせて、NPC やオブジェクトの上に浮かぶ名前ラベルを表示してください
- エンティティを削除して再追加する代わりに、LOD システムには VisibilityComponent を使用してください