Agent Skills by ALSEL
Anthropic ClaudeLLM・AI開発⭐ リポ 0品質スコア 50/100

babylonjs-engine

Babylon.js を使った3Dウェブレンダリングに関する包括的なスキルです。リアルタイム3D体験、ブラウザベースのゲーム、インタラクティブなビジュアライゼーション、没入型ウェブアプリの構築時に活用してください。Babylon.js・3Dシーン・WebGL/WebGPUレンダリング・エンティティコンポーネントシステム・物理シミュレーション・PBRマテリアル・シャドウマッピング・3Dモデルの読み込みといったタスクで起動し、エディタ統合やゲームエンジン機能を標準搭載したThree.jsの代替として利用できます。

description の原文を見る

Comprehensive skill for Babylon.js 3D web rendering engine. Use this skill when building real-time 3D experiences, browser-based games, interactive visualizations, or immersive web applications. Triggers on tasks involving Babylon.js, 3D scenes, WebGL/WebGPU rendering, entity-component systems, physics simulations, PBR materials, shadow mapping, or 3D model loading. Alternative to Three.js with built-in editor integration and game engine features.

SKILL.md 本文

Babylon.js Engine スキル

関連スキル

  • threejs-webgl: 代替 3D エンジン
  • react-three-fiber: 3D 向け React 統合
  • gsap-scrolltrigger: アニメーションライブラリ
  • motion-framer: UI アニメーション

コア概念

1. エンジンとシーン初期化

基本セットアップ

// キャンバス要素を取得
const canvas = document.getElementById('renderCanvas');

// エンジンを作成
const engine = new BABYLON.Engine(canvas, true, {
  preserveDrawingBuffer: true,
  stencil: true
});

// シーンを作成
const scene = new BABYLON.Scene(engine);

// レンダリングループ
engine.runRenderLoop(() => {
  scene.render();
});

// リサイズ対応
window.addEventListener('resize', () => {
  engine.resize();
});

ES6/TypeScript セットアップ

import { Engine } from '@babylonjs/core/Engines/engine';
import { Scene } from '@babylonjs/core/scene';
import { FreeCamera } from '@babylonjs/core/Cameras/freeCamera';
import { Vector3 } from '@babylonjs/core/Maths/math.vector';
import { HemisphericLight } from '@babylonjs/core/Lights/hemisphericLight';
import { CreateSphere } from '@babylonjs/core/Meshes/Builders/sphereBuilder';

const canvas = document.getElementById('renderCanvas') as HTMLCanvasElement;
const engine = new Engine(canvas);
const scene = new Scene(engine);

// カメラセットアップ
const camera = new FreeCamera('camera1', new Vector3(0, 5, -10), scene);
camera.setTarget(Vector3.Zero());
camera.attachControl(canvas, true);

// ライティング
const light = new HemisphericLight('light1', new Vector3(0, 1, 0), scene);
light.intensity = 0.7;

// メッシュを作成
const sphere = CreateSphere('sphere1', { segments: 16, diameter: 2 }, scene);
sphere.position.y = 2;

// レンダリング
engine.runRenderLoop(() => {
  scene.render();
});

シーン設定オプション

const scene = new BABYLON.Scene(engine, {
  // 大量のメッシュに最適化
  useGeometryUniqueIdsMap: true,
  useMaterialMeshMap: true,
  useClonedMeshMap: true
});

2. カメラシステム

フリーカメラ(FPS スタイル)

const camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5, -10), scene);
camera.setTarget(BABYLON.Vector3.Zero());
camera.attachControl(canvas, true);

// 移動設定
camera.speed = 0.5;
camera.angularSensibility = 2000;
camera.keysUp = [87]; // W
camera.keysDown = [83]; // S
camera.keysLeft = [65]; // A
camera.keysRight = [68]; // D

アークロテートカメラ(軌道)

const camera = new BABYLON.ArcRotateCamera(
  'camera',
  -Math.PI / 2,        // alpha(水平回転)
  Math.PI / 2.5,       // beta(垂直回転)
  15,                  // radius(距離)
  new BABYLON.Vector3(0, 0, 0), // target
  scene
);
camera.attachControl(canvas, true);

// 制約
camera.lowerRadiusLimit = 5;
camera.upperRadiusLimit = 50;
camera.lowerBetaLimit = 0.1;
camera.upperBetaLimit = Math.PI / 2;

ユニバーサルカメラ(高度)

const camera = new BABYLON.UniversalCamera('camera', new BABYLON.Vector3(0, 5, -10), scene);
camera.setTarget(BABYLON.Vector3.Zero());
camera.attachControl(canvas, true);

// 衝突検出
camera.checkCollisions = true;
camera.applyGravity = true;
camera.ellipsoid = new BABYLON.Vector3(1, 1, 1);

3. ライティングシステム

ヘミスフェリックライト(アンビエント)

