【夏休みの自由研究】「シェーダー」の世界(第1回)

これから挑戦するのは、ふつうのプログラミングよりもちょっとだけ難しくて、でも圧倒的にかっこいい「WEBGL(ウェブジーエル)」という特別なモードなんだ。

💡 なにがすごいの?

ふだんのプログラミングと、今回の「WEBGL」の違いを、絵を描く場所にたとえるとこんな感じだよ。

ふつうのモード(2D) 「1人の天才絵描きさん」が、線を一本ずつ、順番に描いていく。
WEBGLモード(今回!) 「1万人の小さなロボット」が、画面のつぶつぶに一斉に飛びついて、同時に色をぬる!

この「1万人の小さなロボット」をあやつる技術は、みんなが知っている有名な3Dゲームや、映画のCG(コンピューターグラフィックス)でも使われているプロの技術なんだ。

スポンサーリンク

JS・p5.js・シェーダー:魔法をあやつる3つの力

💡 魔法使いの道具セット
JavaScript (JS) 世界中で使われている「ロボットへの命令書」。
p5.js お絵描きがとく意な「魔法の道具箱」。
Shader (シェーダー) 1万人のロボットに送る「特別な手紙」。

キミは今、JavaScriptという言葉を使って、p5.jsという道具箱をひらいています。その道具箱の中から、さらにすごいパワーをもった「シェーダー」という手紙を取り出して、1万人のロボットたちに命令を送っているんだ!

ふつうなら難しい設定が必要な「WEBGLモード」も、p5.jsを使えばたった1行で準備OK。さあ、最高に効率(こうりつ)がいい魔法の使い方を学んでいこう!

p5.js Web Editor:絵を描く場所を開こう

まずは、インターネット上でプログラミングができる「p5.js Web Editor」を開いてみて。ここが、キミが魔法をかける場所(キャンバス)だよ。

p5.js Web Editor をひらく

※開いたら、もともと書いてある英語のコードは全部消して準備してね!

コードをコピーして土台を作ろう!

下のコードをそのままコピーして貼り付けてみて。貼り付けたら、左上の「▶️(再生ボタン)」を押すと魔法が発動!
画面が「真っ赤」になったかな!

【魔法の土台(テンプレート)】

const vert = `
attribute vec3 aPosition;
attribute vec2 aTexCoord; 
varying vec2 vTexCoord;  

void main() {
  vTexCoord = aTexCoord;
  vec4 positionVec4 = vec4(aPosition, 1.0);
  positionVec4.xy = positionVec4.xy * 2.0 - 1.0;
  gl_Position = positionVec4;
}
`;

const frag = `
// 📍魔法のインク「フラグメントシェーダー」  
// ⬇️ ここを書きかえて色で模様(もよう)をつくっていくよ
  precision mediump float;
  uniform float u_time;
  uniform vec2 u_resolution; 
  varying vec2 vTexCoord;

  void main() {
    // 👨‍🔬実験:色を変えてみてね〜
    // 赤色
    float r = 1.0; 
    // 緑色
    float g = 0.0;
    // 青色
    float b = 0.0;

    // 透明度
    float a = 1.0;

    //  光の三原色(RGB)と透明度(A)vec4(R, G, B, A)
    gl_FragColor = vec4(r, g, b, a); 
  }
// ⬆️ここまで

`;


// 👇ここから下はJavaScript(p5.js)
let myShader;

function setup() {
  // WEBGLモードでキャンバスを作るよ
  createCanvas(windowWidth, windowHeight, WEBGL);
  myShader = createShader(vert, frag);
}

function draw() {
  // ❶ 「今からこの魔法(シェーダー)を使うよ!」という宣言
  shader(myShader);

  // ❷ 魔法に「今、何秒たったか?」の手紙を送る
  myShader.setUniform("u_time", millis() / 1000.0);

  // ❸ 魔法に「画面の大きさ」を教えてあげる
  myShader.setUniform("u_resolution", [width, height]);

  // ❹ 魔法をぬるための「大きな紙」を広げる
  rect(-width / 2, -height / 2, width, height);
}

// 画面のサイズが変わっても大丈夫なようにするおまじない
function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}

ここが大事だよ〜!!注目(ちゅうもく)してね〜

const frag = `
// 📍魔法のインク「フラグメントシェーダー」
// ⬇️ ここを書きかえて色で模様(もよう)をつくっていくよ
precision mediump float;

//・・・中略・・・

gl_FragColor = vec4(r, g, b, 1.0);
}
// ⬆️ここまで

`;
⚠️ 消さないで!魔法の「かこい」

プログラムの中では、「JavaScript」という大きな世界の中に、「シェーダー」という別の国の言葉を書いてるよ。

const frag = `

  // ここがシェーダーの言葉

`;

