Edited at

2019年度GLSLお役立ちシート


はじめに

shaderを書くことに仕事にして2年が経過しました。前回記事 2017年度GLSLお役立ちシート もだいぶ古くなったのでアップデートしたいと思います。

glslがどんなものかについては、2016年の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のコードとライブプレビューを見ることができます。

Shadertoy カタツムリ

glslは世界を創造する言語と言っても過言ではありません。


glslの世界を見てみよう

まずは、シェーダーアート界の巨匠 Inigo Quilez 氏の作品を巡礼してから、Shader Toyを巡回したいところですが、Shader Toyは非常にGPUに高負荷な作品が多いサイトです。GPUで暖に取るには最適なサイトですが、高確率でブラウザもフリーズさせます。まずは、お手軽なGLSL Sandboxの方を見に行くと良いでしょう。Shader Toyもブラウザがフリーズするくらいですので、特に問題ないのですが、別タブで入力フォームを入力したり、ブラウザゲームをやったり別の作業をしながら、Shader Toyを見に行くのは辞めた方がいいでしょう。かなり高性能なPCでもブラウザがフリーズするときにはフリーズします。


国内のglsl投稿サイト


NEORT(ネオルト)

サイト名NEORTはNEO ARTの略とのことで、デジタルアート作品の投稿サイトです。glsl作品の投稿も多く見られます。


glslfan

@doxasさんが作られたglslライブコーディングサイトです。glslのコーディングをライブで他人数と共有できるのはもちろんのこと、glslのコードのアーカイブもできます。ただし、ちゃんと残すには保存の操作をしないとダメです。


glslプログラミングコード投稿サイト 御三家


GLSL Sandbox

three.js の作者である mr.doob が作った、フラグメントシェーダの記述だけに特化したウェブサイトが GLSL Sandbox です。Sandboxという名の通り、glslのテストのコードを書くにはうってつけのサイトです。基本的に劣化コピーだらけになるので、『parent』ボタンで大本のソースを参照した方がいいでしょう。たまに、元のソースから素晴らしい進化を遂げることがあります。shadertoyからの移植が多いですが、稀に素晴らしい作品に出合えることがあります。そういった素晴らしい作品に出合った場合、ブックマークしておきましょう。glslsandboxは検索性があまりよくないので、あとから探そうとすると大変です。


Shadertoy

シェーダーアート界の巨匠 Inigo Quilez 氏が作ったフラグメントシェーダの記述だけに特化したウェブサイトが Shadertoy です。複数のバッファ(複数のシェーダープログラムを実行)を持てる為、より複雑なシェーダーのプログラムを作ることが出来ます。シェーダー中級以上になってくるとウェブサイトを検索して解説があるサイトを見つけるのが難しくなってきます。そんなときはShadertoyで英単語で検索しましょう。きっと実現している人が見つかるはずです。ソースコードにリファレンスのurlを載せてくださっている方もいるので、ソースコードのコメントも読んでみましょう。iq先生の作品はどれも素晴らしいのですが、基礎的な投稿も多くこの基礎的な投稿は困ったときの解決策になったりするので眺めておくと良いかと思います。iq神の作品一覧


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の方にはもっと投稿されています。

※ jsdo.it終了に伴いアクセスできなくなります。過去投稿をgithubに移行予定みたいです。


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さんの上記サイトにならって図形を実装されていっています。

ここまで、来たら、2016年のGLSL Advent Calendarを見てみましょう。ものすごく充実しています!

おすすめは@doxasさんの、[連載 GLSL 物語] チカラが欲しいか……です。こちらは@doxasさんのウェブサイトのレイマーチングの記事のあとの内容です

さらなる世界を求めるなら、glsl sandboxやShader toyの世界を読み解いてみてください。ここまで来れば、レイマーチングなどの基本の部分はどれも変わりがないので、もうコードが読めるようになっている筈です。きっと色々な発見がありますよ。


glslライブコーディング


glslの注意点


並列にプログラムが実行される


  • 他のプログラミング言語と違って、1つのglslプログラムについて、バーテックスシェーダーであれば、頂点数だけ、フラグメントシェーダーであれば、画素数分、同時にプログラムが実行されるところが大きく異なります。


浮動小数点の精度のバラつき


  • GLSLの規格で、ざっくり浮動小数点の最低の精度が決まっていますが、実際の端末で使われる浮動小数点の精度が環境によってバラバラで特にモバイル環境で動作しない場合が多いです。

  • 特に影響を受けるのがノイズ関数で、ちゃんと意図した通り表示されない場合は大抵これが原因です。glsl sandboxでiPhoneで意図したとおりに見えないのは大抵これが原因です。あとIntel CPUに内臓のGPUもちゃんと表示されないことが多々あります。



  • iq神もダメだと言っている。



btw. 43758.5453 is a really poor choice. it won't work on mobiles and many intel cards due to lack of precision

ところで。 43758.5453は本当に悪い選択です。精度が不足しているため、携帯電話や多くのIntelカードでは機能しません

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演算は使えない。将来のために予約はされている。拡張を使えば使える。

  • 配列も基本的には使わない方がいい


他参考サイト


Klab最強チームメンバーのブログ

Tokyo Demo Fest 2018で上位独占したKlabのメンバーがそれぞれブログにて技術解説を行っているのですが、非常に勉強になります。


その他

オンラインエディター付きチュートリアル

いくつか特徴的な手法が載っていますが、webcamが必要

glslsandboxで作品を作っていく過程が記事になっています。非常に参考になります。