const light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), scene);
light.intensity = 0.7;
light.diffuse = new BABYLON.Color3(1, 1, 1);
light.specular = new BABYLON.Color3(1, 1, 1);
light.groundColor = new BABYLON.Color3(0, 0, 0);

ディレクショナルライト(太陽のような)

const light = new BABYLON.DirectionalLight('dirLight', new BABYLON.Vector3(-1, -2, -1), scene);
light.position = new BABYLON.Vector3(20, 40, 20);
light.intensity = 0.5;

// シャドウセットアップ
const shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
shadowGenerator.useExponentialShadowMap = true;

ポイントライト(全方向)

const light = new BABYLON.PointLight('pointLight', new BABYLON.Vector3(0, 10, 0), scene);
light.intensity = 0.7;
light.diffuse = new BABYLON.Color3(1, 0, 0);
light.specular = new BABYLON.Color3(0, 1, 0);

// 範囲とフォールオフ
light.range = 100;
light.radius = 0.1;

スポットライト(集中)

const light = new BABYLON.SpotLight(
  'spotLight',
  new BABYLON.Vector3(0, 10, 0),      // position
  new BABYLON.Vector3(0, -1, 0),      // direction
  Math.PI / 3,                        // angle
  2,                                  // exponent
  scene
);
light.intensity = 0.8;

ライト最適化(特定メッシュのみに影響)

// 特定メッシュのみに影響
light.includedOnlyMeshes = [mesh1, mesh2, mesh3];

// または特定メッシュを除外
light.excludedMeshes = [mesh4, mesh5];

4. メッシュ作成

組み込み図形

// ボックス
const box = BABYLON.MeshBuilder.CreateBox('box', {
  size: 2,
  width: 2,
  height: 2,
  depth: 2
}, scene);

// スフィア
const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {
  diameter: 2,
  segments: 32,
  diameterX: 2,
  diameterY: 2,
  diameterZ: 2,
  arc: 1,
  slice: 1
}, scene);

// シリンダー
const cylinder = BABYLON.MeshBuilder.CreateCylinder('cylinder', {
  height: 3,
  diameter: 2,
  tessellation: 24
}, scene);

// プレーン
const plane = BABYLON.MeshBuilder.CreatePlane('plane', {
  size: 5,
  width: 5,
  height: 5
}, scene);

// グラウンド
const ground = BABYLON.MeshBuilder.CreateGround('ground', {
  width: 10,
  height: 10,
  subdivisions: 2
}, scene);

// ハイトマップからグラウンド
const ground = BABYLON.MeshBuilder.CreateGroundFromHeightMap('ground', 'heightmap.png', {
  width: 100,
  height: 100,
  subdivisions: 100,
  minHeight: 0,
  maxHeight: 10
}, scene);

// トーラス
const torus = BABYLON.MeshBuilder.CreateTorus('torus', {
  diameter: 3,
  thickness: 1,
  tessellation: 16
}, scene);

// トーラスノット
const torusKnot = BABYLON.MeshBuilder.CreateTorusKnot('torusKnot', {
  radius: 2,
  tube: 0.6,
  radialSegments: 64,
  tubularSegments: 8,
  p: 2,
  q: 3
}, scene);

メッシュ変換

// 位置
mesh.position = new BABYLON.Vector3(0, 5, 10);
mesh.position.x = 5;
mesh.position.y = 2;

// 回転(ラジアン)
mesh.rotation = new BABYLON.Vector3(0, Math.PI / 2, 0);
mesh.rotation.y = Math.PI / 4;

// スケーリング
mesh.scaling = new BABYLON.Vector3(2, 2, 2);
mesh.scaling.x = 1.5;

// ルックアット
mesh.lookAt(new BABYLON.Vector3(0, 0, 0));

// 親子関係
childMesh.parent = parentMesh;

メッシュプロパティ

// 可視性
mesh.isVisible = true;
mesh.visibility = 0.5; // 0 = 不可視、1 = 完全可視

// ピッキング
mesh.isPickable = true;
mesh.checkCollisions = true;

// カリング
mesh.cullingStrategy = BABYLON.AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY;

// シャドウ受信
mesh.receiveShadows = true;

5. マテリアル

スタンダードマテリアル

const material = new BABYLON.StandardMaterial('material', scene);

// 色
material.diffuseColor = new BABYLON.Color3(1, 0, 1);
material.specularColor = new BABYLON.Color3(0.5, 0.6, 0.87);
material.emissiveColor = new BABYLON.Color3(0, 0, 0);
material.ambientColor = new BABYLON.Color3(0.23, 0.98, 0.53);

// テクスチャ
material.diffuseTexture = new BABYLON.Texture('diffuse.png', scene);
material.specularTexture = new BABYLON.Texture('specular.png', scene);
material.emissiveTexture = new BABYLON.Texture('emissive.png', scene);
material.ambientTexture = new BABYLON.Texture('ambient.png', scene);
material.bumpTexture = new BABYLON.Texture('normal.png', scene);
material.opacityTexture = new BABYLON.Texture('opacity.png', scene);

