mcpField
T
threejs-lighting

threejs-lighting

github.com/sickn33開発48.8k101 回インストール今日更新
リポジトリ

threejs-lighting について

Three.js のシーン照明を扱う開発者向けのスキルです。ライトの種類、シャドウ、環境照明、性能上の考慮点、代表的な構成を説明します。

主な機能

  1. 01各種 Three.js ライトの設定
  2. 02シャドウの設定と最適化
  3. 03HDR 環境照明の利用
  4. 04代表的な照明構成の適用
  5. 05ライトのアニメーションと性能調整

活用シーン

  1. 01屋外シーンの日光設定
  2. 02屋内スタジオ照明の構築
  3. 03シャドウ品質と負荷の確認
  4. 04シーンの見やすさや雰囲気の改善

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill threejs-lighting

インストール後、Claude Code で/threejs-lightingを入力して読み込まれたか確認します。

詳細

Three.js のライティング

使用する場面

  • Three.js のシーンにライティングを追加、または調整する必要がある場合。
  • タスクにライトの種類、シャドウ、環境ライティング、またはライティングのパフォーマンス上のトレードオフが関係する場合。
  • Three.js のライティング設定によって、シーンの見やすさ、リアリティ、または雰囲気を向上させたい場合。

クイックスタート

import * as THREE from "three";

// Basic lighting setup
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 5, 5);
scene.add(directionalLight);

ライトの種類の概要

ライト説明シャドウのサポートコスト
AmbientLight全体を均一に照らすなし非常に低
HemisphereLight空と地面のグラデーションなし非常に低
DirectionalLight平行光線(太陽)あり低
PointLight全方向(電球)あり中
SpotLight円錐状あり中
RectAreaLight面光源(窓)なし*高

*RectAreaLight のシャドウにはカスタムの手法が必要です。

AmbientLight

すべてのオブジェクトを均等に照らします。方向性はなく、シャドウもありません。

// AmbientLight(color, intensity)
const ambient = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambient);

// Modify at runtime
ambient.color.set(0xffffcc);
ambient.intensity = 0.3;

HemisphereLight

空から地面の色へと変化するグラデーションです。屋外のシーンに適しています。

// HemisphereLight(skyColor, groundColor, intensity)
const hemi = new THREE.HemisphereLight(0x87ceeb, 0x8b4513, 0.6);
hemi.position.set(0, 50, 0);
scene.add(hemi);

// Properties
hemi.color; // Sky color
hemi.groundColor; // Ground color
hemi.intensity;

DirectionalLight

平行な光線です。遠方の光源(太陽)をシミュレートします。

// DirectionalLight(color, intensity)
const dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(5, 10, 5);

// Light points at target (default: 0, 0, 0)
dirLight.target.position.set(0, 0, 0);
scene.add(dirLight.target);

scene.add(dirLight);
DirectionalLight のシャドウ
dirLight.castShadow = true;

// Shadow map size (higher = sharper, more expensive)
dirLight.shadow.mapSize.width = 2048;
dirLight.shadow.mapSize.height = 2048;

// Shadow camera (orthographic)
dirLight.shadow.camera.near = 0.5;
dirLight.shadow.camera.far = 50;
dirLight.shadow.camera.left = -10;
dirLight.shadow.camera.right = 10;
dirLight.shadow.camera.top = 10;
dirLight.shadow.camera.bottom = -10;

// Shadow softness
dirLight.shadow.radius = 4; // Filtering behavior depends on renderer/version/shadow type; verify the installed reference

// Shadow bias (fixes shadow acne)
dirLight.shadow.bias = -0.0001;
dirLight.shadow.normalBias = 0.02;

// Helper to visualize shadow camera
const helper = new THREE.CameraHelper(dirLight.shadow.camera);
scene.add(helper);

PointLight

一点から全方向に光を放ちます。電球のようなライトです。

// PointLight(color, intensity, distance, decay)
const pointLight = new THREE.PointLight(0xffffff, 1, 100, 2);
pointLight.position.set(0, 5, 0);
scene.add(pointLight);

// Properties
pointLight.distance; // Maximum range (0 = infinite)
pointLight.decay; // Light falloff (physically correct = 2)
PointLight のシャドウ
pointLight.castShadow = true;
pointLight.shadow.mapSize.width = 1024;
pointLight.shadow.mapSize.height = 1024;

// Shadow camera (perspective - 6 directions for cube map)
pointLight.shadow.camera.near = 0.5;
pointLight.shadow.camera.far = 50;

pointLight.shadow.bias = -0.005;

SpotLight

円錐状の光です。懐中電灯やステージライトのようなライトです。

// SpotLight(color, intensity, distance, angle, penumbra, decay)
const spotLight = new THREE.SpotLight(0xffffff, 1, 100, Math.PI / 6, 0.5, 2);
spotLight.position.set(0, 10, 0);

