第4回クリエイティブ・コーディング:React Three Fiberでシェーダーを召喚

開発環境をどこに構えるか?

AD – 読み進める前のひとやすみ

p5.jsの時は OpenProcessing という便利な場所がありますが、本格的なシェーダー開発では「自分の道具」を揃える必要があります。

✅ 初心者におすすめの2ステップ

  1. まずは手軽に:CodeSandbox
    ブラウザだけで動く「Web版OpenProcessing」。React Three Fiber の練習には最適です。
  2. 本気でやるなら:VS Code + Vite
    自分のPCに環境を作る。最初は少し勇気がいるが、一度整えてしまえば、自由自在になります。

「巨人の肩」に乗るための準備

AD – 読み進める前のひとやすみ

⚠️ Shadertoyのコードをそのまま、自分のWebサイトに貼り付けても、エラーになります。

🎨 1. 環境:Three.js (React Three Fiber)という「舞台」を用意する
どれだけ優れた役者(シェーダー)がいても、演じる場所がなければ何も始まらない。ブラウザという画面の中に、描画専用のキャンバス=「舞台」を広げてくれるのがThree.jsの役割です。

📜 2. 翻訳:Shadertoy語を「標準GLSL語」に変換する
Shadertoyのコードは、実はそのサイト専用にアレンジされた「方言」のようなもの。自分のサイトで動かすには、ブラウザが直接理解できる「標準GLSL語」へ書き換える必要があります。

基本の書き換えルール表

役割 Shadertoy Three.js / R3F
魔法の入り口 void mainImage(…) void main()
最終的な色 fragColor gl_FragColor
経過時間 iTime uTime
画面の解像度 iResolution uResolution
画面の座標 fragCoord.xy / iResolution.xy vUv
Three.js(R3F)では vUv という名前で座標を受け取るのが一般的。これは「頂点シェーダー」から送られてくる値で、0.0から1.0の範囲に綺麗に整えられてるから、計算が楽になる!

AI を「専属翻訳家」にして効率アップ!

自力で書き換えるのも勉強になりますが、この翻訳作業こそ AI の得意分野です。

💡 AI へのプロンプト例

「以下の Shadertoy のコードを、React Three Fiber の shaderMaterial で使えるように翻訳してください。 uTimevUv を使う形式にし、初心者にも分かりやすいように日本語でコメントを入れてください。」

(ここに Shadertoy のコードを貼り付ける)

Three.js という舞台を支える「4人のスタッフ」

Three.jsは、ブラウザの中に広大な 3D 空間を作り出すことに特化した「舞台監督」のような存在です。Three.js では、主に 4 つの要素がチームとなって動いています。

🎬 シーン (Scene)

すべての役者が集まる「舞台そのもの」です。

🎥 カメラ (Camera)

観客がどこから舞台を見るかを決める「目」の役割です。

🧍 メッシュ (Mesh)

形(ジオメトリ)と肌(マテリアル)が合体した「役者」です。

🖥️ レンダラー (Renderer)

舞台を計算して、画面に映像として映し出す「監督」です。

3Dといっても、今回は奥行きを使いません。「平らな板(PlaneGeometry)」という役者を一人用意し、その肌である「マテリアル」の中に Shadertoy の魔法を流し込んでいきます。

Three.js でシェーダーの「舞台」を作る

まずは、もっとも標準的な Three.js のコードです。ここでは「何が準備に必要なのか」と「どこに Shadertoy のコードを流し込むのか」だけに注目します。

import * as THREE from 'three';

// -----------------------------------------------------------
// 1. 舞台装置(Renderer)の準備
// -----------------------------------------------------------
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio); // 高精細ディスプレイ対応
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// -----------------------------------------------------------
// 2. 舞台(Scene)とカメラ(Camera)
// -----------------------------------------------------------
const scene = new THREE.Scene();

// 今回は「板」を画面いっぱいに映すだけなので、
// 座標 (-1, 1) の範囲を映す特殊なカメラを使います
const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);

// -----------------------------------------------------------
// 3. 役者(Mesh)= 形(Geometry)+ 魔法の肌(Material)
// -----------------------------------------------------------
// 画面全体を覆う 2x2 の板
const geometry = new THREE.PlaneGeometry(2, 2);

const material = new THREE.ShaderMaterial({
  // 頂点シェーダー:板を画面の隅々まで広げる設定
  vertexShader: `
    void main() {
      gl_Position = vec4(position, 1.0);
    }
  `,

  // 🔥【ここが Shadertoy のコードを貼り付ける場所!】🔥
  fragmentShader: `
    void main() {
      // 翻訳したコードをここに! 
      // 例:オレンジ色で塗りつぶす
      gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0);
    }
  `
});

const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