// プロパティ
material.alpha = 0.8;
material.backFaceCulling = true;
material.wireframe = false;
material.specularPower = 64;

// メッシュに適用
mesh.material = material;

PBR マテリアル(物理ベースレンダリング)

const pbr = new BABYLON.PBRMaterial('pbr', scene);

// メタリックワークフロー
pbr.albedoColor = new BABYLON.Color3(1, 1, 1);
pbr.albedoTexture = new BABYLON.Texture('albedo.png', scene);
pbr.metallic = 1.0;
pbr.roughness = 0.5;
pbr.metallicTexture = new BABYLON.Texture('metallic.png', scene);

// またはスペキュラーワークフロー
pbr.albedoTexture = new BABYLON.Texture('albedo.png', scene);
pbr.reflectivityTexture = new BABYLON.Texture('reflectivity.png', scene);

// 環境
pbr.environmentTexture = BABYLON.CubeTexture.CreateFromPrefilteredData('environment.dds', scene);

// その他のマップ
pbr.bumpTexture = new BABYLON.Texture('normal.png', scene);
pbr.ambientTexture = new BABYLON.Texture('ao.png', scene);
pbr.emissiveTexture = new BABYLON.Texture('emissive.png', scene);

mesh.material = pbr;

マルチマテリアル

const multiMat = new BABYLON.MultiMaterial('multiMat', scene);
multiMat.subMaterials.push(material1);
multiMat.subMaterials.push(material2);
multiMat.subMaterials.push(material3);

mesh.material = multiMat;
mesh.subMeshes = [];
mesh.subMeshes.push(new BABYLON.SubMesh(0, 0, verticesCount, 0, indicesCount1, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(1, 0, verticesCount, indicesCount1, indicesCount2, mesh));

6. モデル読み込み

GLTF/GLB インポート

// シーンに追加
BABYLON.SceneLoader.Append('path/to/', 'model.gltf', scene, function(scene) {
  console.log('モデル読み込み完了');
});

// メッシュをインポート
BABYLON.SceneLoader.ImportMesh('', 'path/to/', 'model.gltf', scene, function(meshes) {
  const mesh = meshes[0];
  mesh.position.y = 5;
});

// 非同期版
const result = await BABYLON.SceneLoader.ImportMeshAsync(
  null,  // すべてのメッシュ
  'https://assets.babylonjs.com/meshes/',
  'village.glb',
  scene
);
console.log('読み込まれたメッシュ:', result.meshes);

// バイナリから読み込み
const result = await BABYLON.SceneLoader.AppendAsync(
  '',
  'data:' + arrayBuffer,
  scene
);

アセットマネージャー(バッチ読み込み)

const assetsManager = new BABYLON.AssetsManager(scene);

// メッシュタスクを追加
const meshTask = assetsManager.addMeshTask('model', '', 'path/to/', 'model.gltf');
meshTask.onSuccess = function(task) {
  task.loadedMeshes[0].position = new BABYLON.Vector3(0, 0, 0);
};

// テクスチャタスクを追加
const textureTask = assetsManager.addTextureTask('texture', 'texture.png');
textureTask.onSuccess = function(task) {
  material.diffuseTexture = task.texture;
};

// すべてを読み込み
assetsManager.onFinish = function(tasks) {
  console.log('すべてのアセット読み込み完了');
  engine.runRenderLoop(() => scene.render());
};

assetsManager.load();

7. 物理エンジン

Havok Physics セットアップ

// Havok をインポート
import HavokPhysics from '@babylonjs/havok';

// 初期化
const havokInstance = await HavokPhysics();
const havokPlugin = new BABYLON.HavokPlugin(true, havokInstance);

// 物理を有効化
scene.enablePhysics(new BABYLON.Vector3(0, -9.8, 0), havokPlugin);

// メッシュ用物理アグリゲートを作成
const sphereAggregate = new BABYLON.PhysicsAggregate(
  sphere,
  BABYLON.PhysicsShapeType.SPHERE,
  { mass: 1, restitution: 0.75 },
  scene
);

// グラウンド(静的)
const groundAggregate = new BABYLON.PhysicsAggregate(
  ground,
  BABYLON.PhysicsShapeType.BOX,
  { mass: 0 }, // mass 0 = 静的
  scene
);

物理シェイプ

// 利用可能なシェイプ
BABYLON.PhysicsShapeType.SPHERE
BABYLON.PhysicsShapeType.BOX
BABYLON.PhysicsShapeType.CAPSULE
BABYLON.PhysicsShapeType.CYLINDER
BABYLON.PhysicsShapeType.CONVEX_HULL
BABYLON.PhysicsShapeType.MESH
BABYLON.PhysicsShapeType.HEIGHTFIELD

物理ボディ制御

// ボディを取得
const body = aggregate.body;

// 力を適用
body.applyForce(
  new BABYLON.Vector3(0, 10, 0),    // force
  new BABYLON.Vector3(0, 0, 0)      // point of application
);

// インパルスを適用
body.applyImpulse(
  new BABYLON.Vector3(0, 5, 0),
  new BABYLON.Vector3(0, 0, 0)
);

// 速度を設定
body.setLinearVelocity(new BABYLON.Vector3(0, 5, 0));
body.setAngularVelocity(new BABYLON.Vector3(0, 1, 0));

// プロパティ
body.setMassProperties({ mass: 2 });
body.setCollisionCallbackEnabled(true);

8. アニメーション

ダイレクトアニメーション

// プロパティをアニメーション
BABYLON.Animation.CreateAndStartAnimation(
  'anim',
  mesh,
  'position.y',
  30,                    // FPS
  120,                   // 総フレーム数
  mesh.position.y,       // from
  10,                    // to
  BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);

アニメーションクラス

const animation = new BABYLON.Animation(
  'myAnimation',
  'position.x',
  30,
  BABYLON.Animation.ANIMATIONTYPE_FLOAT,
  BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);

// キーフレーム
const keys = [
  { frame: 0, value: 0 },
  { frame: 30, value: 10 },
  { frame: 60, value: 0 }
];
animation.setKeys(keys);

// メッシュにアタッチ
mesh.animations.push(animation);

// 開始
scene.beginAnimation(mesh, 0, 60, true);

アニメーショングループ

const animationGroup = new BABYLON.AnimationGroup('group', scene);
animationGroup.addTargetedAnimation(animation1, mesh1);
animationGroup.addTargetedAnimation(animation2, mesh2);

// 制御
animationGroup.play();
animationGroup.pause();
animationGroup.stop();
animationGroup.speedRatio = 2.0;

// イベント
animationGroup.onAnimationEndObservable.add(() => {
  console.log('アニメーション完了');
});

スケルトンアニメーション(インポートモデルから)

// インポートモデルからスケルトンを取得
const skeleton = result.skeletons[0];

// アニメーション範囲を取得
const ranges = skeleton.getAnimationRanges();

// アニメーション範囲を再生
scene.beginAnimation(skeleton, 0, 100, true);

// またはアニメーショングループを使用
result.animationGroups[0].play();
result.animationGroups[0].setWeightForAllAnimatables(0.5);

一般的なパターン

パターン1: デフォルト環境でのシーンセットアップ

const createScene = function() {
  const scene = new BABYLON.Scene(engine);

  // クイックセットアップ
  scene.createDefaultCameraOrLight(true, true, true);
  const env = scene.createDefaultEnvironment({
    createGround: true,
    createSkybox: true,
    skyboxSize: 150,
    groundSize: 50
  });

  // メッシュ
  const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {diameter: 2}, scene);
  sphere.position.y = 1;

  return scene;
};