// Target (light points at this)
spotLight.target.position.set(0, 0, 0);
scene.add(spotLight.target);

scene.add(spotLight);

// Properties
spotLight.angle; // Cone angle (radians, max Math.PI/2)
spotLight.penumbra; // Soft edge (0-1)
spotLight.distance; // Range
spotLight.decay; // Falloff
SpotLight のシャドウ
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;

// Shadow camera (perspective)
spotLight.shadow.camera.near = 0.5;
spotLight.shadow.camera.far = 50;
spotLight.shadow.camera.fov = 30;

spotLight.shadow.bias = -0.0001;

// Focus (affects shadow projection)
spotLight.shadow.focus = 1;

RectAreaLight

長方形の面光源です。柔らかくリアルなライティングに最適です。

import { RectAreaLightHelper } from "three/examples/jsm/helpers/RectAreaLightHelper.js";
import { RectAreaLightUniformsLib } from "three/examples/jsm/lights/RectAreaLightUniformsLib.js";

// Must initialize uniforms first (WebGL renderer only)
RectAreaLightUniformsLib.init();

// RectAreaLight(color, intensity, width, height)
const rectLight = new THREE.RectAreaLight(0xffffff, 5, 4, 2);
rectLight.position.set(0, 5, 0);
rectLight.lookAt(0, 0, 0);
scene.add(rectLight);

// Helper
const helper = new RectAreaLightHelper(rectLight);
rectLight.add(helper);

// Works with MeshStandardMaterial, MeshPhysicalMaterial
// r183: Clearcoat on MeshPhysicalMaterial is now properly lit by RectAreaLight
// Does not cast shadows natively

シャドウの設定

シャドウを有効にする
// 1. Enable on renderer
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;

// Shadow map types:
// THREE.BasicShadowMap - fastest, low quality
// THREE.PCFShadowMap - default, filtered
// THREE.PCFSoftShadowMap - softer edges
// THREE.VSMShadowMap - variance shadow map

// 2. Enable on light
light.castShadow = true;

// 3. Enable on objects
mesh.castShadow = true;
mesh.receiveShadow = true;

// Ground plane
floor.receiveShadow = true;
floor.castShadow = false; // Usually false for floors
シャドウの最適化
// Tight shadow camera frustum
const d = 10;
dirLight.shadow.camera.left = -d;
dirLight.shadow.camera.right = d;
dirLight.shadow.camera.top = d;
dirLight.shadow.camera.bottom = -d;
dirLight.shadow.camera.near = 0.5;
dirLight.shadow.camera.far = 30;

// Fix shadow acne
dirLight.shadow.bias = -0.0001; // Depth bias
dirLight.shadow.normalBias = 0.02; // Bias along normal

// Shadow map size (balance quality vs performance)
// 512 - low quality
// 1024 - medium quality
// 2048 - high quality
// 4096 - very high quality (expensive)
接地シャドウ

three/examples/jsm/objects/ContactShadows.js はインポートしないでください。このガイドでは、そのパスにあることが確認済みの Three.js アドオンを特定していません。React Three Fiber プロジェクトでは、Drei の ContactShadows は別個のコンポーネント/依存関係です。導入する前に、そのバージョンとパフォーマンスコストを確認してください。プレーンな Three.js プロジェクトでは、レビュー済みのレンダーターゲット実装またはサポート対象の代替手段が必要です。

ライトヘルパー

import { RectAreaLightHelper } from "three/examples/jsm/helpers/RectAreaLightHelper.js";

// DirectionalLight helper
const dirHelper = new THREE.DirectionalLightHelper(dirLight, 5);
scene.add(dirHelper);

// PointLight helper
const pointHelper = new THREE.PointLightHelper(pointLight, 1);
scene.add(pointHelper);

// SpotLight helper
const spotHelper = new THREE.SpotLightHelper(spotLight);
scene.add(spotHelper);

// Hemisphere helper
const hemiHelper = new THREE.HemisphereLightHelper(hemi, 5);
scene.add(hemiHelper);

// RectAreaLight helper
const rectHelper = new RectAreaLightHelper(rectLight);
rectLight.add(rectHelper);

// Update helpers when light changes
dirHelper.update();
spotHelper.update();

環境ライティング(IBL)

HDR 環境マップを使用するイメージベースドライティングです。

import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";

const rgbeLoader = new RGBELoader();
rgbeLoader.load("environment.hdr", (texture) => {
  texture.mapping = THREE.EquirectangularReflectionMapping;

  // Set as scene environment (affects all PBR materials)
  scene.environment = texture;

  // Optional: also use as background
  scene.background = texture;
  scene.backgroundBlurriness = 0; // 0-1, blur the background
  scene.backgroundIntensity = 1;
});

// PMREMGenerator for better reflections
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();

