mcpField
R
r3f-shaders

r3f-shaders

github.com/enzed開発1312.0k 回インストール8 週間前に更新
リポジトリ

r3f-shaders について

React Three Fiber 開発者向けのシェーダー作成スキルです。WebGL のカスタムマテリアルや組み込みマテリアルの変更に加え、バージョンや描画パイプライン、よくある問題を扱います。

主な機能

  1. 01WebGL と WebGPU のシェーダー経路の選択
  2. 02Drei shaderMaterial によるアニメーションマテリアル作成
  3. 03uniform とシェーダーコンパイルの管理
  4. 04座標空間とカラー管理の処理
  5. 05変形ジオメトリの法線とシャドウ設定
  6. 06onBeforeCompile による組み込みマテリアルの変更

活用シーン

  1. 01React Three Fiber シーンのアニメーションマテリアル作成
  2. 02GLSL のコンパイルやカラー出力の問題調査
  3. 03頂点変形に合わせたライティングとシャドウの維持

インストール

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

$npx skills add https://github.com/enzed/r3f-skills --skill r3f-shaders

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

同梱ファイルreferences/webgpu.md

詳細

React Three Fiber シェーダー

シェーダーの選択

まず、インストールされている Fiber、Drei、Three.js、レンダラーのバージョンを確認します。この例は Fiber 9/React 19 と WebGL を使用しています。既存のプロジェクトでは、現在のバージョンを維持してください。

  • エフェクトを組み立てるプロパティがある場合は、組み込みマテリアルを使用します。カスタム WebGL シェーディングには、Drei の shaderMaterial またはネイティブの <shaderMaterial> を使用します。
  • WebGPU ではノードマテリアルと TSL を使用します。GLSL の ShaderMaterial と onBeforeCompile は WebGPU に移植できません。該当するレンダラーを使用する場合に限り、WebGPU and TSL をお読みください。
  • シェーダーは自動的にライティング、シャドウ、フォグ、インスタンシング、スキニングに対応するわけではありません。組み込みマテリアルを置き換える前に、必要な機能を選択してください。

アニメーションする WebGL マテリアル

Canvas の下にマウントします。マテリアルクラスと extend の呼び出しは、レンダーの外に置きます。このローカルコンポーネントでは、グローバルな JSX の拡張は不要です。

import { useRef } from 'react'
import { extend, useFrame } from '@react-three/fiber'
import { shaderMaterial } from '@react-three/drei'
import { Color } from 'three'

const WaveMaterial = shaderMaterial(
  { uTime: 0, uColor: new Color('coral') },
  `uniform float uTime;
   varying vec2 vUv;
   void main() {
     vUv = uv;
     vec3 p = position;
     p.z += sin(p.x * 4.0 + uTime) * 0.15;
     gl_Position = projectionMatrix * modelViewMatrix * vec4(p, 1.0);
   }`,
  `uniform vec3 uColor;
   varying vec2 vUv;
   void main() {
     gl_FragColor = vec4(uColor * (0.4 + 0.6 * vUv.y), 1.0);
     #include <tonemapping_fragment>
     #include <colorspace_fragment>
   }`,
)
const Wave = extend(WaveMaterial)

export default function Example() {
  const material = useRef<InstanceType<typeof WaveMaterial>>(null)
  useFrame((_, delta) => {
    if (material.current) material.current.uTime += delta
  })
  return (
    <mesh>
      <planeGeometry args={[3, 3, 32, 32]} />
      <Wave ref={material} key={WaveMaterial.key} />
    </mesh>
  )
}

Uniform とコンパイル

  • Drei の shaderMaterial は uniform アクセサーを作成します。material.uTime を割り当ててください。ネイティブの ShaderMaterial では、material.uniforms.uTime.value を使用します。
  • uniform コンテナは安定した状態に保ちます。毎フレーム React の state を設定するのではなく、値を変更してください。値のみの uniform 変更では、material.needsUpdate を設定しないでください。
  • シェーダーソース、define、機能の変更では、再コンパイルが必要になることがあります。ホットリロードにはクラスの key を使用し、アニメーション中に React の key を変更しないでください。
  • Fiber 9 では extend(Class) を使用できます。小文字のグローバル要素を使う場合は、ThreeElement<typeof Class> で ThreeElements を拡張してください。削除された Object3DNode は、マテリアルの型指定の代替にはなりません。
  • GLSL 文字列は TypeScript によるチェックの対象外です。実際にレンダリングし、実際のレンダラーやエフェクトを使用する構成も含めて、シェーダーコンパイラーのエラーを確認してください。
  • シェーダーソースは JavaScript のテンプレートリテラル内にあります。そのため、GLSL 内のどこであっても、コメント内を含めてバッククォートや ${ があると、文字列が意図せず終了し、モジュールが壊れます。シェーダーのコメントにはバッククォートを使わず、これを目視で確認するのではなく、型チェッカーに検出させてください。

空間、色、ジオメトリ

  • 法線、光の方向、視線方向は、同じ座標空間にそろえます。normalMatrix * normal はビュー空間です。これをワールド空間のカメラ方向との内積に使用しないでください。
  • Color を介して渡される CSS/16 進数カラーは、リニアの作業色空間に変換されます。数値の uniform ベクトルはすでにリニアなので、二重に変換しないでください。
  • 色入力テクスチャには SRGBColorSpace、データテクスチャには NoColorSpace を設定します。テクスチャのサンプリングと出力変換は、マテリアル/レンダラーのパイプラインに合わせてください。
  • Canvas に直接書き込む WebGL シェーダーでは、例のようにトーンマッピングと出力色変換を適用します。手動でガンマ補正したうえで出力チャンクも適用しないでください。コンポーザーを介してレンダリングする場合は、最終出力をコンポーザーに任せてください。
  • 頂点の変形には、十分なジオメトリの分割数が必要です。ライティングが必要な場合は、法線も一貫して更新してください。シャドウを使用するには、深度マテリアル/距離マテリアルにも同じ変形を適用します。CPU のレイキャストと境界は、GPU の変形には自動的に追従しません。
  • ネイティブのカスタムインスタンシングシェーダーでは、instanceMatrix とインスタンスごとの属性を考慮する必要があります。スキニングとモーフターゲットにも、それぞれ対応するシェーダーロジックが必要です。

組み込み WebGL マテリアルへのパッチ適用

組み込みマテリアルのライティングを維持する必要がある場合に限り、onBeforeCompile を使用します。シェーダーチャンク名はバージョンによって変わるため、インストール済みのソースを確認し、Three.js の更新後にレンダリングテストを行ってください。

初回コンパイルより前にコールバックを設定します。設定変更によって生成される GLSL が変わる場合は、対応する customProgramCacheKey を指定して再コンパイルを実行してください。アニメーションする値は uniform に保持します。.clone() やシリアライズでコールバックが保持されるとは限りません。WebGPU を対象とするタスクでは、ノードマテリアルを優先してください。

参考資料

コメント