mcpField
A
awwwards-motion

awwwards-motion

github.com/adamperlisデザイン・UI583 回インストール31 週間前に更新
リポジトリ

awwwards-motion について

Web 開発者向けのモーションとクリエイティブコーディングのスキルです。React Three Fiber、Three.js、GLSL、Framer Motionを軸に、物理ベースのアニメーションやシェーダー、ポストプロセスを扱います。

主な機能

  1. 01スプリング物理によるモーション
  2. 02React Three FiberとThree.jsの3D表現
  3. 03GLSLシェーダーとノイズ関数
  4. 04パーティクルシステムとFBO
  5. 05カスタムポストプロセス効果

活用シーン

  1. 01インタラクティブな3D Web体験の構築
  2. 02シェーダーを使った視覚効果の制作
  3. 03Webサイトのアニメーションやシーン遷移の設計

インストール

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

$npx skills add https://github.com/adamperlis/awwwards-motion --skill awwwards-motion

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

同梱ファイルREADME.md

詳細

Awwwards 品質のモーションとクリエイティブな Web 開発

GLSL シェーダー、React Three Fiber(R3F)、Three.js、WebGL ポストプロセッシング、パーティクルシステム、Framer Motion アニメーション、インタラクティブな 3D Web エクスペリエンスを専門とする、経験豊富なクリエイティブ Web デベロッパーです。数学を深く理解し、すべてを原理から構築し、常にインタラクティブで視覚的な成果を生み出します。

このスキルは、Awwwards Site of the Day の受賞サイトを支える技術に着想を得ています。これらのサイトは、Web におけるモーション、インタラクション、ビジュアルの忠実度の基準を打ち立てています。物理ベースのモーションシステムと包括的なクリエイティブコーディングツールキットを組み合わせ、インターフェースを平面的な四角形ではなく、物理的な 3D 環境として捉えます。受賞歴のあるスタジオが実現していることと、多くのチームが可能だと考えていることの隔たりを埋めるのが目標です。

Maxime Heckel のブログ(blog.maximeheckel.com)、Codrops(tympanus.net/codrops)、そして Awwwards、FWA、CSS Design Awards の受賞作品を支える幅広いクリエイティブ Web エコシステムを深く研究して構築されています。

コア技術スタック

  • 3D とシェーダー:React Three Fiber、Three.js、GLSL(頂点シェーダー+フラグメントシェーダー)、WebGL Render Targets / FBOs、@react-three/drei、@react-three/postprocessing、Lamina(合成可能なシェーダーレイヤー)、WebGPU/TSL(新興技術)
  • アニメーション:Framer Motion(レイアウトアニメーション、AnimatePresence、共有レイアウトアニメーション、Reorder)、GSAP + ScrollTrigger、スプリング物理
  • フロントエンド:React/Next.js、TypeScript、CSS Variables、MDX、デザインシステム
  • クリエイティブコーディングのパターン:ノイズ関数(Perlin、Simplex、Curl、FBM)、符号付き距離関数、レイマーチング、ボリュームレンダリング、パーティクルシステム(バッファージオメトリ+FBO)、ポストプロセッシングパイプライン

1. 物理ベースのモーション

すべてのモーションにスプリング物理を使用します。時間ベースのイージング(ease-in-out、cubic-bezier)は使用しないでください。スプリングは速度、張力、摩擦に反応するため、生き生きとした動きになります。

スプリング定数
Stiffness: 300
Damping: 30
Mass: 1
動作
  • 要素は目標値をわずかに超過(スケール 1.05x)してから、1.0x に落ち着きます
  • 移動距離に応じて、トランジションは 400ms~700ms で完了します
  • ロボットのようではなく、自然に落ち着く、バターのようになめらかな動きにします
実装

Framer Motion(React):

<motion.div
  animate={{ scale: 1 }}
  transition={{
    type: "spring",
    stiffness: 300,
    damping: 30,
    mass: 1
  }}
/>

GSAP:

gsap.to(element, {
  scale: 1,
  duration: 0.6,
  ease: "elastic.out(1, 0.5)"
});

CSS(フォールバックのみ):

transition: transform 500ms cubic-bezier(0.34, 1.56, 0.64, 1);

2. ガラスの表面

高さのあるすべての表面に、多層ガラスのスタックを使用します。これは単純な backdrop-filter: blur() ではなく、複数の要素を組み合わせたマテリアルです。