rgbeLoader.load("environment.hdr", (texture) => {
  const envMap = pmremGenerator.fromEquirectangular(texture).texture;
  scene.environment = envMap;
  texture.dispose();
  pmremGenerator.dispose();
});
キューブテクスチャ環境
const cubeLoader = new THREE.CubeTextureLoader();
const envMap = cubeLoader.load([
  "px.jpg",
  "nx.jpg",
  "py.jpg",
  "ny.jpg",
  "pz.jpg",
  "nz.jpg",
]);

scene.environment = envMap;
scene.background = envMap;

ライトプローブ(上級)

空間内の一点からライティングをキャプチャして、アンビエントライティングに使用します。

import { LightProbeGenerator } from "three/examples/jsm/lights/LightProbeGenerator.js";

// Generate from cube texture
const lightProbe = new THREE.LightProbe();
scene.add(lightProbe);

lightProbe.copy(LightProbeGenerator.fromCubeTexture(cubeTexture));

// Or from render target
const cubeCamera = new THREE.CubeCamera(
  0.1,
  100,
  new THREE.WebGLCubeRenderTarget(256),
);
cubeCamera.update(renderer, scene);
lightProbe.copy(
  LightProbeGenerator.fromCubeRenderTarget(renderer, cubeCamera.renderTarget),
);

一般的なライティング設定

3点ライティング
// Key light (main light)
const keyLight = new THREE.DirectionalLight(0xffffff, 1);
keyLight.position.set(5, 5, 5);
scene.add(keyLight);

// Fill light (softer, opposite side)
const fillLight = new THREE.DirectionalLight(0xffffff, 0.5);
fillLight.position.set(-5, 3, 5);
scene.add(fillLight);

// Back light (rim lighting)
const backLight = new THREE.DirectionalLight(0xffffff, 0.3);
backLight.position.set(0, 5, -5);
scene.add(backLight);

// Ambient fill
const ambient = new THREE.AmbientLight(0x404040, 0.3);
scene.add(ambient);
屋外の昼光
// Sun
const sun = new THREE.DirectionalLight(0xffffcc, 1.5);
sun.position.set(50, 100, 50);
sun.castShadow = true;
scene.add(sun);

// Sky ambient
const hemi = new THREE.HemisphereLight(0x87ceeb, 0x8b4513, 0.6);
scene.add(hemi);
屋内スタジオ
// Multiple area lights
RectAreaLightUniformsLib.init();

const light1 = new THREE.RectAreaLight(0xffffff, 5, 2, 2);
light1.position.set(3, 3, 3);
light1.lookAt(0, 0, 0);
scene.add(light1);

const light2 = new THREE.RectAreaLight(0xffffff, 3, 2, 2);
light2.position.set(-3, 3, 3);
light2.lookAt(0, 0, 0);
scene.add(light2);

// Ambient fill
const ambient = new THREE.AmbientLight(0x404040, 0.2);
scene.add(ambient);

ライトのアニメーション

const clock = new THREE.Clock();

function animate() {
  const time = clock.getElapsedTime();

  // Orbit light around scene
  light.position.x = Math.cos(time) * 5;
  light.position.z = Math.sin(time) * 5;

  // Pulsing intensity
  light.intensity = 1 + Math.sin(time * 2) * 0.5;

  // Color cycling
  light.color.setHSL((time * 0.1) % 1, 1, 0.5);

  // Update helpers if using
  lightHelper.update();
}

パフォーマンスのヒント

  1. ライトの数を制限する:ライトごとにシェーダーが複雑になります。
  2. ベイクしたライティングを使う:静的なシーンでは、ライティングをテクスチャにベイクします。
  3. シャドウマップを小さくする:512~1024 で十分な場合が多くあります。
  4. シャドウのフラスタムを絞る:必要な領域だけをカバーします。
  5. 使用しないシャドウを無効にする:すべてのライトにシャドウが必要なわけではありません。
  6. カメラレイヤーを慎重に使う:レイヤーはカメラからの可視性を制御するものであり、メッシュごとの一般的なライトリンクを制御するものではありません。
// Camera layers control visibility. Do not assume matching light/mesh layers
// isolates that light to that mesh; verify supported light-linking mechanisms
// for the selected renderer/version.

// Selective shadows
mesh.castShadow = true;
mesh.receiveShadow = true;
decorMesh.castShadow = false; // Small objects often don't need to cast

関連項目

  • threejs-materials - マテリアルのライトへの反応
  • threejs-textures - ライトマップと環境マップ
  • threejs-postprocessing - ブルームなどのライト効果

制限事項

  • タスクが上記の説明された範囲に明確に合致する場合に限り、このスキルを使用してください。
  • 出力を、環境固有の検証、テスト、または専門家によるレビューの代替として扱わないでください。
  • 必要な入力、権限、安全上の境界、または成功基準が不足している場合は、作業を中断して確認を求めてください。

コメント