パターン2: 非同期シーン読み込み

const createScene = async function() {
  const scene = new BABYLON.Scene(engine);

  const camera = new BABYLON.ArcRotateCamera('camera', 0, 0, 10, BABYLON.Vector3.Zero(), scene);
  camera.attachControl(canvas, true);

  const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0), scene);

  // モデルを読み込み
  const result = await BABYLON.SceneLoader.ImportMeshAsync(
    null,
    'https://assets.babylonjs.com/meshes/',
    'village.glb',
    scene
  );

  // 物理セットアップ
  const havokInstance = await HavokPhysics();
  const havokPlugin = new BABYLON.HavokPlugin(true, havokInstance);
  scene.enablePhysics(new BABYLON.Vector3(0, -9.8, 0), havokPlugin);

  return scene;
};

createScene().then(scene => {
  engine.runRenderLoop(() => scene.render());
});

パターン3: インタラクティブピッキング

scene.onPointerDown = function(evt, pickResult) {
  if (pickResult.hit) {
    console.log('ピックされたメッシュ:', pickResult.pickedMesh.name);
    console.log('ピック地点:', pickResult.pickedPoint);

    // ピックされたメッシュをハイライト
    pickResult.pickedMesh.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
  }
};

// またはアクションマネージャーを使用
mesh.actionManager = new BABYLON.ActionManager(scene);
mesh.actionManager.registerAction(
  new BABYLON.ExecuteCodeAction(
    BABYLON.ActionManager.OnPickTrigger,
    function() {
      console.log('メッシュがクリックされた');
    }
  )
);

パターン4: ポストプロセッシングエフェクト

// デフォルトパイプライン
const pipeline = new BABYLON.DefaultRenderingPipeline('pipeline', true, scene, [camera]);
pipeline.samples = 4;
pipeline.fxaaEnabled = true;
pipeline.bloomEnabled = true;
pipeline.bloomThreshold = 0.8;
pipeline.bloomWeight = 0.5;
pipeline.bloomKernel = 64;