この ` (バックティック)は、「ここからここまでがシェーダーの魔法だよ!」とJavaScriptに教えるための、特別な記号で、テンプレートリテラルとよびます。

Shift@
これで打てるよ!
もし消しちゃったら、この2つのボタンを同時に押してね。

💡 ちょこっとメモ: 普通の '" だと、何行にもわたってコードを書くことができません。このバックティックだけが、長い魔法の呪文をまとめて包み込んでくれるよ。

p5.jsでsetupとdraw:「じゅんび」と「じっこう」

まずは、👇JavaScriptの「p5.jsという道具箱」の中で大切な2つの道具を説明するよ!

  • setup(セットアップ):最初の1回だけやる「じゅんび」。色をぬる場所(キャンバス)を作ったり、魔法(シェーダー)を呼び出したりするよ。
  • draw(ドロー):1秒間に60回も繰り返される「じっこう」。パラパラ漫画みたいに、すごいスピードで色を描きかえるんだよ。

シェーダーの魔法がずっと動いて見えるのは、この draw の中で、1万人のロボットたちが休まずに色を塗り続けてくれているからなんだね!

コメント:プログラムの中のメモ「//」のひみつ

コードの中に、ときどき // という記号が出てくるよね?これは「コメント」といって、プログラミングですごく大事な役割(やくわり)があるんだよ。

💡 コンピュータには見えない「メモ」

先頭に // をつけると、コンピュータはその行を「あ、これは人間へのメッセージだな!」と判断して、読み飛ばしてくれるんだ。いわば、コンピュータには見えない「魔法の透明インク」だね。

なぜ書くの?

  • わすれ防止:明日、自分のコードを見たときに「これ何だっけ?」とならないための自分へのメモ。
  • 説明書:他の人がキミのコードを読んだときに、使いかたを教えてあげる優しさ。
  • 実験のしるし:今は動かしたくないコードの先頭に付けて、一時的に「お休み」させる(これを「コメントアウト」と呼ぶよ!)。

👨‍🔬 数字をいじって実験しよう!

コードの中の数字をいじって、何が起きるか観察(かんさつ)しよう。

👨‍🔬実験1:色を変えてみる

float r = 1.0;
float g = 0.0;
float b = 0.0;
の数字を「0.0」や「0.5」「1.0」に変えてみよう。何色になったかな?

👨‍🔬実験2:r g b 全部「0.0」にしてみる

真っ黒になった?

👨‍🔬実験3:透明度を0.0にしてみる

float a = 0.0;
色が消えちゃったかな?

色のひみつ:0.0 と 1.0 は「光のパワー」

🔦 0.0 は「消灯」、1.0 は「全開」!
数字は、ライトの「スイッチのひねり具合」だと思ってね。

0.0
スイッチOFF
(真っ黒)
0.5
半分くらい
(グレー)
1.0
パワー全開!
(真っ白)
🌈 なんで全部混ぜると「白」なの?

絵の具は混ぜると暗くなるけど、光は混ぜれば混ぜるほど明るくなるんだ!
赤(R)・緑(G)・青(B)の3つのライトを全部パワー全開(1.0)にすると、まぶしく光って「真っ白」に見えるんだよ。

今日のまとめ(自由研究シートに書こう!)

1. 魔法のインク「フラグメントシェーダー」
画面にある数百万個の「色のつぶ(ピクセル)」に、一斉に色をぬる担当だよ。キミの命令どおりに一瞬でぬってくれる力持ちなんだ。

2. 光の三原色(RGB)と透明度(A)
パソコンの色は4つの数字 vec4(R, G, B, A) で決まるよ!

  • R(レッド):赤のひかり(0.0 〜 1.0)
  • G(グリーン):緑のひかり(0.0 〜 1.0)
  • B(ブルー):青のひかり(0.0 〜 1.0)
  • A(アルファ)すき通り具合(1.0ははっきり、0.0は透明)

例:vec4(1.0, 1.0, 0.0, 1.0) ➔ 赤と緑をマックスで混ぜると「黄色」になるよ!

とりあえず遊んじゃおう!完成版コード

フラグメントシェーダーの部分をこのコードに変更してみて!

// ⬇️ 
precision mediump float;
uniform float u_time;
uniform vec2 u_resolution;
varying vec2 vTexCoord;

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 = vTexCoord * 2.0 - 1.0;
    uv.x *= u_resolution.x / u_resolution.y;
    vec2 uv0 = uv; 
    vec3 finalColor = vec3(0.0);

    for (float i = 0.0; i < 4.0; i++) {
        uv = fract(uv * 1.5) - 0.5;  
        vec3 col = palette(length(uv0) + i*0.4 + u_time*0.4);
        float d = length(uv) * exp(-length(uv0)); 
        d = sin(d * 8.0 + u_time) / 8.0;
        d = abs(d);
        d = pow(0.01 / d, 1.2); 
        finalColor += col * d;
    }
    gl_FragColor = vec4(finalColor, 1.0);
}
// ⬆️

Kishimisuさんの動画の魔法を、p5.jsというみんなが使いやすい道具にアレンジしたコードだよ!

🎮 数字で「じっけん」してみよう!

コードを貼り付けたら、中にある「数字」を好きなように書きかえてみて!

それだけで、模様が速くなったり、細かくなったり、色が全然ちがう宝石に変わったり……キミだけの魔法が生まれるよ!

NEXT STEP

🧪 魔法の「ナゾ」を解き明かしたいキミへ

数字をさわって遊んでいるうちに、こんな風に思わなかったかな?

「なんでこの数字を変えるとこうなるの?」
「そもそも、この呪文(コード)はどういう意味なんだろう?」

ここから先は、大人でも頭をかかえるくらい、ちょっと難しい「算数と魔法」の世界になります。

「自分だけの魔法を一から作ってみたい!」

そう思ったなら、ぜひ次の第2回をのぞいてみてね。少しずつ仕組みを理解していけば、キミも、本当のデジタル魔法使いになれるかもしれないよ!

👉 第2回【ロボットへの命令と座標のナゾ:丸を描く】を読む

シリーズ一覧

スポンサーリンク