// -----------------------------------------------------------
// 4. 【重要】リサイズ対策:画面の大きさが変わったら追いかける
// -----------------------------------------------------------
window.addEventListener('resize', () => {
  // ブラウザのサイズを取得
  const width = window.innerWidth;
  const height = window.innerHeight;

  // レンダラー(描画装置)のサイズを更新
  renderer.setSize(width, height);

  // カメラの比率などは今回 Orthographic なので固定でOKですが、
  // 通常の3D(PerspectiveCamera)ならここでもっと複雑な更新をします
});

// -----------------------------------------------------------
// 5. 上映開始(アニメーションループ)
// -----------------------------------------------------------
function animate() {
  // 1秒間に60回、自分自身を呼び出し続ける
  requestAnimationFrame(animate);

  // 描画!
  renderer.render(scene, camera);
}

animate();

仕組みを知るなら Three.js、効率化なら React Three Fiber

AD – 読み進める前のひとやすみ

React Three Fiberは、ReactというWebサイトを効率的に開発するためのライブラリの利点を活かし、Three.jsという『最強の 3D エンジン』を「コンポーネント単位で制御する」ためのツールです。

🚀 なぜ「素の Three.js」から入るのか?

それは、「舞台の仕組み」を根本から理解するためです。

  • 🟢 メリット: カメラやレンダラーがどう動いているか、3Dの基本構造が身につく 。
  • 🔴 デメリット: 画面のリサイズ対応や、アニメーションのループ処理など、本質(クリエイティブ)以外の「準備」にコードの半分以上が割かれてしまう。

RTF で得られる「自由」

一方で React Three Fiber (RTF) は、これら面倒な準備をすべて自動化してくれる。

  • 圧倒的な短さ: 先ほどの Vanilla Three.js のコードが、数行のタグだけで完結する。
  • 🎨 クリエイティブに集中: リサイズ対応などの「裏方仕事」を RTF に任せ、私たちは「どんなシェーダーを書くか」だけに時間を使える。
  • 🧩 コンポーネント化: 作ったシェーダーを「部品」として扱えるので、Blender で作ったモデルと組み合わせるのも簡単です。

CodeSandboxで試してみよう

AD – 読み進める前のひとやすみ

今回は CodeSandbox を使って、最短ルートで React Three Fiber の舞台を作ります。

Step 1:新しいプロジェクトを作る

CodeSandbox を開き、「Create Sandbox」ボタンから 「React」を選択。これだけで、React が動く環境が整う。


Step 2:必要な「道具」を追加する

次に、3D を動かすためのライブラリを 2 つ追加する。画面左側の 「Dependencies」 という項目を探して、以下の 2 つを検索・追加します。

  • 1. three
    すべての基礎となる 3D エンジン本体。
  • 2. @react-three/fiber
    Three.js を React で簡単に扱えるようにする「魔法の橋」。

⚠️ 注意:検索窓に正確に入力して、最新バージョンを選べば OK!
CodeSandbox でライブラリを探すとき、ついつい「three.js」と検索したくなるが、正解は 「three」 です。

🛠️ Step3:コードを上書きします

style.css の中身をすべて上書きしてください。

/* 全要素の余計なマージンをリセット */
* {
  box-sizing: border-box;
}

html,
body,
#root {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden; /* スクロールバーを消す */
  background-color: #000; /* 読み込み前の背景を黒にしておく */
}

/* Canvas要素を画面いっぱいに固定 */
canvas {
  display: block;
  width: 100vw;
  height: 100vh;
}

App.js中身をすべて上書きしてください。CodeSandbox で React Three Fiber (R3F) でシェーダーを利用するための、基本的なテンプレートです。

import React, { useMemo, useRef } from "react";
import { Canvas, useFrame } from "@react-three/fiber";
import * as THREE from "three";
import "./styles.css";

// --- 💡 1. 頂点シェーダー(基本はこのままでOK) ---
const vertexShader = `
  varying vec2 vUv;
  void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.0);
  }
`;

// --- 🔥 2. フラグメントシェーダー(ここを書き換える!) ---
const fragmentShader = `
  precision mediump float;
  uniform float uTime;
  uniform vec2 uResolution;
  varying vec2 vUv;

  void main() {
    // Shadertoyのコードを貼る時は、ここから下を書き換える
    // 例:(vUv * 2.0 - 1.0) で座標の中心を真ん中にする処理など
    vec2 uv = (vUv * 2.0 - 1.0) * vec2(uResolution.x / uResolution.y, 1.0);
    
    vec3 color = vec3(uv.x, uv.y, abs(sin(uTime)));
    gl_FragColor = vec4(color, 1.0);
  }
`;