// 被写界深度
pipeline.depthOfFieldEnabled = true;
pipeline.depthOfFieldBlurLevel = BABYLON.DepthOfFieldEffectBlurLevel.Low;
pipeline.depthOfField.focusDistance = 2000;
pipeline.depthOfField.focalLength = 50;

// グロウレイヤー
const glowLayer = new BABYLON.GlowLayer('glow', scene);
glowLayer.intensity = 0.5;

// ハイライトレイヤー
const highlightLayer = new BABYLON.HighlightLayer('highlight', scene);
highlightLayer.addMesh(mesh, BABYLON.Color3.Green());

パターン5: GUI(2D UI)

import { AdvancedDynamicTexture, Button, TextBlock, Rectangle } from '@babylonjs/gui';

// フルスクリーン UI
const advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI('UI');

// ボタン
const button = BABYLON.GUI.Button.CreateSimpleButton('button', 'クリック');
button.width = '150px';
button.height = '40px';
button.color = 'white';
button.background = 'green';
button.onPointerUpObservable.add(() => {
  console.log('ボタンがクリックされた');
});
advancedTexture.addControl(button);

// テキスト
const text = new BABYLON.GUI.TextBlock();
text.text = 'こんにちは世界';
text.color = 'white';
text.fontSize = 24;
advancedTexture.addControl(text);

// 3D メッシュ UI
const plane = BABYLON.MeshBuilder.CreatePlane('plane', {size: 2}, scene);
const advancedTexture3D = BABYLON.GUI.AdvancedDynamicTexture.CreateForMesh(plane);
const button3D = BABYLON.GUI.Button.CreateSimpleButton('button3D', 'クリック');
advancedTexture3D.addControl(button3D);

パターン6: シャドウマッピング

const light = new BABYLON.DirectionalLight('light', new BABYLON.Vector3(-1, -2, -1), scene);
light.position = new BABYLON.Vector3(20, 40, 20);

// シャドウジェネレータを作成
const shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
shadowGenerator.useExponentialShadowMap = true;
shadowGenerator.usePoissonSampling = true;

// シャドウキャスターを追加
shadowGenerator.addShadowCaster(sphere);
shadowGenerator.addShadowCaster(box);

// シャドウ受信を有効化
ground.receiveShadows = true;

パターン7: パーティクルシステム

const particleSystem = new BABYLON.ParticleSystem('particles', 2000, scene);
particleSystem.particleTexture = new BABYLON.Texture('particle.png', scene);

// エミッター
particleSystem.emitter = new BABYLON.Vector3(0, 5, 0);
particleSystem.minEmitBox = new BABYLON.Vector3(-1, 0, 0);
particleSystem.maxEmitBox = new BABYLON.Vector3(1, 0, 0);

// 色
particleSystem.color1 = new BABYLON.Color4(0.7, 0.8, 1.0, 1.0);
particleSystem.color2 = new BABYLON.Color4(0.2, 0.5, 1.0, 1.0);
particleSystem.colorDead = new BABYLON.Color4(0, 0, 0.2, 0.0);

// サイズ
particleSystem.minSize = 0.1;
particleSystem.maxSize = 0.5;

// ライフタイム
particleSystem.minLifeTime = 0.3;
particleSystem.maxLifeTime = 1.5;

// 放出レート
particleSystem.emitRate = 1500;

// 方向
particleSystem.direction1 = new BABYLON.Vector3(-1, 8, 1);
particleSystem.direction2 = new BABYLON.Vector3(1, 8, -1);

// 重力
particleSystem.gravity = new BABYLON.Vector3(0, -9.81, 0);

// 開始
particleSystem.start();

統合パターン

パターン1: React 統合

import { useEffect, useRef } from 'react';
import * as BABYLON from '@babylonjs/core';

function BabylonScene() {
  const canvasRef = useRef(null);
  const engineRef = useRef(null);
  const sceneRef = useRef(null);

  useEffect(() => {
    if (!canvasRef.current) return;

    // 初期化
    const engine = new BABYLON.Engine(canvasRef.current, true);
    engineRef.current = engine;

    const scene = new BABYLON.Scene(engine);
    sceneRef.current = scene;

    // シーンセットアップ
    const camera = new BABYLON.ArcRotateCamera('camera', 0, 0, 10, BABYLON.Vector3.Zero(), scene);
    camera.attachControl(canvasRef.current, true);

    const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0), scene);

    const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {diameter: 2}, scene);

    // レンダリングループ
    engine.runRenderLoop(() => {
      scene.render();
    });

    // リサイズハンドラー
    const handleResize = () => engine.resize();
    window.addEventListener('resize', handleResize);

    // クリーンアップ
    return () => {
      window.removeEventListener('resize', handleResize);
      scene.dispose();
      engine.dispose();
    };
  }, []);

  return (
    <canvas
      ref={canvasRef}
      style={{ width: '100%', height: '100vh' }}
    />
  );
}

パターン2: WebXR(VR/AR)

