postfx-bloom について
postfx-bloomは、three.jsとReact Three Fiberのシーン向けBloomポストプロセスのガイドです。輝度ベースのグローや選択的なBloomに加え、アニメーション、音声連動、性能調整を扱います。
主な機能
- 01輝度しきい値とぼかし合成
- 02オブジェクト単位のBloom
- 03強度アニメーションのパターン
- 04音声連動グロー
- 05性能調整とトラブルシューティング
活用シーン
- 013Dシーンへのグロー追加
- 02脈動するBloom効果の作成
- 03音声データに応じたグロー強度の調整
- 04Bloomの表示や性能の問題解決
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ bbeierle12/ skill-mcp-claude --skill postfx-bloomインストール後、Claude Code で/postfx-bloomを入力して読み込まれたか確認します。
同梱ファイル_meta.json
詳細
ポストプロセスのブルーム
UnrealBloomPass を使用した、輝度ベースのグローとオブジェクトを選択したブルーム効果です。
クイックスタート
npm install three @react-three/fiber @react-three/postprocessing
import { Canvas } from '@react-three/fiber';
import { EffectComposer, Bloom } from '@react-three/postprocessing';
function Scene() {
return (
<Canvas>
<mesh>
<sphereGeometry args={[1, 32, 32]} />
<meshStandardMaterial emissive="#00F5FF" emissiveIntensity={2} />
</mesh>
<EffectComposer>
<Bloom
luminanceThreshold={0.2}
luminanceSmoothing={0.9}
intensity={1.5}
/>
</EffectComposer>
</Canvas>
);
}
基本概念
ブルームの仕組み
- しきい値 — しきい値より明るいピクセルを抽出します
- ぼかし — 抽出したピクセルを複数のパスでぼかします
- 合成 — ぼかした結果を元の画像に加えます
主なパラメーター
| パラメーター | 範囲 | 説明 |
|---|---|---|
luminanceThreshold | 0-1 | ブルームを適用する明るさのしきい値(値が小さいほどグローが強くなります) |
luminanceSmoothing | 0-1 | しきい値の遷移の滑らかさ |
intensity | 0-10 | ブルームの明るさの倍率 |
radius | 0-1 | ぼかしの広がり/サイズ |
levels | 1-9 | ぼかしの品質/反復回数 |
パターン
コズミックグロー効果
import { EffectComposer, Bloom } from '@react-three/postprocessing';
import { KernelSize } from 'postprocessing';
function CosmicBloom() {
return (
<EffectComposer>
<Bloom
luminanceThreshold={0.1}
luminanceSmoothing={0.9}
intensity={2.5}
radius={0.8}
kernelSize={KernelSize.LARGE}
mipmapBlur
/>
</EffectComposer>
);
}
ネオン・サイバーパンクのブルーム
// High-contrast neon with sharp falloff
function NeonBloom() {
return (
<EffectComposer>
<Bloom
luminanceThreshold={0.4}
luminanceSmoothing={0.2}
intensity={3.0}
radius={0.4}
mipmapBlur
/>
</EffectComposer>
);
}
// Emissive material for neon objects
function NeonTube({ color = '#FF00FF' }) {
return (
<mesh>
<cylinderGeometry args={[0.05, 0.05, 2]} />
<meshStandardMaterial
emissive={color}
emissiveIntensity={4}
toneMapped={false}
/>
</mesh>
);
}
レイヤーを使った選択的ブルーム
import { useRef } from 'react';
import { useThree } from '@react-three/fiber';
import { EffectComposer, SelectiveBloom } from '@react-three/postprocessing';
function SelectiveGlow() {
const glowRef = useRef();
return (
<>
{/* Non-blooming object */}
<mesh position={[-2, 0, 0]}>
<boxGeometry />
<meshStandardMaterial color="#333" />
</mesh>
{/* Blooming object */}
<mesh ref={glowRef} position={[2, 0, 0]}>
<sphereGeometry args={[0.5, 32, 32]} />
<meshStandardMaterial
emissive="#00F5FF"
emissiveIntensity={3}
/>
</mesh>
<EffectComposer>
<SelectiveBloom
selection={glowRef}
luminanceThreshold={0.1}
intensity={2}
mipmapBlur
/>
</EffectComposer>
</>
);
}
複数選択のブルーム
import { Selection, Select, EffectComposer } from '@react-three/postprocessing';
import { SelectiveBloom } from '@react-three/postprocessing';
function MultiSelectBloom() {
return (
<Selection>
{/* Non-blooming */}
<mesh position={[-2, 0, 0]}>
<boxGeometry />
<meshStandardMaterial color="#333" />
</mesh>
{/* Blooming objects wrapped in Select */}
<Select enabled>
<mesh position={[0, 0, 0]}>
<sphereGeometry args={[0.5]} />
<meshStandardMaterial emissive="#00F5FF" emissiveIntensity={2} />
</mesh>
</Select>
<Select enabled>
<mesh position={[2, 0, 0]}>
<octahedronGeometry args={[0.5]} />
<meshStandardMaterial emissive="#FF00FF" emissiveIntensity={2} />
</mesh>
</Select>
<EffectComposer>
<SelectiveBloom
luminanceThreshold={0.1}
intensity={1.5}
mipmapBlur
/>
</EffectComposer>
</Selection>
);
}
ブルーム強度のアニメーション
import { useRef } from 'react';
import { useFrame } from '@react-three/fiber';
import { EffectComposer, Bloom } from '@react-three/postprocessing';
function PulsingBloom() {
const bloomRef = useRef();
useFrame(({ clock }) => {
if (bloomRef.current) {
const pulse = Math.sin(clock.elapsedTime * 2) * 0.5 + 1.5;
bloomRef.current.intensity = pulse;
}
});
return (
<EffectComposer>
<Bloom
ref={bloomRef}
luminanceThreshold={0.2}
intensity={1.5}
mipmapBlur
/>
</EffectComposer>
);
}
音声に反応するブルーム
function AudioReactiveBloom({ audioData }) {
const bloomRef = useRef();
useFrame(() => {
if (bloomRef.current && audioData) {
// Map bass frequency (0-255) to bloom intensity (1-4)
const bassLevel = audioData[0] / 255;
bloomRef.current.intensity = 1 + bassLevel * 3;
// Map mid frequencies to threshold
const midLevel = audioData[4] / 255;
bloomRef.current.luminanceThreshold = 0.1 + (1 - midLevel) * 0.3;
}
});
return (
<EffectComposer>
<Bloom
ref={bloomRef}
luminanceThreshold={0.2}
intensity={1.5}
mipmapBlur
/>
</EffectComposer>
);
}
発光マテリアル
標準的な発光の設定
// For bloom to work, objects need emissive materials
function GlowingSphere({ color = '#00F5FF', intensity = 2 }) {
return (
<mesh>
<sphereGeometry args={[1, 32, 32]} />
<meshStandardMaterial
color="#000"
emissive={color}
emissiveIntensity={intensity}
toneMapped={false} // Important: prevents HDR clamping
/>
</mesh>
);
}
テクスチャを使った発光
import { useTexture } from '@react-three/drei';
function EmissiveTextured() {
const emissiveMap = useTexture('/glow-pattern.png');
return (
<mesh>
<planeGeometry args={[2, 2]} />
<meshStandardMaterial
emissiveMap={emissiveMap}
emissive="#FFFFFF"
emissiveIntensity={3}
toneMapped={false}
/>
</mesh>
);
}
発光を使ったシェーダーマテリアル
import { shaderMaterial } from '@react-three/drei';
import { extend } from '@react-three/fiber';
const GlowMaterial = shaderMaterial(
{ uTime: 0, uColor: [0, 0.96, 1], uIntensity: 2.0 },
// Vertex shader
`
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
// Fragment shader - outputs HDR values for bloom
`
uniform float uTime;
uniform vec3 uColor;
uniform float uIntensity;
varying vec2 vUv;
void main() {
float pulse = sin(uTime * 2.0) * 0.3 + 0.7;
vec3 glow = uColor * uIntensity * pulse;
gl_FragColor = vec4(glow, 1.0);
}
`
);
extend({ GlowMaterial });
function PulsingGlowMesh() {
const materialRef = useRef();
useFrame(({ clock }) => {
materialRef.current.uTime = clock.elapsedTime;
});
return (
<mesh>
<sphereGeometry args={[1, 32, 32]} />
<glowMaterial ref={materialRef} toneMapped={false} />
</mesh>
);
}
パフォーマンスの最適化
解像度のスケーリング
<EffectComposer
multisampling={0} // Disable MSAA for performance
>
<Bloom
luminanceThreshold={0.2}
intensity={1.5}
mipmapBlur // More efficient blur method
radius={0.8}
levels={5} // Reduce for performance (default: 8)
/>
</EffectComposer>
モバイル向けに最適化したブルーム
import { useDetectGPU } from '@react-three/drei';
function AdaptiveBloom() {
const { tier } = useDetectGPU();
const config = tier < 2
? { levels: 3, radius: 0.5, intensity: 1.0 }
: { levels: 5, radius: 0.8, intensity: 1.5 };
return (
<EffectComposer multisampling={tier < 2 ? 0 : 4}>
<Bloom
luminanceThreshold={0.2}
luminanceSmoothing={0.9}
mipmapBlur
{...config}
/>
</EffectComposer>
);
}
時間崩壊テーマ
新年のカウントダウンに合わせた、宇宙をイメージしたブルーム設定です。
// Cosmic void with cyan/magenta glow
function TemporalCollapseBloom() {
return (
<EffectComposer>
<Bloom
luminanceThreshold={0.15}
luminanceSmoothing={0.9}
intensity={2.0}
radius={0.85}
mipmapBlur
/>
</EffectComposer>
);
}
// Color palette for emissive materials
const TEMPORAL_COLORS = {
cyan: '#00F5FF',
magenta: '#FF00FF',
gold: '#FFD700',
void: '#050508'
};
// Time digit with glow
function GlowingDigit({ digit, color = TEMPORAL_COLORS.cyan }) {
return (
<Text3D font="/fonts/cosmic.json" size={2} height={0.2}>
{digit}
<meshStandardMaterial
color="#111"
emissive={color}
emissiveIntensity={3}
toneMapped={false}
/>
</Text3D>
);
}
トラブルシューティング
| 問題 | 解決策 |
|---|---|
| ブルームが表示されない | emissiveIntensity > 1 と toneMapped={false} が設定されていることを確認します |
| ブルームが弱すぎる | luminanceThreshold を下げ、intensity を上げます |
| パフォーマンスの問題 | levels を減らし、mipmapBlur を有効にして、マルチサンプリングを無効にします |
| 選択的ブルームが機能しない | ref が渡され、オブジェクトに発光マテリアルが設定されていることを確認します |
| ブルームが全体に広がる | luminanceThreshold を上げて、明るい領域を絞り込みます |
リファレンス
postfx-composerで EffectComposer の設定パターンを参照してくださいpostfx-effectsでブルームをほかの効果と組み合わせる方法を参照してくださいshaders-glslでカスタム発光シェーダーの手法を参照してください
コメント
Markdown 対応