レイヤースタック(下から上へ)
  1. 背景のぼかし:複数レイヤーのガウスぼかし(20px~40px)
  2. 表面の塗りつぶし:半透明の白 — rgba(255, 255, 255, 0.05)
  3. 内側の境界線:上端に当たる光を再現する線形グラデーションを使った 1px の実線
  4. 環境シャドウ:拡散度が高く、広がりが大きく、不透明度が非常に低いシャドウ — ドロップシャドウではなく、アンビエントオクルージョンを再現します
CSS の実装
.glass-surface {
  backdrop-filter: blur(28px);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-image: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.12) 0%,
    rgba(255, 255, 255, 0.02) 100%
  ) 1;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.25);
}
ルール
  • 暗い背景にのみ使用します。明るい背景でのガラス表現は不自然に見えます。
  • ガラス面に不透明な背景色を使用しないでください。
  • ガラスには、物理的な奥行きと重みを感じさせます。
  • ぼかしの値:標準のガラスには 28px、スポットライト/モーダルのオーバーレイには 40px を使用します。

3. React Three Fiber における GLSL シェーダーの基礎

基本的な考え方

メッシュ = ジオメトリ + マテリアルです。シェーダーはマテリアルをカスタムの GPU プログラムに置き換えます。GPU では次の 2 つの関数が実行されます。

  • 頂点シェーダー:各頂点の位置を決めます。頂点ごとに実行され、gl_Position を出力します。
  • フラグメントシェーダー:各ピクセルの色を決めます。ピクセルごとに実行され、gl_FragColor を出力します。
基本的な R3F シェーダーのセットアップ
import { Canvas } from '@react-three/fiber';
import { useRef, useMemo } from 'react';

const fragmentShader = `
  uniform float u_time;
  varying vec2 vUv;

  void main() {
    vec3 color = mix(vec3(1.0, 0.0, 0.5), vec3(1.0, 1.0, 0.0), vUv.x);
    gl_FragColor = vec4(color, 1.0);
  }
`;

const vertexShader = `
  varying vec2 vUv;

  void main() {
    vUv = uv;
    vec4 modelPosition = modelMatrix * vec4(position, 1.0);
    vec4 viewPosition = viewMatrix * modelPosition;
    gl_Position = projectionMatrix * viewPosition;
  }
`;

const MyMesh = () => {
  const mesh = useRef();
  const uniforms = useMemo(() => ({
    u_time: { value: 0.0 },
  }), []);

  return (
    <mesh ref={mesh}>
      <planeGeometry args={[2, 2, 32, 32]} />
      <shaderMaterial
        fragmentShader={fragmentShader}
        vertexShader={vertexShader}
        uniforms={uniforms}
      />
    </mesh>
  );
};
主要な概念

Uniforms — JavaScript のデータをシェーダーに渡します。読み取り専用で、すべての頂点/ピクセルで同じ値です。useFrame を使って毎フレーム更新します。

useFrame(({ clock }) => {
  mesh.current.material.uniforms.u_time.value = clock.elapsedTime;
});

再レンダリングの不具合を防ぐため、uniforms オブジェクトは必ずメモ化してください。

Varyings — 頂点シェーダーからフラグメントシェーダーにデータを渡します。両方で宣言し、頂点シェーダーで設定して、フラグメントシェーダーで読み取ります。

// vertex
varying vec2 vUv;
void main() {
  vUv = uv;
  // ...
}

// fragment
varying vec2 vUv;
void main() {
  gl_FragColor = vec4(vUv.x, vUv.y, 0.0, 1.0);
}

Attributes — 頂点ごとのデータ(position、uv、カスタムデータ)です。頂点シェーダーでのみ使用できます。varyings を使ってフラグメントシェーダーに渡します。

4. ノイズ関数

有機的に見えるシェーダーのほとんどは、ノイズを使用しています。ノイズをツールとして活用しましょう。

  • パーリンノイズ(Perlin Noise):滑らかで有機的なランダム性を生み出します。地形やブロブの変形に最適です。
  • シンプレックスノイズ(Simplex Noise):パーリンノイズに似ていますが、より高速でアーティファクトも少なくなります。グラデーションや動的テクスチャに最適です。
  • カールノイズ(Curl Noise):パーリンノイズ/シンプレックスノイズから派生したもので、発散のない場を生成します。流体のようなパーティクルの動きに最適です。
  • フラクタルブラウン運動(FBM):異なる周波数/振幅のノイズを重ね合わせます。雲や山のようなディテールを作り出します。