const createScene = async function() {
  const scene = new BABYLON.Scene(engine);

  const camera = new BABYLON.FreeCamera('camera', new BABYLON.Vector3(0, 5, -10), scene);
  camera.attachControl(canvas, true);

  const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0), scene);

  const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {diameter: 2}, scene);
  sphere.position.y = 1;

  const env = scene.createDefaultEnvironment();

  // WebXR を有効化
  const xrHelper = await scene.createDefaultXRExperienceAsync({
    floorMeshes: [env.ground],
    disableTeleportation: false
  });

  // XR コントローラー入力
  xrHelper.input.onControllerAddedObservable.add((controller) => {
    controller.onMotionControllerInitObservable.add((motionController) => {
      const trigger = motionController.getMainComponent();
      trigger.onButtonStateChangedObservable.add(() => {
        if (trigger.pressed) {
          console.log('トリガー押下');
        }
      });
    });
  });

  return scene;
};

パターン3: ノードマテリアル(ビジュアルシェーダーエディター)

// スニペットから作成
const nodeMaterial = await BABYLON.NodeMaterial.ParseFromSnippetAsync('#SNIPPET_ID', scene);

// メッシュに適用
nodeMaterial.build();
mesh.material = nodeMaterial;

// またはプログラムから作成
const nodeMaterial = new BABYLON.NodeMaterial('node', scene);

const positionInput = new BABYLON.InputBlock('position');
positionInput.setAsAttribute('position');

const worldPos = new BABYLON.TransformBlock('worldPos');
nodeMaterial.addOutputNode(worldPos);

パフォーマンス最適化

1. メッシュ最適化

// 同じマテリアルを持つメッシュをマージ
const merged = BABYLON.Mesh.MergeMeshes(
  [mesh1, mesh2, mesh3],
  true,  // disposeSource
  true,  // allow32BitsIndices
  undefined,
  false, // multiMultiMaterials
  true   // preserveSerializationHelper
);

// インスタンス(繰り返されたメッシュ用)
const instance1 = mesh.createInstance('instance1');
const instance2 = mesh.createInstance('instance2');
instance1.position.x = 5;
instance2.position.x = -5;

// シンインスタンス(さらに効率的)
const buffer = new Float32Array(16 * count); // マトリックスあたり16フロート
mesh.thinInstanceSetBuffer('matrix', buffer, 16);

// メッシュをフリーズ(静的メッシュ)
mesh.freezeWorldMatrix();

// マテリアルをフリーズ
material.freeze();

// メッシュを簡略化(LOD)
const simplified = mesh.simplify(
  [
    { quality: 0.8, distance: 10 },
    { quality: 0.4, distance: 50 },
    { quality: 0.2, distance: 100 }
  ],
  true,  // parallelProcessing
  BABYLON.SimplificationType.QUADRATIC
);

2. シーン最適化

// シーンオプティマイザー
const options = new BABYLON.SceneOptimizerOptions();
options.addOptimization(new BABYLON.HardwareScalingOptimization(0, 1));
options.addOptimization(new BABYLON.ShadowsOptimization(1));
options.addOptimization(new BABYLON.PostProcessesOptimization(2));
options.addOptimization(new BABYLON.LensFlaresOptimization(3));
options.addOptimization(new BABYLON.ParticlesOptimization(4));
options.addOptimization(new BABYLON.TextureOptimization(5, 512));
options.addOptimization(new BABYLON.RenderTargetsOptimization(6));
options.addOptimization(new BABYLON.MergeMeshesOptimization(7));

const optimizer = new BABYLON.SceneOptimizer(scene, options);
optimizer.start();

// オクツリー(空間分割)
const octree = scene.createOrUpdateSelectionOctree();

// フラスタムカリング
scene.blockMaterialDirtyMechanism = true;

// ポインター移動ピッキングをスキップ
scene.skipPointerMovePicking = true;

// アクティブメッシュをフリーズ
scene.freezeActiveMeshes();

3. レンダリング最適化

// ハードウェアスケーリング
engine.setHardwareScalingLevel(0.5); // 半分の解像度でレンダリング

// 適応的品質
scene.onBeforeRenderObservable.add(() => {
  const fps = engine.getFps();
  if (fps < 30) {
    // 品質を低下
    engine.setHardwareScalingLevel(2);
  } else if (fps > 55) {
    // 品質を向上
    engine.setHardwareScalingLevel(1);
  }
});

// インクリメンタル読み込み
scene.useDelayedTextureLoading = true;

// カリング戦略
mesh.cullingStrategy = BABYLON.AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY;

4. テクスチャ最適化

// 圧縮テクスチャ
const texture = new BABYLON.Texture('texture.dds', scene);

// ミップマップ
texture.updateSamplingMode(BABYLON.Texture.TRILINEAR_SAMPLINGMODE);

// 異方性フィルタリング
texture.anisotropicFilteringLevel = 4;

// KTX2 圧縮
const texture = new BABYLON.Texture('texture.ktx2', scene);

