第3回の主役は、Web 3Dの世界で圧倒的なシェアを誇る Three.js です。
このライブラリは、ブラウザの中に広大な 3D 空間を作り出すことに特化した「舞台監督」のような存在。今回はこの Three.js の力を借りて、シェーダーという魔法を披露するための「舞台(ステージ)」を整えます。
「Shadertoy」という魔法の鏡
シェーダーの世界は数学と物理の塊、一からすべてを理解しようとすると、入り口で立ち往生してしまいます。
そこで登場するのが、世界中の天才たちが魔法の数式を公開している聖地 Shadertoy 。
Shadertoy とは?
ブラウザ上で直接 GLSL(シェーダーコード)を書き、その結果をリアルタイムで確認できるサイト。 天才たちが作った魔法のコードが、公開されています。
巨人の肩」に乗るための準備
⚠️ コピーしたコードをそのまま、自分のWebサイトに貼り付けても、エラーになります。
- 🎨 1. 環境:Three.js という「舞台」を用意する
- どれだけ優れた役者(シェーダー)がいても、演じる場所がなければ何も始まらない。ブラウザという画面の中に、描画専用のキャンバス=「舞台」を広げてくれるのがThree.jsの役割です。
- 📜 2. 翻訳:Shadertoy語を「標準GLSL語」に変換する
- Shadertoyのコードは、実はそのサイト専用にアレンジされた「方言」のようなもの。自分のサイトで動かすには、ブラウザが直接理解できる「標準GLSL語」へ書き換える必要があります。
Three.js という舞台を支える「4人のスタッフ」
まずはブラウザの中に「舞台」を整える必要があります。Three.js では、主に 4 つの要素がチームとなって動いています。
🎬 シーン (Scene)
すべての役者が集まる「舞台そのもの」です。
🎥 カメラ (Camera)
観客がどこから舞台を見るかを決める「目」の役割です。
🧍 メッシュ (Mesh)
形(ジオメトリ)と肌(マテリアル)が合体した「役者」です。
🖥️ レンダラー (Renderer)
舞台を計算して、画面に映像として映し出す「監督」です。
3Dといっても、今回は奥行きを使いません。「平らな板(PlaneGeometry)」という役者を一人用意し、その肌である「マテリアル」の中に Shadertoy の魔法を流し込んでいきます。
GLSLの基礎:JavaScriptとは違う「魔法の国のルール」
シェーダーを書くための専用言語 GLSL (OpenGL Shading Language) の仕組み。
JavaScriptの常識が通用しないこの世界には、独自のルールと「癖」が存在します。
二人の専属魔法使い:頂点とフラグメント
シェーダーの舞台裏では、役割の違う二人の担当者がチームを組んで働いている。
📐 頂点シェーダー (Vertex Shader)
担当:場所と形(Where)
3Dモデルの「点」が画面のどこにあるかを決める数学担当。「画面いっぱいに、この板(Plane)を広げておいて!」と指示する舞台設営の役割。
🎨 フラグメントシェーダー (Fragment Shader)
担当:色(Color)
ピクセルの一つひとつに「お前はこの色になれ!」と命じる色彩担当。Shadertoyで私たちが書くコードの正体はこれ。 私たちが目指す「色の魔法使い」の本体。
初心者が必ずハマる「3つの癖」
GLSLには、JavaScriptに慣れた人ほど驚くような独特の「癖」があります。
-
💧 「.0」を忘れると即エラー(小数の呪い)
JSなら1も1.0も同じだが、GLSLは型に超厳しい。小数を扱う時は必ず1.0と書くこと。整数と小数を混ぜて計算するだけで、魔法はエラーで止まってしまう。 -
🧘 隣のピクセルに相談できない(孤独なピクセル)
「左のピクセルが赤だから自分も……」という相談は一切できない。全ピクセルが同時に、孤独に、自分の色だけを計算している。この「超並列処理」こそが、GPUのパワーの秘密。 -
🕰️ 昨日のことは覚えていない(一期一会)
前のフレームの値を保存して使い回すことはできない。常に「今の時間(iTime)」と「今の場所(座標)」というヒントだけを頼りに、毎フレームゼロから色を計算し直している。
この癖さえ分かってしまえば、あとは数学という名の「レシピ」を記述するだけ。1秒間に60回、数百万回の計算を涼しい顔でこなします。
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
Reactという「UIを宣言的に構築する」ライブラリの利点を活かし、Three.jsという『最強の 3D エンジン』を「コンポーネント単位で制御する」ためのツール。それが React Three Fiber です。
なぜ「素の Three.js」から入るのか?
それは、「舞台の仕組み」を根本から理解するためです。
- 🟢 メリット: カメラやレンダラーがどう動いているか、3Dの基本構造が身につく 。
- 🔴 デメリット: 画面のリサイズ対応や、アニメーションのループ処理など、本質(クリエイティブ)以外の「準備」にコードの半分以上が割かれてしまう。
RTF で得られる「自由」
一方で React Three Fiber (RTF) は、これら面倒な準備をすべて自動化してくれる。
- ⚡ 圧倒的な短さ: 先ほどの Vanilla Three.js のコードが、数行のタグだけで完結する 。
- 🎨 クリエイティブに集中: リサイズ対応などの「裏方仕事」を RTF に任せ、私たちは「どんなシェーダーを書くか」だけに時間を使える。
- 🧩 コンポーネント化: 作ったシェーダーを「部品」として扱えるので、組み合わせるのも簡単。
React Three Fiber:最小限のシェーダー舞台
先ほどの「Vanilla Three.js」のコードを覗き、「React Three Fiber」でいかにスマートに記述できるかを比較してみてください。
import { Canvas } from '@react-three/fiber'
function ShaderPlane() {
return (
<mesh>
{/* 1. 役者の「形」を決める(2x2の板) */}
<planeGeometry args={[2, 2]} />
{/* 2. 役者の「肌(シェーダー)」を決める */}
<shaderMaterial
// 頂点シェーダー:板を画面いっぱいに広げる
vertexShader={`
void main() {
gl_Position = vec4(position, 1.0);
}
`}
// 🔥【ここが Shadertoy のコードを貼り付ける場所!】🔥
fragmentShader={`
void main() {
// ここに翻訳したコードを流し込む
gl_FragColor = vec4(0.0, 0.8, 1.0, 1.0); // 水色の魔法
}
`}
/>
</mesh>
)
}
export default function App() {
return (
// Canvasタグが「Scene」「Camera」「Renderer」「Animation Loop」を
// すべて自動で準備し、リサイズ対応までやってくれます!
<Canvas style={{ width: '100vw', height: '100vh' }}>
<ShaderPlane />
</Canvas>
)
}開発環境をどこに構えるか?
p5.jsの時は OpenProcessing という便利な場所があったが、本格的なシェーダー開発では「自分の道具」を揃える必要があります。
✅ 初心者におすすめの2ステップ
-
まずは手軽に:CodeSandbox
ブラウザだけで動く「Web版OpenProcessing」。React Three Fiber の練習には最適です。 -
本気でやるなら:VS Code + Vite
自分のPCに環境を作る。最初は少し勇気がいるが、一度整えてしまえば、自由自在になります。
第4回では、いよいよ React Three Fiber を使って、Shadertoy の芸術的なコードを自分のプロジェクトへと繋ぎ込む『クリエイティブ・コーディング』に挑戦します!
