title: "カスタムエフェクト" description: "Three.jsのポストプロセスパイプラインにカスタムシェーダーエフェクトを組み込む方法を学びます。" chapter: "10-threejs" order: 4 challenge: description: "CRTモニター風のポストプロセスエフェクトを作ってください。走査線(スキャンライン)と画面端のビネット効果を組み合わせましょう。" hints:
- "走査線はsin(vUv.y * 800.0) * 0.04のように高周波のsinで縞模様を作ります。"
- "ビネットは画面中心からの距離を使います。"
- "元のテクスチャ色に走査線を減算し、ビネットを乗算します。"
カスタムエフェクト
ポストプロセスとは
ポストプロセスは、3Dシーンのレンダリング結果(画像)に後処理を適用する技法です。ブルーム、被写界深度、色調補正など、映画のような表現が可能になります。
Three.jsのポストプロセス
Three.jsではEffectComposerを使ってポストプロセスのパイプラインを構築します。パイプラインには複数の「パス」を追加でき、順番に処理が適用されます:
- RenderPass -- 通常の3Dシーンレンダリング
- ShaderPass -- カスタムシェーダーエフェクト
- 追加のパス...
レンダリングループでは renderer.render() の代わりに composer.render() を呼びます。
カスタムShaderPassの作成
ShaderPassに渡すシェーダーオブジェクトには、特別なuniform tDiffuse が必要です。これには前のパスの出力テクスチャが自動的に設定されます。
フラグメントシェーダーの例:
// ポストプロセス用フラグメントシェーダー
uniform sampler2D tDiffuse;
uniform float u_time;
uniform float u_intensity;
varying vec2 vUv;
void main() {
vec4 texel = texture2D(tDiffuse, vUv);
// セピア調エフェクト
vec3 color = texel.rgb;
float gray = dot(color, vec3(0.299, 0.587, 0.114));
vec3 sepia = vec3(gray) * vec3(1.2, 1.0, 0.8);
color = mix(color, sepia, u_intensity);
gl_FragColor = vec4(color, 1.0);
}
R3Fでのポストプロセス
React Three Fiberでは@react-three/postprocessingライブラリを使うのが一般的です。EffectComposer、Bloom、VignetteなどのコンポーネントをCanvas内に配置するだけで簡単にエフェクトを追加できます。
カスタムEffectの作成
postprocessingライブラリのEffectクラスを継承してカスタムエフェクトを作れます。mainImage関数を定義し、入力色を受け取って加工した色を出力します:
// カスタムEffect用のフラグメントシェーダー
// mainImage関数で処理を定義
// inputColor: 前段の処理結果
// uv: テクスチャ座標
// outputColor: 出力色
// 走査線エフェクトの例
// float scanline = sin(uv.y * 800.0) * 0.04;
// outputColor = vec4(inputColor.rgb - scanline, inputColor.a);
よく使うエフェクト
| エフェクト | 用途 | |-----------|------| | Bloom | 明るい部分を光らせるグロー効果 | | Vignette | 画面端を暗くするフィルム風効果 | | ChromaticAberration | 色ずれ(色収差)効果 | | Glitch | デジタルグリッチ効果 | | Noise | フィルムグレイン風ノイズ | | SSAO | スクリーンスペースアンビエントオクルージョン |
まとめ
- ポストプロセスはレンダリング結果に後処理を適用する技法
EffectComposerとShaderPassでカスタムエフェクトを作れるtDiffuseuniformで前のパスの出力テクスチャを受け取る- R3Fでは
@react-three/postprocessingが便利 - カスタムEffectクラスで独自エフェクトを定義できる