一般的な落とし穴

落とし穴1: メモリリーク

問題: リソースを解放しない

// ❌ 悪い例 - メモリリーク
function createAndRemoveMesh() {
  const mesh = BABYLON.MeshBuilder.CreateBox('box', {}, scene);
  scene.removeMesh(mesh);
}

解決策: 適切に解放

// ✅ 良い例
function createAndRemoveMesh() {
  const mesh = BABYLON.MeshBuilder.CreateBox('box', {}, scene);
  mesh.dispose();
}

// シーン全体を解放
scene.dispose();

// エンジンを解放
engine.dispose();

落とし穴2: ドローコール数が多すぎることによるパフォーマンス問題

問題: 各メッシュ = 1 ドローコール

// ❌ 悪い例 - 1000 ドローコール
for (let i = 0; i < 1000; i++) {
  const box = BABYLON.MeshBuilder.CreateBox('box' + i, {}, scene);
  box.position.x = i;
}

解決策: インスタンスまたはマージを使用

// ✅ 良い例 - 1 ドローコール
const box = BABYLON.MeshBuilder.CreateBox('box', {}, scene);
for (let i = 0; i < 1000; i++) {
  const instance = box.createInstance('instance' + i);
  instance.position.x = i;
}

落とし穴3: メインスレッドをブロック

問題: 重い計算がレンダリングをブロック

// ❌ 悪い例 - レンダリングをブロック
function createManyMeshes() {
  for (let i = 0; i < 10000; i++) {
    const mesh = BABYLON.MeshBuilder.CreateSphere('sphere' + i, {}, scene);
  }
}

解決策: 非同期/インクリメンタル読み込みを使用

// ✅ 良い例 - インクリメンタル
async function createManyMeshes() {
  for (let i = 0; i < 10000; i++) {
    const mesh = BABYLON.MeshBuilder.CreateSphere('sphere' + i, {}, scene);

    if (i % 100 === 0) {
      await new Promise(resolve => setTimeout(resolve, 0));
    }
  }
}

落とし穴4: 不正なカメラコントロール

問題: カメラが応答しない

// ❌ 悪い例 - attachControl を忘れた
const camera = new BABYLON.ArcRotateCamera('camera', 0, 0, 10, BABYLON.Vector3.Zero(), scene);

解決策: 常にコントロールをアタッチ

// ✅ 良い例
const camera = new BABYLON.ArcRotateCamera('camera', 0, 0, 10, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);

落とし穴5: 非同期操作を処理しない

問題: シーンが準備完了する前に使用

// ❌ 悪い例
BABYLON.SceneLoader.ImportMesh('', 'path/', 'model.gltf', scene);
const mesh = scene.getMeshByName('meshName'); // null!

解決策: コールバックまたは async/await を使用

// ✅ 良い例
const result = await BABYLON.SceneLoader.ImportMeshAsync('', 'path/', 'model.gltf', scene);
const mesh = scene.getMeshByName('meshName');

// またはコールバック付き
BABYLON.SceneLoader.ImportMesh('', 'path/', 'model.gltf', scene, function(meshes) {
  const mesh = meshes[0];
});

落とし穴6: 物理が機能しない

問題: 物理を有効化し忘れたか、アグリゲートを作成していない

// ❌ 悪い例
const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {}, scene);
sphere.physicsImpostor = new BABYLON.PhysicsImpostor(sphere, BABYLON.PhysicsImpostor.SphereImpostor, {mass: 1}, scene);
// エラー: 物理が有効化されていない!

解決策: 最初に物理を有効化し、アグリゲートを使用

// ✅ 良い例
const havokInstance = await HavokPhysics();
const havokPlugin = new BABYLON.HavokPlugin(true, havokInstance);
scene.enablePhysics(new BABYLON.Vector3(0, -9.8, 0), havokPlugin);

const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {}, scene);
const aggregate = new BABYLON.PhysicsAggregate(
  sphere,
  BABYLON.PhysicsShapeType.SPHERE,
  {mass: 1},
  scene
);

高度なトピック

1. カスタムシェーダー

BABYLON.Effect.ShadersStore['customVertexShader'] = `
  precision highp float;
  attribute vec3 position;
  attribute vec2 uv;
  uniform mat4 worldViewProjection;
  varying vec2 vUV;

  void main(void) {
    gl_Position = worldViewProjection * vec4(position, 1.0);
    vUV = uv;
  }
`;

BABYLON.Effect.ShadersStore['customFragmentShader'] = `
  precision highp float;
  varying vec2 vUV;
  uniform sampler2D textureSampler;

  void main(void) {
    gl_FragColor = texture2D(textureSampler, vUV);
  }
`;

const shaderMaterial = new BABYLON.ShaderMaterial('shader', scene, {
  vertex: 'custom',
  fragment: 'custom'
}, {
  attributes: ['position', 'uv'],
  uniforms: ['worldViewProjection']
});

2. コンピュートシェーダー