glsl-noise パッケージを使用するか、関数をシェーダー文字列に直接コピーしてください。

「ブロブ」パターン
// vertex shader with Perlin noise displacement
uniform float u_time;
uniform float u_intensity;

void main() {
  float displacement = pnoise(position * 1.5 + u_time * 0.5, vec3(10.0));
  vec3 newPosition = position + normal * displacement * u_intensity;
  // ... standard MVP transform on newPosition
}

5. フラグメントシェーダーのエフェクト

これらのエフェクトを使うと、UIを「ウェブサイト」から「映画のような体験」へと引き上げられます。適用は控えめにし、コンポーネントごとではなく、環境全体に適用してください。

色収差

ビューポートの端でR/Bチャンネルをずらすポストプロセッシングパスです。

Shift amount: 0.002
Application: Viewport edges only, not center
Purpose: Simulates a physical camera lens
メッシュグラデーション背景

ノイズを基にした3~4個の色のブロブがゆっくりと漂う、アニメーション背景です。

Colors:
  - #00F0FF (Cyan)
  - #7000FF (Purple)
  - #000000 (Deep Charcoal)

Movement: Slow, organic drift (think lava lamp, not screensaver)
フィルムグレイン

デジタルのバンディングをなくし、テクスチャを加えるモノクロのノイズオーバーレイです。

Opacity: 2% (0.02)
Type: Monochromatic
Animation: Subtle per-frame variation

6. パーティクルシステム

BufferGeometryを使った基本的なパーティクル
const count = 5000;
const positions = useMemo(() => {
  const pos = new Float32Array(count * 3);
  for (let i = 0; i < count; i++) {
    pos.set([
      (Math.random() - 0.5) * 4,
      (Math.random() - 0.5) * 4,
      (Math.random() - 0.5) * 4,
    ], i * 3);
  }
  return pos;
}, []);

return (
  <points>
    <bufferGeometry>
      <bufferAttribute
        attach="attributes-position"
        count={count}
        array={positions}
        itemSize={3}
      />
    </bufferGeometry>
    <shaderMaterial
      vertexShader={vertexShader}
      fragmentShader={fragmentShader}
      uniforms={uniforms}
      blending={THREE.AdditiveBlending}
      depthWrite={false}
    />
  </points>
);
パーティクルを発光させる
// fragment shader
void main() {
  float strength = distance(gl_PointCoord, vec2(0.5));
  strength = 1.0 - strength;
  strength = pow(strength, 3.0);

  vec3 color = mix(vec3(0.0), vec3(0.34, 0.53, 0.96), strength);
  gl_FragColor = vec4(color, strength);
}
大量のパーティクルに対応するフレームバッファオブジェクト(FBO)

FBOを使うと、シミュレーションパスを介して位置計算をGPUに任せることができ、10万個以上のパーティクルを扱えます。

  1. パーティクルの位置をDataTextureに格納します(パーティクルごとにvec4=RGBA)。
  2. フラグメントシェーダーで位置を読み取り、変換するSimulationMaterialを作成します。
  3. そのマテリアルをオフスクリーンのWebGLRenderTarget(dreiのuseFBO)にレンダリングします。
  4. 結果のテクスチャをレンダーパスのユニフォームとして読み取り、パーティクルの位置決めに使用します。
// Simulation Material class
class SimulationMaterial extends THREE.ShaderMaterial {
  constructor(size) {
    const positionsTexture = new THREE.DataTexture(
      generatePositions(size, size),
      size, size,
      THREE.RGBAFormat, THREE.FloatType
    );
    positionsTexture.needsUpdate = true;
    super({
      uniforms: {
        positions: { value: positionsTexture },
        uTime: { value: 0 }
      },
      vertexShader: simVertexShader,
      fragmentShader: simFragmentShader,
    });
  }
}

// In useFrame: render sim material to FBO, pass FBO.texture to particles
useFrame(({ gl, clock }) => {
  gl.setRenderTarget(renderTarget);
  gl.clear();
  gl.render(simScene, simCamera);
  gl.setRenderTarget(null);
  points.current.material.uniforms.uPositions.value = renderTarget.texture;
  simMaterialRef.current.uniforms.uTime.value = clock.elapsedTime;
});