const ShaderPlane = () => {
  const meshRef = useRef();

 // 📦 1. JSからGLSLへ送る「荷物(Uniforms)」の準備
 // Reactは画面に変化があると「再レンダリング(再計算)」して、中身を新しく作り直す性質があります。
 // もし useMemo を使わずに直接書くと、レンダリングのたびにシェーダー側では「さっきまで使っていた変数が壊された!」とパニックになります。
 // この設定は1回しか作らないから、勝手に作り直して捨てないでね!と、Reactに釘を刺して記憶させるのが useMemo の重要な役割です。
 //空のカッコ「[]」が、最初の一回だけ作るという印
 const uniforms = useMemo(() => ({
  uTime: { value: 0.0 },
  uResolution: { value: new THREE.Vector2() },
}), []); 

  // 毎フレーム、荷物の中身を最新の状態に更新する(自動配線)
  useFrame((state) => {
    const { width, height } = state.size;
    uniforms.uTime.value = state.clock.getElapsedTime();
    uniforms.uResolution.value.set(width, height);
  });

  return (
    <mesh ref={meshRef}>
      <planeGeometry args={[2, 2]} />
      <shaderMaterial
        uniforms={uniforms}
        vertexShader={vertexShader}
        fragmentShader={fragmentShader}
      />
    </mesh>
  );
};

export default function App() {
  return (
    <Canvas>
      <ShaderPlane />
    </Canvas>
  );
}

深堀:「平らな板(PlaneGeometry)」

AD – 読み進める前のひとやすみ

同じ PlaneGeometry でも、その役割によってシェーダーの書き方は異なります。
「画面そのもの」として扱うのか、「空間内のオブジェクト」として扱うのか。
この違いを理解することが、第一歩になると思います。

画面の「歪み」を支配する黄金の1行

移植したコードの中で、ひときわ異彩を放つこの計算式。実はこれ、シェーダーの数学における「画面と対話するための魔法」

vec2 uv = (vUv * 2.0 – 1.0) * vec2(uResolution.x / uResolution.y, 1.0);
  • 1. 「世界の中心」を定義する
  • 2. 「真円」を守り抜く
    ブラウザの画面は、正方形じゃない。そのまま描画すると、円はラグビーボールのように横に潰れてしまう。 そこで uResolution(解像度)を使って縦横比(アスペクト比)を計算し、座標を補正しています。

「背景」vs「看板」コードの書き分けガイド

項目 ① 背景スタイル (Screen Space) ② 看板スタイル (World Space)
頂点シェーダー gl_Position = vec4(position, 1.0); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
UV座標の基準 ブラウザの画面全体(ピクセル) 板(Mesh)そのものの表面
歪み補正 上で説明したuResolution を使った数学的計算が必要 不要(板の形がそのまま描画範囲になる)
「背景スタイル」はモニターという額縁に合わせて絵を描くイメージ。「看板スタイル」はキャンバスという板に絵を描いてから、それを3D空間の好きな場所に置くイメージ。 今回は、「背景スタイル」にしています。

おわりに:0円で広がる無限のクリエイティブ

AD – 読み進める前のひとやすみ

全4回にわたる連載「クリエイティブ・コーディングへの招待状」を最後までお読みいただき、ありがとうございました。

第4回では、最新のライブラリである React Three Fiber (R3F) を導入し、実際にブラウザ上で高度なシェーダーを動かすところまで到達しました。しかし、ここで一つ重要な事実を整理しておきたいと思います。

実は、今回目にした美しい奥行きや複雑な造形は、すべてシェーダー内の「数学的な計算」によって作られた、いわば「究極の2Dアート」です。

R3Fという強力な3Dエンジンを使いながらも、『深堀:「平らな板」』で書いたように、実際には「画面いっぱいに広げた1枚の板(Plane)」にシェーダーを投影していたに過ぎません(空間内のオブジェクトとして扱っていません)。

3D制作において不可欠な「カメラワーク」や「光源の設定」には、まだ一度も触れていないのです。

次のフェーズ:平面から「空間」へ
しかし、これは決して「3Dができていない」ということではありません。むしろ、3D空間を自由に操るための「武器」を手に入れたということです。

この武器があれば、次は「画面全体」ではなく、「3Dモデルの表面」や「広大な3D空間」へと魔法を解き放つフェーズに入ることができます。Blenderで作ったキャラクターに独自の質感を纏わせたり、光り輝く3D空間を構築したりといった冒険が、目の前まで来ています。

かつては専門知識の壁に阻まれていたこうした表現も、今では「AIという最強の家庭教師」がいれば、手軽に(しかも材料費は0円で!)楽しめる時代になりました。

数学が苦手でも、環境構築に自信がなくても、AIを「最高の通訳」として味方につければ、誰でもクリエイターとしての第一歩を踏み出せます。

この連載が、皆さんの創作活動における小さな「招待状」となれば幸いです。


👇AIを家庭教師にしてサクッと「Vite環境構築」を作る方法。

最後まで読んでいただき、ありがとうございました。
おつかれさまでした 🍵

スポンサーリンク