第3回の主役は、シェーダー(GLSL)です。
「Shadertoy」という魔法の鏡
シェーダーの世界は数学と物理の塊、一からすべてを理解しようとすると、入り口で立ち往生してしまいます。
そこで登場するのが、世界中の天才たちが魔法の数式を公開している聖地 Shadertoy 。
Shadertoy とは?:ブラウザ上で直接 GLSL(シェーダーコード)を書き、その結果をリアルタイムで確認できるサイト。 天才たちが作った魔法のコードが、公開されています。
Shadertoy からの「翻訳マニュアル」
Shadertoy のコードはそのままコピペしても動きません。なぜなら、Shadertoy 独自の「方言」で書かれているからです。ここでは、標準的なp5.jsで動くようにするための翻訳ルールを整理。
基本の書き換えルール表
p5.jsでシェーダーを書く時は、ファイルの1行目に必ず
precision highp float; と書きます。
AI を「専属翻訳家」にして効率アップ!
自力で書き換えるのも勉強になりますが、この翻訳作業こそ AI の得意分野です。
💡 AI へのプロンプト例(p5.js版)
「以下の Shadertoy のコードを、p5.js の WEBGL モードで動くように翻訳してください。
JavaScript 内の定数(バッククォート)として vert と frag の変数に格納する形式にし、uTime、uResolution、vTexCoord を使うように調整してください。初心者にも分かりやすいように日本語でコメントを入れてください。」
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ファイル完結テンプレート
/**
* クリエイティブ・コーディング 第2回 実践編
* 「1ファイルで完結!シェーダー召喚テンプレート」
*/
// --- 1. 頂点シェーダー (Vertex Shader) ---
// 画面の座標をそのままフラグメントシェーダーに渡す「おまじない」。
// 最小限の構成。varyingを使わず、キャンバスの設営だけに集中します。
const vert = `
precision highp float;
attribute vec3 aPosition;
void main() {
vec4 positionVec4 = vec4(aPosition, 1.0);
// p5.jsの平面を画面いっぱいに広げる
positionVec4.xy = positionVec4.xy * 2.0 - 1.0;
gl_Position = positionVec4;
}`;
// --- 2. フラグメントシェーダー (Fragment Shader) ---
// ★ここを書き換える!
const frag = `
precision highp float;
uniform vec2 uResolution;
uniform float uTime;
void main() {
// 【ここがポイント】
// gl_FragCoord(ピクセル位置)から -1.0 〜 1.0 の座標を作ります。
// 短い方の辺を基準にするため min() を使ってアスペクト比を補正します。
vec2 uv = (gl_FragCoord.xy * 2.0 - uResolution.xy) / min(uResolution.x, uResolution.y);
vec3 col = 0.5 + 0.5 * cos(uTime + uv.xyx + vec3(0, 2, 4));
gl_FragColor = vec4(col, 1.0);
}`;
// ★ここまで
let myShader;
function setup() {
// WEBGLモード。pixelDensity(1)を入れると計算がズレにくくなります。
createCanvas(windowWidth, windowHeight, WEBGL);
pixelDensity(1);
myShader = createShader(vert, frag);
noStroke();
}
function draw() {
shader(myShader);
// シェーダーに現在の「画面サイズ」と「時間」を教えてあげる
myShader.setUniform('uResolution', [width, height]);
myShader.setUniform('uTime', millis() / 1000.0);
// キャンバスとなる四角形。中心原点なのでこの範囲で画面全体を覆います。
rect(-width / 2, -height / 2, width, height);
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}⚠️貼り付ける時の注意!
シェーダーを書くとき、コードを ` `(バッククォート)で囲みます。これは JavaScript の「テンプレートリテラル」という機能です。
Shadertoy のコードをコピーしてきたとき、貼り付ける場所は大きく分けて 2 箇所あります。
// Shadertoy で mainImage の「外」に書いてある関数はここに貼る
void main() {
// — 2. ここは「メインロジックの置き場」 —
// mainImage の「中身」はここに書き込む
gl_FragColor = …
}
万華鏡エフェクトでシェーダーの真髄に触れる
フラグメントシェーダーの部分をこちらに書き換えてみてください。
kishimisuさんのYoutubeで詳しく解説されているものです。
// --- 2. フラグメントシェーダー (Fragment Shader) ---
const frag = `
precision highp float;
uniform vec2 uResolution;
uniform float uTime;
vec3 palette(float t) {
vec3 a = vec3(0.5, 0.5, 0.5);
vec3 b = vec3(0.5, 0.5, 0.5);
vec3 c = vec3(1.0, 1.0, 1.0);
vec3 d = vec3(0.000, 0.333, 0.667);
return a + b * cos(6.28318 * (c * t + d));
}
void main() {
vec2 uv = (gl_FragCoord.xy * 2.0 - uResolution.xy) / min(uResolution.x, uResolution.y);
vec2 uv0 = uv;
vec3 finalColor = vec3(0.0);
for (int i = 0; i < 4; i++) {
float fi = float(i);
uv = fract(uv * 1.5) - 0.5;
float d = length(uv) * exp(-length(uv0));
vec3 col = palette(length(uv0) + fi * 0.4 + uTime * 0.4);
d = sin(d * 8.0 + uTime) / 8.0;
d = abs(d);
d = pow(0.01 / d, 1.2);
finalColor += col * d;
}
gl_FragColor = vec4(finalColor, 1.0);
}`;平面から「空間」へ。
今の私たちはまだ「1 枚の板」の上に絵を描いてる状態。
もし、この魔法の質感を、Blender で作った 3D キャラクターに纏わせたいとしたら?
あるいは、奥行きのある宇宙空間をカメラで自由自在に飛び回りたいとしたら?
そんな「平面」を超えた「空間」の魔法が必要になったとき
舞台はp5.jsからはなれて、Three.js (React Three Fiber) に移すのがベストだと思います。
第4回では、 React Three Fiber を使って、Shadertoy の芸術的なコードを自分のプロジェクトへと繋ぎ込む『クリエイティブ・コーディング』に挑戦します!