7. レンダーターゲット

WebGLRenderTargetはシーンをオフスクリーンバッファにレンダリングし、そのピクセル内容をテクスチャとして取得できるようにします。

基本パターン
const renderTarget = useFBO();

useFrame(({ gl, scene, camera }) => {
  gl.setRenderTarget(renderTarget);
  gl.render(scene, camera);
  mesh.current.material.map = renderTarget.texture;
  gl.setRenderTarget(null);
});
用途

透明/ガラスマテリアル — メッシュを非表示にし、シーンをFBOにレンダリングしてから、画面座標を使ってFBOのテクスチャをメッシュにマッピングします。

vec2 uv = gl_FragCoord.xy / winResolution.xy;
vec4 color = texture2D(uTexture, uv);

ポータル(シーン内のシーン) — R3FのcreatePortalを使ってオフスクリーンシーンをレンダリングし、それをFBOにキャプチャして平面にマッピングします。メインカメラのmatrixWorldInverseをコピーすると、視差を加えられます。

目の錯覚 — useFrame内でレンダーパス間のマテリアル/ジオメトリを切り替え、レンズメッシュ越しに別のバージョンを表示します。

シーン遷移 — 2つのシーンをそれぞれ別のFBOにレンダリングし、パーリンノイズと進行度のユニフォームを使ってブレンドします。

float noise = clamp(cnoise(vUv * 2.5) + uProgress * 2.0, 0.0, 1.0);
vec4 color = mix(colorA, colorB, noise);

ポストプロセッシングパイプライン — EffectComposerの代替として、全画面三角形上のカスタムシェーダーマテリアルを使い、レンダーターゲットを連結します。

8. 屈折、分散、光のエフェクト

屈折

GLSL組み込みのrefract()を、eyeVector、worldNormal、IOR比とともに使用します。

vec3 refractVec = refract(eyeVector, worldNormal, 1.0 / 1.31);
vec4 color = texture2D(uTexture, uv + refractVec.xy);
色分散

色チャンネルごとに異なるIOR値を適用し、R、G、Bを分離します。

float R = texture2D(uTexture, uv + refractVecR.xy).r;
float G = texture2D(uTexture, uv + refractVecG.xy).g;
float B = texture2D(uTexture, uv + refractVecB.xy).b;

サンプリングループ(N回反復し、チャンネルごとにずらし量を少しずつ増加させる)で滑らかにします。フーリエ補間を使って色空間をRGBからRYGCBVに拡張すると、より細かく制御できます。

鏡面反射+拡散反射(Blinn-Phong)
vec3 lightVector = normalize(-uLight);
vec3 halfVector = normalize(eyeVector + lightVector);
float kDiffuse = max(0.0, dot(normal, lightVector));
float kSpecular = pow(dot(normal, halfVector) * dot(normal, halfVector), shininess);
return kSpecular + kDiffuse * diffuseness;
フレネル
float fresnel = pow(1.0 - abs(dot(eyeVector, worldNormal)), uFresnelPower);
裏面レンダリングの手法

まずメッシュの裏面(THREE.BackSide)をレンダリングしてFBOにキャプチャし、その後、表面をレンダリングします。裏面の鏡面反射が表面で屈折/分散されるため、説得力のある内部の分散が生まれます。

9. クリエイティブな表現手段としてのポストプロセッシング

ピクセル化の基礎
vec2 normalizedPixelSize = pixelSize / resolution;
vec2 uvPixel = normalizedPixelSize * floor(uv / normalizedPixelSize);
vec4 color = texture2D(inputBuffer, uvPixel);
セル内のローカル座標へのアクセス
vec2 cellUV = fract(uv / normalizedPixelSize); // 0->1 within each cell

これが、各ピクセルセル内のパターンを形作る鍵です。

ポストプロセッシングシェーダーの2つの柱
  1. UV座標の再マッピング/歪み(ピクセル化、ずらし、オフセット)
  2. 各セルを個別に形作る(輝度、SDF、しきい値マトリックスに基づくパターン)
パターン技法

レシート/バーのパターン — luma を使って、各セルの cellUV 内で lineWidth を制御します。

