はじめに
glslがどんなものかについては、去年のAdvent Calenderで@doxasさんがまとめていますので、ここでは要点のみまとめています。
詳細について知りたい方は去年の@doxasさんの記事を見ると良いでしょう。
※ 分量が多いので一旦投稿してしまいます。あとから加筆します。間違え等あればご指摘ください。
glslとは
glslをものすごくザックリ言うと、3Dグラフィックの規格であるOpenGLの規格の中で、GPUでポリゴンの影の色や頂点の位置の計算を行うためのshaderと言われる言語です。
WebGLはOpenGL ES 2.0をWebで扱えるようにしたものですので、WebGLで使えるshader言語はglslと言ってもいいでしょう。
glslの扱う基本的なシェーダーの種類は、バーテックスシェーダーとフラグメントシェーダーの2種類あり、バーテックスシェーダーはポリゴンの頂点の計算を行うシェーダーで、フラグメントシェーダーはポリゴンの影の計算(着色)するシェーダーになります。
本来の用途と異なる使い方
glslの最大の特徴は、GPUを直接操作する事が出来ることに尽きます。3Dだけではなく2Dについても高速に描画出来る可能性を秘めています。特に並列での大量の計算に威力を発揮する為、最近では、ディープラーニングの計算deeplearnjs や大量の行列計算 gpu.jsといったグラフィック以外の用途にも用いられています。尚、後述するGLSL sandboxや、Shadertoyで良く出てくるレイトレーシングの一種である『レイマーチング』は、バーテックスシェーダーでは、三角形2枚で板だけ作り、フラグメントシェーダーでその板に3Dを描画することによって3D描画を実現している方法ですので、本来のポリゴンで3Dを描画する方法とは全く異なります。また、レイマーチングで使用されている距離関数を使ったシェイプの描画(2D)も、本来の用途と異なっています。本来、フラグメントシェーダーはポリゴンの影を計算するところであって、シェイプを描画するところじゃない。ですが、こういったshder内でオブジェクトを生み出しシェーダーアートを生成することがglslでの大きな魅力の1つで、その世界が広がっているのが、後述するGLSL sandboxや、Shadertoyの世界です。
まずは、シェーダーアート界の巨匠 Inigo Quilez 氏の作品を見てみましょう
シェーダーアート界の巨匠 Inigo Quilez 氏の作品
カタツムリがどんどん描かれていくyoutubeの動画が流れていると思いますが、このカタツムリ、glslのコードだけで出来ているんです。信じられますか?
実際にShader toyでglslのコードとライブプレビューを見ることができます。
glslは世界を創造する言語と言っても過言ではありません。
glslの世界を見てみよう
まずは、シェーダーアート界の巨匠 Inigo Quilez 氏の作品を巡礼してから、Shader Toyを巡回したいところですが、Shader Toyは非常にGPUに高負荷な作品が多いサイトです。GPUで暖に取るには最適なサイトですが、高確率でブラウザもフリーズさせます。まずは、お手軽なGLSL Sandboxの方を見に行くと良いでしょう。Shader Toyもブラウザがフリーズするくらいですので、特に問題ないのですが、別タブで入力フォームを入力したり、ブラウザゲームをやったり別の作業をしながら、Shader Toyを見に行くのは辞めた方がいいでしょう。かなり高性能なPCでもブラウザがフリーズするときにはフリーズします。
glslプログラミングコード投稿サイト 御三家
GLSL Sandbox
three.js の作者である mr.doob が作った、フラグメントシェーダの記述だけに特化したウェブサイトが GLSL Sandbox です。Sandboxという名の通り、glslのテストのコードを書くにはうってつけのサイトです。基本的に劣化コピーだらけになるので、『parent』ボタンで大本のソースを参照した方がいいでしょう。たまに、元のソースから素晴らしい進化を遂げることがあります。shadertoyからの移植が多いですが、稀に素晴らしい作品に出合えることがあります。そういった素晴らしい作品に出合った場合、ブックマークしておきましょう。glslsandboxは検索性があまりよくないので、あとから探そうとすると大変です。
Shadertoy
シェーダーアート界の巨匠 Inigo Quilez 氏が作ったフラグメントシェーダの記述だけに特化したウェブサイトが Shadertoy です。複数のバッファ(複数のシェーダープログラムを実行)を持てる為、より複雑なシェーダーのプログラムを作ることが出来ます。シェーダー中級以上になってくるとウェブサイトを検索して解説があるサイトを見つけるのが難しくなってきます。そんなときはShadertoyで英単語で検索しましょう。きっと実現している人が見つかるはずです。ソースコードにリファレンスのurlを載せてくださっている方もいるので、ソースコードのコメントも読んでみましょう。
vertexshader.com
GLSL Sandboxや、Shadertoyがフラグメントシェーダーに特化したウェブサイトだとすると、こちらは、バーテックスシェーダーに特化したウェブサイトになります。線や点といった頂点を使ったパーティクルなどが中心です。
Interactive Shader Format
VJソフト用glslフィルターのライブラリサイト
GLSL Sandboxや、Shadertoyからの転載が多いが中にはオリジナルもある。
glslで世界を創ってみよう
上記glslのプログラミングコード投稿サイトの、オンラインエディターで作品を直接いじってみるのが一番手っ取り早いのですが、そもそも、どこをどういじればいいか分からないと思います。
まずは、以下の@doxasさんのqiitaの記事を見て、オンラインエディターで作品を作ってみましょう。
まず2D系
次に、シェーダーアートの教科書的サイトであるThe Book of Shadersを見てみましょう。
こちらも、オンラインエディターを使って、色々試して勉強できるので覚えやすいと思います。
The Book of Shadersは、まだ完成していませんが、実はExamples Galleryのコーナーにこれから教科書に書かれる内容のギャラリーが並んでいます。詳細な説明はありませんが、チェックしておくといいでしょう。
東京工業大学デジタル創作同好会さんのサイトです。こちらでは、glslのフラグメントシェーダーで2Dの星を描く方法が載っています。また、基本となる線の描き方(実は線を描くのは難しい)や、スムーズなmin sminについて書かれているので必見です。
glslで円と正方形の中間の図形を描く方法、図形を繰り返し描く方法、マッピング、極座標変換、疑似パースペクティブ変換と様々なテクニックが一通り紹介されています。必見です。
@cx20さんによるフィルターまとめ。jsdo.itの方にはもっと投稿されています。
3D系
@doxasさんのウェブサイトです。2Dはフラクタルと難しいところから入っているので、qiitaの先の記事を読んだ後、こちらからレイマーチング(3D)の学習を進めていくと捗ると思います。
言わずと知れた、Inigo Quilez 氏のウェブサイトでレイマーチングで使う基本図形の一覧を作ってくださっています。@doxasさんのウェブサイトでレイマーチングを学んだら、色々な図形を試してみましょう。尚、記事中、length8とかlength2といった関数はこの記事には用意されていないので注意してください。自分で用意しろってことです。length8やlength2はこちらに乗っています。lengthが円だとすると、lengthNはNが大きくなればなるほど正方形に近づく図形の距離を測る関数になります。invert(m)やprimitve(p)といった関数もありません。ここは、invertの行列を用意しろという意味と各primitveの関数をここに入れるという意味です。
上記サイトと合わせて@muripo_lifeさんの『GLSLレイマーチング研究_距離関数について勉強してみた』のシリーズはお勧めです。iqさんの上記サイトにならって図形を実装されていっています。
ここまで、来たら、去年のGLSL Advent Calendarを見てみましょう。去年の記事はものすごく充実しています!
おすすめは@doxasさんの、[連載 GLSL 物語] チカラが欲しいか……です。こちらは@doxasさんのウェブサイトのレイマーチングの記事のあとの内容です
さらなる世界を求めるなら、glsl sandboxやShader toyの世界を読み解いてみてください。ここまで来れば、レイマーチングなどの基本の部分はどれも変わりがないので、もうコードが読めるようになっている筈です。きっと色々な発見がありますよ。
glslの注意点
並列にプログラムが実行される
- 他のプログラミング言語と違って、1つのglslプログラムについて、バーテックスシェーダーであれば、頂点数だけ、フラグメントシェーダーであれば、画素数分、同時にプログラムが実行されるところが大きく異なります。
浮動小数点の精度のバラつき
- GLSLの規格で、ざっくり浮動小数点の最低の精度が決まっていますが、実際の端末で使われる浮動小数点の精度が環境によってバラバラで特にモバイル環境で動作しない場合が多いです。
- 特に影響を受けるのがノイズ関数で、ちゃんと意図した通り表示されない場合は大抵これが原因です。glsl sandboxでiPhoneで意図したとおりに見えないのは大抵これが原因です。
glslのプログラミングで良く使われる以下の関数を
float rand(vec2 co){
return fract(sin(dot(co.xy,vec2(12.9898,78.233))) * 43758.5453);
}
↓
highp float rand(vec2 co){
highp float a = 12.9898;
highp float b = 78.233;
highp float c = 43758.5453;
highp float dt= dot(co.xy ,vec2(a,b));
highp float sn= mod(dt,3.14);
return fract(sin(sn) * c);
}
に書き換えてあげることで動作するようになります。
他注意点
- for文のループ回数を動的に出来ない。
- if文はあまり使わない方がいいらしい
- 基本bit演算は使えない。将来のために予約はされている。拡張を使えば使える。
- 配列も基本的には使わない方がいい
他参考サイト
オンラインエディター付きチュートリアル
いくつか特徴的な手法が載っていますが、webcamが必要
glslsandboxで作品を作っていく過程が記事になっています。非常に参考になります。
-
Roy's Blog
このサイトでしかないようなglslの技法が載っています。 -
Andrew Baldwin氏のウェブサイト
恐らく最初にglslでrandam関数を考案した人、最近は、modでリプリケーションしたオブジェクトを別々の動きをつけてパーティクルのように見せる手法を紹介している。 -
Mercury HG SDF
mercuryで使っているディスタンスファンクションのライブラリ