カスタムエフェクト


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を使ってポストプロセスのパイプラインを構築します。パイプラインには複数の「パス」を追加でき、順番に処理が適用されます:

  1. RenderPass -- 通常の3Dシーンレンダリング
  2. ShaderPass -- カスタムシェーダーエフェクト
  3. 追加のパス...

レンダリングループでは 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 | スクリーンスペースアンビエントオクルージョン |

まとめ

  • ポストプロセスはレンダリング結果に後処理を適用する技法
  • EffectComposerShaderPass でカスタムエフェクトを作れる
  • tDiffuse uniformで前のパスの出力テクスチャを受け取る
  • R3Fでは @react-three/postprocessing が便利
  • カスタムEffectクラスで独自エフェクトを定義できる