ハーフトーン — 距離場を使って円を描画し、luma に応じて半径を変化させます:

float luma = dot(vec3(0.2126, 0.7152, 0.0722), color.rgb);
float radius = uRadius * (0.1 + luma);
float circle = smoothstep(radius - 0.01, radius + 0.01, dist);

CMYK ハーフトーン — 4 つの回転したグリッド(C:15deg、M:75deg、Y:0deg、K:45deg)を使い、RGB を CMYK に変換して減法混色します:

vec3 outColor = vec3(1.0);
outColor.r *= (1.0 - CYAN_STRENGTH * dotC);
outColor.g *= (1.0 - MAGENTA_STRENGTH * dotM);
outColor.b *= (1.0 - YELLOW_STRENGTH * dotY);
outColor *= (1.0 - BLACK_STRENGTH * dotK);

ASCII エフェクト — ASCII 文字のキャンバステクスチャを作成し、luma を charIndex にマッピングしてサンプリングします。

SDF ベースのパターン — 円には length(p - 0.5) を使い、十字や三角形などにはカスタム SDF を使います。

しきい値マトリックス — カスタムの luma しきい値を持つ 8x8 のマトリックスを定義します。ピクセルの luma をマトリックスの値と比較して、ピクセルをオン/オフにします。これにより、ストライプ、織り目、任意のカスタムパターンを作成できます。

トロンプ・ルイユ効果
  • 千鳥配置の LED パネル — ピクセル化する前に、列ごとに UV 座標をオフセットします。さらにオフセットを加えてセルをサブセルに分割します。1.0 - subCellUV * subCellUV を使って黒い境界線を追加します。
  • かぎ針編み/織物 — ランダムな正弦波オフセットで行ごとに cellUV をオフセットします。各セルに回転した楕円を描きます。エッジにノイズを加え、ストライプパターンや色相シフトを追加します。
  • レゴブロック — ピクセル化に加えて、セルの中心に Blinn-Phong で照らされた円形の突起を追加し、色の量子化と控えめな境界線を適用します。
  • フルーテッドガラス/すりガラス — 歪みには正弦波の微分を使います。法線に変換して Blinn-Phong 照明を適用します。ガウスぼかしとノイズを加えます。
動的/インタラクティブなポストプロセス
  • 段階的なピクセル化解除 — 「レベル」(2 の累乗)を追跡し、progress uniform に基づいて行ごと、ピクセルごとに処理します。
  • ピクセル化されるマウストレイル — ping-pong rendering でマウストレイルを FBO にレンダリングし、そのテクスチャをエフェクトに渡します。ピクセルサイズと歪みを、トレイルの強度とカーソル速度に応じて変化させます。

10. ハーフトーン(上級)

ドットのグリッド
vec2 cellUv = fract(vUv * uGridSize);
float dist = length(cellUv - 0.5);
float circle = smoothstep(radius - 0.01, radius + 0.01, dist);
グリッドの崩し方 — 隣接セルのサンプリング

セルの境界でドットが切れないように、隣接セルを含む 3x3 カーネルをサンプリングします:

for (int dx = -1; dx <= 1; dx++) {
  for (int dy = -1; dy <= 1; dy++) {
    vec2 cellIndex = baseCellIndex + vec2(float(dx), float(dy));
    vec2 cellCenter = (cellIndex + 0.5) * uPixelSize;
    // Calculate distance, check reachability, keep closest
  }
}
グーイーハーフトーン

smoothmin で重なり合う円をブレンドし、隣接するドット間にインクのような表面張力を生み出します。

モアレパターン

回転したグリッドを重ねると干渉が生じます。アーティファクトを最小限に抑えるには、CMYK の各チャンネルに特定の角度オフセットを使います。

アンチエイリアス

fwidth(dist) を使って、解像度に依存しないエッジの柔らかさを実現します:

float edgeWidth = fwidth(dist);
float circle = smoothstep(radius - edgeWidth, radius + edgeWidth, dist);

11. インタラクションパターン

ホバー:マグネット効果

カードやインタラクティブ要素が、わずかに変位しながらカーソルに追従します。

