シェーダーはNon-Stop!

これはWebGL Advent Calendar 2015、10日目の記事です。

自前でいろいろやられているネタが続いていますが人の褌で相撲を取るスタイルで気楽にいきます。

というわけで最近颯爽と現れたvertexshaderart.comを勝手に紹介。

開発者はgreggman氏。なんとバーテックスシェーダーを投稿できるWebサービスです! バーテックスシェーダーファンの皆様は心待ちにしていたことでしょう。

いままでにもGLSLを投稿できるところはGLSL SnadboxShadertoyがありました。 どちらも超弩級のシェーダーを手軽に見られて素晴らしいのですが、これらはフラグメントシェーダーのサービスです。

いっそCodePenjsdo.itを使うという方法もありましたが、この手のものはHTMLからCSSJavascriptまで用意しなくてはならず面倒です。

純粋にバーテックスシェーダーだけで手軽に遊ぶことができるのがvertexshaderart.comです。

ではとりあえずvertexshaderart.comを開いてみましょう。

f:id:c5h12:20151209061314j:plain

一番上にsign inとcreate new、それからgithubへのリンクがあって、その下には投稿作品がずらっと並んでいます。 とりあえず目に付いたものをいくつか眺めて、create newを押せば楽しい時間の始まりです!

ちなみにサインインとあってTwitterGitHubなどのアカウントで登録できるようになっていますが、投稿するのに登録が必須なわけではありません。 いくつかあるby:-anon-という表記のものがanonymous、詠み人知らずのシェーダーです。GLSL Snadboxのように匿名で使いたい人でも安心です。

さて編集画面はこんな感じです。

f:id:c5h12:20151209061333j:plain

スクリーンショットを撮るときに画面を小さくしたら画面の真ん中に行ってしまいましたが、普通は右上にhelpがあります。 helpを見れば画面上の説明や使えるパラメーターなどが全てわかりますのでやりたい放題です。

折角なのでUIの説明を簡単にしてみます。左から順に、

  • hide : シェーダー編集エリアを隠す (12/13追記)なんとこの記事が公開されたまさにその日、サイトがアップデートされてコメントをつけられるようになり、このボタンがコードとレンダリング結果の表示レイアウトの変更ボタンになっていました。まだまだ進化するvertexshaderart.com!
  • T : timeを0にリセット
  • ● : レンダリングの停止/再開。GLSL SandboxよりもPCに優しい設計(笑
  • + : デフォルトのシェーダーをリロード。2種類(?)からランダムのようす
  • save : セーブ。Ctrl-S(Cmd-S)のショートカットあり
  • プリミティブ描画モードのプルダウン : ちょうど昨日のemadurandalさんの記事で軽く触れられていたこれの指定
  • ラインの太さ設定のプルダウン : HD-DPIディスプレイでは見え方が違うらしい
  • 頂点数のスライダーとフィールド : 今画面に出ている頂点の数
  • 背景色のカラーピッカー
  • BGMとして使いたいsoundcloudのURL : embedded/streamのパーミッションがある曲かプレイリストを指定すればいいらしい。空欄にするとBGM無し
  • BGM再生ボタン
  • BGM固定ボタン : 違うシェーダーへ移動しても同じBGMを流し続けるボタン。投稿されたシェーダーの閲覧時に有効。
  • ギャラリーへ戻る
  • ヘルプ

肝心の入力パラメーターは

attribute float vertexId; // 頂点番号

uniform float vertexCount; // 指定されている頂点数
uniform vec2 resolution; // 画面解像度
uniform vec2 mouse; // マウスの位置(-1, 1)
uniform sampler2D touch; // タッチのヒストリーを記録した32x240のテクスチャ。(R,G,B,A)=(x,y,pressure,time)で0行目がマウスか指1,1行目が指2...と格納されている
uniform float time; // 経過時間
uniform sampler2D sound; // サウンドのFFTをaに記録したNx240のテクスチャ
uniform sampler2D floatSound; // サウンドのFFTをaに記録したNx240のテクスチャfloatバージョン
uniform vec2 soundRes; // サウンド解像度。(n, 240)。nはテクスチャの解像度かFFTのビンの数
uniform vec4 background; // 背景色

そして出力は

// GLSLの出力
vec4 gl_Position;
float gl_PointSize;

// varying変数
varying vec4 v_color; // 色

となっています。 通常gl_Positionとgl_PointSizeはバーテックスシェーダーから出力するものなので、v_colorだけがオリジナルな出力になります。 とはいえ名前の通りその頂点の色なので特に変わったこともありません。

さて、この条件でなにか作るにはvertexIdから何かしら算出する以外に方法はありません。 立方体などを描きたかったらどうにかして何個目のオブジェクトの何番目の頂点になるかを求める、という感じです。

だいたい既存のものを参考にすればいいのですが結構大胆な書き方をしていたりするので、ランダムに点を並べるだけの素朴な感じのやつを作ってみました

あと6日のcx02さんが触れていたリサージュ曲線に沿って立方体を飛ばすなんかdebrisっぽいやつがタイミングよく匿名で投稿されています。なぜかとてもいいタイミングですね! 参考:debris

白々しいこと言ってますが日本語コメントをつけてgistに置いてみましたのでもし参考になれば幸いです。

コピペ大歓迎なので透視変換とか書くの面倒という人もぜひ超かっこいいシェーダーを投稿してください。

最後に定番テクニック的なものを。

CullFaceは効いていないので面の向きはそれほど重要ではありません。 しかしDepthTestが効いているので、2Dのエフェクトとして重ねて描画するには少しずつ手前にずらさないといけないので注意です。

// 三角形をいくつか描く。TRIANGLESで頂点数12。
void main() {
  vec3 p;
  
  float triangleId = floor(vertexId / 3.0);
  float triangleVertexId = mod(vertexId, 3.0);
  
  float angle = radians(60.0) * (triangleVertexId * 2.0 + triangleId * 0.6667);
  p = vec3(sin(angle), cos(angle), -0.01 * triangleId);
  
  p.x *= resolution.y / resolution.x;
  
  gl_Position = vec4(p * 0.8, 1);
  gl_PointSize = 10.0;
  
  v_color = vec4(0.5, 0.5, 0.5, 0.5);
}

またBlendFuncは GL_ONE, GL_ONE_MINUS_SRC_ALPHAに設定されています。 そのためいわゆるアルファブレンディングをするには乗算済みにしておく必要があります。 一方でアルファを0にして色を入れれば加算として使うことができるのでパーティクルなどに最適です。

f:id:c5h12:20151209061403j:plain

それからsoundのテクスチャは右側にほとんど値が入ってこないので、左のほうだけ使うといいよとデフォルトで入っているシェーダーに書いてあります。

Shadertoyで見かけるガチ勢の名前もチラホラ見えますが、まだ投稿数もそれほど多くないのでチャンスです!

Com'on Ready? Let's GO!