const computeShader = new BABYLON.ComputeShader('compute', engine, {
  computeSource: `
    #version 450
    layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
    layout(std430, binding = 0) buffer OutputBuffer { vec4 data[]; } outputBuffer;

    void main() {
      uint index = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * 8u;
      outputBuffer.data[index] = vec4(1.0, 0.0, 0.0, 1.0);
    }
  `
});

3. 手続き型テクスチャ

const noiseTexture = new BABYLON.NoiseProceduralTexture('noise', 256, scene);
noiseTexture.octaves = 4;
noiseTexture.persistence = 0.8;
noiseTexture.animationSpeedFactor = 5;

material.emissiveTexture = noiseTexture;

デバッグ

// インスペクターを表示
scene.debugLayer.show();

// バウンディングボックスを表示
scene.forceShowBoundingBoxes = true;

// ワイヤーフレームを表示
material.wireframe = true;

// FPS をログ出力
setInterval(() => {
  console.log('FPS:', engine.getFps());
}, 1000);

// インストルメンテーション
const instrumentation = new BABYLON.SceneInstrumentation(scene);
instrumentation.captureFrameTime = true;
console.log('フレーム時間:', instrumentation.frameTimeCounter.average);

リソース

バージョン注記

このスキルは Babylon.js 7.x に基づいています。最新機能については、公式ドキュメントを参照してください。

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
freshtechbro
リポジトリ
freshtechbro/claudedesignskills
ライセンス
MIT
最終更新
不明

Source: https://github.com/freshtechbro/claudedesignskills / ライセンス: MIT

関連スキル

OpenAILLM・AI開発⭐ リポ 6,054

agent-browser

AI エージェント向けのブラウザ自動化 CLI です。ウェブサイトとの対話が必要な場合に使用します。ページ遷移、フォーム入力、ボタンクリック、スクリーンショット取得、データ抽出、ウェブアプリのテスト、ブラウザ操作の自動化など、あらゆるブラウザタスクに対応できます。「ウェブサイトを開く」「フォームに記入する」「ボタンをクリックする」「スクリーンショットを取得する」「ページからデータを抽出する」「このウェブアプリをテストする」「サイトにログインする」「ブラウザ操作を自動化する」といった要求や、プログラマティックなウェブ操作が必要なタスクで起動します。

by JimmyLv
汎用LLM・AI開発⭐ リポ 1,982

anyskill

AnySkill — あなたのプライベート・スキルクラウド。GitHubを基盤としたリポジトリからエージェントスキルを管理、同期、動的にロードできます。自然言語でクラウドスキルを検索し、オンデマンドでプロンプトを自動ロード、カスタムスキルのアップロードと共有、スキルバンドルの一括インストールが可能です。OpenClaw、Antigravity、Claude Code、Cursorに対応しています。

by LeoYeAI
汎用LLM・AI開発⭐ リポ 1,982

engram

AIエージェント向けの永続的なメモリシステムです。バグ修正、意思決定、発見、設定変更の後はmem_saveを使用してください。ユーザーが「覚えている」「記憶している」と言及した場合、または以前のセッションと重複する作業を開始する際はmem_searchを使用します。セッション終了前にmem_session_summaryを使用して、コンテキストを保持してください。

by LeoYeAI
汎用LLM・AI開発⭐ リポ 21,584

skyvern

AI駆動のブラウザ自動化により、任意のウェブサイトを自動化できます。フォーム入力、データ抽出、ファイルダウンロード、ログイン、複数ステップのワークフロー実行など、ユーザーがウェブサイトと連携する必要があるときに使用します。Skyvernは、LLMとコンピュータビジョンを活用して、未知のサイトも自動操作可能です。Python SDK、TypeScript SDK、REST API、MCPサーバー、またはCLIを通じて統合できます。

by Skyvern-AI
汎用LLM・AI開発⭐ リポ 1,149

pinchbench

PinchBenchベンチマークを実行して、OpenClawエージェントの実世界タスクにおけるパフォーマンスを評価できます。モデルの機能テスト、モデル間の比較、ベンチマーク結果のリーダーボード提出、またはOpenClawのセットアップがカレンダー、メール、リサーチ、コーディング、複数ステップのワークフローにどの程度対応しているかを確認する際に使用します。

by pinchbench
汎用LLM・AI開発⭐ リポ 4,693

openui

OpenUIとOpenUI Langを使用してジェネレーティブUIアプリを構築できます。これらはLLM生成インターフェースのためのトークン効率的なオープン標準です。OpenUI、@openuidev、ジェネレーティブUI、LLMからのストリーミングUI、AI向けコンポーネントライブラリ、またはjson-render/A2UIの置き換えについて述べる際に使用します。スキャフォルディング、defineComponent、システムプロンプト、Renderer、およびOpenUI Lang出力のデバッグに対応しています。

by thesysdev
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: freshtechbro · freshtechbro/claudedesignskills · ライセンス: MIT