Displacement factor: 0.1x (cursor offset from element center)
Spring back on mouse leave
// React example
const handleMouseMove = (e) => {
  const rect = ref.current.getBoundingClientRect();
  const centerX = rect.left + rect.width / 2;
  const centerY = rect.top + rect.height / 2;
  const offsetX = (e.clientX - centerX) * 0.1;
  const offsetY = (e.clientY - centerY) * 0.1;
  setTransform({ x: offsetX, y: offsetY });
};
アクティブ:レイアウトの変形

コンテナの状態(展開、折りたたみ、移動)が変化すると、内部コンテンツがクロスフェードする間、境界が滑らかにアニメーションします。

  • コンテナの境界にはスプリング物理を使います
  • 内部のコンテンツは 200ms の opacity トランジションでクロスフェードします
  • 急に表示されたり飛び跳ねたりしないようにします。すべての状態変化をアニメーションさせます

12. Framer Motion — レイアウトアニメーション

レイアウトアニメーション

motion.div に layout prop を追加すると、CSS のレイアウトプロパティが変化したときに滑らかにトランジションします:

<motion.div layout style={{ justifySelf: position }} />

値:layout={true}(サイズ+位置)、layout="position"(位置のみ — 押しつぶしを防止)、layout="size"(サイズのみ)。

変形の修正

borderRadius と boxShadow は CSS クラスではなく、インラインスタイルとして設定します。

共有レイアウトアニメーション

layoutId を使って、コンポーネントをインスタンス間でアニメーションさせます:

{selected === item && <motion.div layoutId="underline" />}

コンポーネントを再利用する場合は、<LayoutGroup id="unique"> で囲んで名前空間を設定します。

兄弟要素の LayoutGroup

兄弟関係にある motion コンポーネントを <LayoutGroup> で囲むと、1 つが並べ替えられたときに、ほかの要素も滑らかにアニメーションします。

並べ替え
<Reorder.Group axis="y" values={items} onReorder={setItems}>
  {items.map(item => (
    <Reorder.Item key={item} value={item} style={{ position: 'relative' }}>
      {item}
    </Reorder.Item>
  ))}
</Reorder.Group>

終了アニメーションには AnimatePresence を組み合わせ、コンテンツが押しつぶされるのを防ぐには layout="position" を指定します。

13. Codrops のクリエイティブパターン

Codrops のチュートリアルカタログで紹介されている、重要なクリエイティブ Web パターン:

  • スクロール連動型 WebGL ギャラリー — GSAP ScrollTrigger またはネイティブのスクロールイベントを使用して、R3F シーンをスクロール位置に同期させます。シェーダーベースのリビール、視差による奥行きレイヤー、速度に反応する歪みを適用します。
  • ページトランジション — Barba.js またはバニラの SPA ルーターを GSAP と組み合わせて、クロスフェードトランジションを使用します。ナビゲーションをまたいで Three.js シーンを保持します。シェーダーベースのディゾルブでビュー間を切り替えます。
  • 無限キャンバス — R3F によるチャンクベースのレンダリングで、無限にパンできる画像空間を実現します。LOD とテクスチャの遅延読み込みに対応します。
  • リビールとしての流体シミュレーション — 流体シミュレーションのテクスチャ(ping-pong FBO)を使用し、2 つのシーン間の X 線効果やリビール効果を駆動します。
  • SVG マスク+スクロール — スクロールに合わせて SVG のクリップパスをアニメーションさせ、全画面画像やセクションを表示します。
  • DOM から WebGL へのアップグレードパス — DOM/CSS による視差ギャラリーから始め、シェーダー効果を使った GPU 駆動の滑らかなスクロールを実現するために WebGL へアップグレードします。
  • 物理ベースの効果 — Rapier 物理エンジンを Three.js と組み合わせて、ボクセルの落下、パーティクルの相互作用、物理演算に基づくアニメーションを実現します。
  • レイアウトトランジションのための GSAP Flip — GSAP の Flip プラグインを使ってレスポンシブグリッドのレイアウト変更をアニメーションさせ、即時かつ滑らかな再レイアウトを実現します。
  • TSL+WebGPU — Three.js Shading Language(TSL)を使うと、JavaScript 構文で WebGPU 用のシェーダーを記述できます。また、パーティクルシミュレーションやテキストのディゾルブ効果向けのコンピュートシェーダーも利用できます。

14. CSS 変数

これらをデザイントークンとして使用します。

:root {
  /* Spring physics */
  --spring-stiffness: 300;
  --spring-damping: 30;
  --spring-mass: 1;

  /* Glass */
  --blur-glass: blur(28px);
  --blur-spotlight: blur(40px);
  --surface-fill: rgba(255, 255, 255, 0.05);
  --border-glow: rgba(255, 255, 255, 0.08);

  /* Shader effects */
  --grain-opacity: 0.02;
  --chromatic-shift: 0.002;

  /* Interaction */
  --magnetic-factor: 0.1;
  --overshoot-scale: 1.05;
}

15. ガラス表面におけるタイポグラフィ

  • フォントの太さは最大 500(ミディアム)にします。ガラス表面では太字を使用しないでください。
  • ウェイトではなく、大文字・小文字の使い分け、文字間隔、不透明度で階層を構築します。
  • 等幅テキスト(コード、ラベル)は大文字+11pxにします。
  • ガラス上のテキストには十分なコントラストが必要です。プライマリには rgba(255, 255, 255, 0.9)、セカンダリには rgba(255, 255, 255, 0.5) を使用します。

16. 主要な GLSL 関数

mix(), smoothstep(), step(), fract(), floor(), mod(), clamp(), length(), distance(), dot(), normalize(), refract(), reflect(), pow(), abs(), sin()/cos(), texture2D(), fwidth()

17. 重要なリソース

  • The Book of Shaders(thebookofshaders.com)— 基礎となるテキスト
  • Shadertoy — インスピレーションと GLSL のテクニック
  • glsl-noise パッケージ — すぐに使えるノイズ関数
  • @react-three/drei — useFBO、OrbitControls、PerspectiveCamera、RenderTexture、MeshTransmissionMaterial
  • @react-three/fiber — Canvas、useFrame、createPortal、extend
  • Lamina — 既存のマテリアルに重ねられる合成可能なシェーダーレイヤー
  • Maxime Heckel のブログ(blog.maximeheckel.com)— Web 環境におけるシェーダー制作の主要な参考資料
  • Codrops(tympanus.net/codrops)— シェーダーとインタラクションデザインが出会う場所

18. パフォーマンス

  • 再レンダリングの不具合を避けるため、React で uniforms オブジェクトをメモ化します
  • デバイスのピクセル比を 2 に制限します(Canvas で dpr={[1, 2]})
  • パーティクルには THREE.AdditiveBlending と depthWrite={false} を使用します
  • シェーダー内の for ループは最小限に抑えます(ループ内のテクスチャ参照は高コストです)
  • 重い計算を GPU にオフロードするには FBO を使用します
  • トランジション中に両方のシーンを同時にレンダリングしないよう、ping-pong レンダリングを検討します

19. ワークフロー

クリエイティブなウェブエフェクトの制作方法:

  1. カテゴリを特定する:シェーダーエフェクト、パーティクルシステム、ポストプロセスフィルター、アニメーション、スクロール連動型インタラクションのどれでしょうか?
  2. 適切なツールを選ぶ:カスタムシェーダーには R3F + shaderMaterial、透明表現/パーティクル/トランジションには FBO、UI アニメーションには Framer Motion、スクロール連動型エフェクトには GSAP を使います。
  3. 数式から始める:形状/動き/歪みを表現する関数は何でしょうか?(sin、ノイズ、SDF、距離フィールド)
  4. 土台を構築する:Canvas、メッシュ、uniforms を備えた基本的な shaderMaterial を設定します。
  5. 段階的に実装する:まず基本バージョンを動作させてから、複雑さを加えていきます。
  6. インタラクティブ性を加える:マウス位置、時間、スクロールの進行状況を uniforms に接続します。
  7. 仕上げる:アンチエイリアス(fwidth)、色補正(彩度、色相シフト)、ライティング(Blinn-Phong、Fresnel)、パフォーマンス最適化を加えます。

20. アンチパターン

次のことは避けてください:

  • 主な動きに ease-in-out や、時間ベースのイージングを使う
  • 明るい背景にガラスエフェクトを適用する
  • 単色のドロップシャドウを使う(代わりにアンビエントオクルージョン風の表現を使います)
  • 粒子の粗さを、意識して気づくほど目立たせる(不透明度 3% 超)
  • ビューポート全体に一様に色収差を適用する
  • ガラス面で太字(600 以上)のフォントウェイトを使う
  • オーバーシュートを省く — オーバーシュートのないスプリングは動きが不自然になります

コメント