GLSL で暖を取るための準備をしよう！ GLSL お役立ちマニュアル

## はじめに

本稿は、WebGL で GLSL を使って暖を取るために個人的にまとめたもので、もしかしたら仕様と異なるような表記や勘違いがあるかもしれません。そういうの見つけたときはぜひ教えてください。🔥🔥🔥

GLSL やシェーダに気軽に触れてみてほしい、楽しく取り組んでみてほしいという観点からやや崩れた文体で、イメージのしやすさ優先で書いてます。そういうの苦手な人は公式の仕様を見ましょうね。


## GLSL について知る

GLSL がなんであるかは、たぶんこの記事を読んでいる方には説明不要かと思いますが、あえて簡単に説明します。

まず、PC などのコンピュータを用いて二次元、あるいは三次元のグラフィックスを描画するための世界標準の規格として OpenGL という API が存在します。その名のとおり、オープンな規格として策定されている OpenGL は、OpenCL や Vulkan などと同じく [Khronos Group](https://jp.khronos.org/) によって管理されており、PC だけでなくモバイル端末やゲーム機など、マルチプラットフォームで利用されているのが特徴です。📱

OpenGL はそれなりに歴史も古く、また非営利団体によってオープン規格として管理されているので、様々なところでグラフィックス処理を中心に広く利用されています。

そんな OpenGL で利用される *シェーダを記述するための言語* が、GLSL です。

OpenGL がそうであるように、GLSL も複数のバージョンが存在し、それぞれに若干ルールが異なっています。また当然ながら、古いものと新しいものを比較すると、機能面にも差がありますし、いくらオープンな API とは言っても、バージョンに関する部分はしっかりと意識して、ルールに沿った記述を行ってやる必要があります。


## GLSL の役割

3DCG を描画する場合など、高速にハイレベルなグラフィックスを描画しなければならないケースでは、GPU と呼ばれるグラフィックス描画に特化したハードウェアを活用します。GPU の性能が高くても、その性能を十分に引き出すことができなければ、高速に美しい CG を描くことはできません。

逆に言えば、GPU を思うがままに操ることができればこそ、美しいグラフィックスを高速に描くことが可能になります。一般に、GPU 内部で行われる様々な処理を、詳細かつ具体的に制御するために *シェーダ* が用いられます。

誤解を恐れずにわかりやすさ重視で書きますが、GLSL とはいわば、GPU にどのような処理をしてもらいたいのかをプログラマが任意に制御するための言語なんですね。📔

C 言語や JavaScript などは、あくまでも CPU 上で動作します。しかし GLSL は、GPU 上で高速に動作するプログラム（シェーダ）を記述することができるというわけです。


## GLSL とシェーダ

GLSL は、先ほども書いたように OpenGL に付随して動く言語です。ですから、OpenGL の機能やバージョン、GLSL 自身のバージョンなどによってどこまでできるのかが変わってきます。

ここでは、最も簡単に GLSL に触れることが可能な WebGL をプラットフォームとして考えてみましょう。

WebGL の場合は、GLSL のバージョンは *GLSL ES 1.0* というのを使っています。このバージョンの GLSL では、ふたつのシェーダを記述することができるようになっています。それが、*頂点シェーダ* と *フラグメントシェーダ* です。

### 頂点シェーダ

頂点シェーダは、その名前からも想像できるかと思いますが、3DCG などにおける頂点を制御するためのものです。

頂点を移動させたり、あるいは頂点が持つ情報を元になにかしらの変換処理を行なったり、というように、頂点の制御を主眼にしたシェーダです。WebGL のデモで、パーティクルが大量に飛び交っているようなものを見たことがありませんか？ あれは、大抵の場合は頂点シェーダが頑張って大量の頂点の動きを制御してくれているんですね。

![001.jpg](https://qiita-image-store.s3.amazonaws.com/0/39638/b18e0401-fb3b-5443-dee5-feadfc32e4f8.jpeg)


### フラグメントシェーダ

さてもうひとつのシェーダであるフラグメントシェーダですが、こちらは頂点という単位ではなく、スクリーン上の *各ピクセル* を舞台に活躍します。

どのような 3DCG であっても、それは最終的には小さなドットの集合体であるスクリーンに映し出されます。つまり、突き詰めていけば CG とは、あるピクセルに何色を出力するのか、ということを、途方もないほど大量にこなして描画していくわけです。

フラグメントシェーダはまさに、そんなピクセルのひとつひとつに、何色を塗るのかを決めるために使います。ですから一般に、頂点シェーダよりもフラグメントシェーダのほうがボトルネックになりやすい傾向があるといえるでしょう。🍷


## GLSL の実行環境

さて、GLSL についてなんとなく理解できてきたでしょうか。

ここまでを読んでシェーダや GLSL にちょっとばかし興味が出てきたとしても、いったいどのようにして GLSL と向き合っていけばいいのでしょうか。また、その使い方を勉強するにはどんな準備が必要なのでしょう。

何度も書いているように、GLSL は OpenGL 系の API とセットで利用するものなので、必然的に、OpenGL やその系列 API が利用できるプラットフォームから準備をしてやらなくてはなりません。C++ などを利用して OpenGL 実装を組んだり、モバイル向けの OpenGL ES を使うために iOS アプリの実装を組んだりするのもいいですが、最も簡単に環境構築ができるのは WebGL でしょう。🌏

WebGL はブラウザ上で OpenGL ES 相当の API を、JavaScript から制御することができる比較的新しい JavaScript の API です。WebGL と GLSL の組み合わせなら、テキストエディタと、WebGL が実行できるウェブブラウザさえあれば、いつでも GLSL に挑戦することができ、とても手軽です。ここからは、WebGL における GLSL を前提に話を進めていきましょう。


## GLSL を実行する

WebGL が気軽にトライしやすいプラットフォームであると言っても、やはり JavaScript を使って OpenGL 系の API を初期化する処理などはかなり複雑かつ冗長です。ここをゼロから構築していくのは、普段 JavaScript をバリバリ記述している人でも簡単ではないでしょう。

WebGL 界には、[three.js](https://threejs.org/) というとても優れた WebGL 用のライブラリが存在しますが、それでも、GLSL を記述していくためには若干の準備が要ります。

そこで、さらに簡単に、とにかく余分な WebGL 実装などは省略し、GLSL の記述のみに特化したウェブサイトが既にいくつか誕生しています。

ここではそのうちのいくつか代表的なところを紹介しましょう。

### GLSL Sandbox

先述の three.js の作者である mr.doob が作った、フラグメントシェーダの記述だけに特化したウェブサイトが GLSL Sandbox です。

[GLSL Sandbox Gallery](http://glslsandbox.com/)

3DCG や GLSL 界隈のなかでは比較的敷居が低く、また他の誰かが書いたシェーダのコードをフォークする機能もある老舗です。

GLSL はウェブサイト上でリアルタイムに編集でき、その変化も、随時描画結果にリアルタイムに反映されます。逆に言うと、描画負荷がどれほど高かろうが、一時的にでもそれをストップするような機能はありませんので、GPU が常に稼働し続ける状態になります。

GPU は CPU などと同様に負荷が高ければ発熱しますし、同時に大量の電力を消費しますので、負荷の高い状態を長時間維持するのはあまりハードウェア的にもよくありませんね。GLSL Sandbox では実行そのものを止めることはできませんが、描画負荷を下げる工夫をすることはできます。

シェーダエディタの画面の、左上にあるドロップダウンリストから、大きめの数値を選択してやりましょう。そうすることで、フラグメントシェーダが実行されるピクセルの数を減らすことができるため、負荷が驚くほど低く保てるようになります。

どうしても GLSL で暖を取らないと寒くて死んじゃう！ というときとかは、逆にドロップダウンリストから、0.5 とか小さめの数値を選んでみると *一瞬で暖まれる* のでおすすめです。🔥🔥🔥

![002.jpg](https://qiita-image-store.s3.amazonaws.com/0/39638/1f7a2c6e-e9bb-d8f1-17da-a3415fff41c0.jpeg)


### vertexshaderart.com

先述の GLSL Sandbox はフラグメントシェーダに特化したオンラインの GLSL エディタでしたが、こちらは逆に、頂点シェーダに特化した作りになっているオンライン GLSL エディタです。

[vertexshaderart\.com](https://www.vertexshaderart.com/)

個人的な印象ですが、フラグメントシェーダだけで描画を行うのとは違い、頂点シェーダを駆使するには 3DCG 全般にある程度習熟している必要があります。ですから、気軽に GLSL を書き始められるという点では間違いないのですが、あまり初心者向けというわけではありませんね。

GLSL Sandbox と同様に、他の人が書いたシェーダのコードがたくさん掲載されているので、あくまでもコードリーディング的に眺めてみるというのは面白いかもしれません。

特徴的な機能として、描画する頂点のプリミティブタイプを三角形ポリゴンからラインに変更したり、あるいは頂点の描かれる総個数を変更したりできる機能があり、玄人にはたまらないオモシロツールとなっています。

頂点の個数を MAX にすると、寒さ対策にもなるのでいいですね！

![003.jpg](https://qiita-image-store.s3.amazonaws.com/0/39638/2d97fee3-8629-1b0d-0d01-ba996712d9cb.jpeg)

### Shdr Editor

こちらはフラグメントシェーダと頂点シェーダを同時に編集することができる、バランス良く仕上げられたオンライン GLSL エディタです。

[Shdr Editor](http://shdr.bkcore.com/)

プリセットでいくつかの 3D モデルが用意されているので、これらを自由自在に頂点シェーダで変形させてみたり、あるいは、お好きなようにライトを当ててみたりと、なかなか活用できる場面が多いエディタです。

非常に洗練された作りになっているので、正統派で GLSL を書いていきたいという人には、とてもよいツールだと思います。

ちなみに、このエディタの作者の方は、WebGL 製のレーシングゲーム [HexGL](http://ffos.hexgl.bkcore.com/) などでおなじみの WebGL 界の貴公子、Thibaut Despoulain さんです。

![004.jpg](https://qiita-image-store.s3.amazonaws.com/0/39638/a3d04c74-1af8-49ae-8bf7-f3ea08131210.jpeg)


### pixelshaders.com

簡単なチュートリアルも付属するオンラインエディタで、GLSL Sandbox のようにフラグメントシェーダを記述することができます。

[Pixel Shaders: An Interactive Introduction to Graphics Programming](http://pixelshaders.com/)

グラデーションやノイズといった、3DCG 表現には欠かせないタイプの概念を紹介しながら、コードも同時に掲載されていて見やすいですね。

特にこれといった特徴のあるエディタというわけではないのですが、解説付きなので基本的なところをまず押さえるには向いているかもしれません。

![005.jpg](https://qiita-image-store.s3.amazonaws.com/0/39638/6e80a5f7-90ce-3814-850d-390ad8056867.jpeg)

### Shadertoy

シェーダを記述することを極めた仙人たちが棲んでいる聖地、Shadertoy――

GLSL Sandbox と同様にフラグメントシェーダを利用することが前提ですが、まあなんていうか、初心者はハッキリ言ってお断りな空気感が漂う **恐ろしいところ** です。GLSL を使って暖を取りたいときには、真っ先に候補に上がります。💪💪💪💪💪

[Shadertoy BETA](https://www.shadertoy.com/)

Shadertoy を作ったのは、CG 界隈ではかなり有名なシェーダ界の神様みたいな人です。

必然、このサイトにあるシェーダはどれも一級品ばかりなので *GPU の発熱量も半端ではない* のが特徴です。

MacBook Pro などの Retina ディスプレイで、解像度の設定をドットバイドットにしているならこのサイトのデモを **絶対にフルスクリーン実行しない** ようにしたほうがいいと思います。グラフィックスドライバごとあなたのおブラウザ様がお亡くなりになる可能性が極めて高いです。というか上のリンク踏んでトップページに行っただけで死ぬかもしれません（経験者談）。

このサイトだけは、他のサイトとは異なり、ラップトップなどでお気楽に閲覧することはおすすめできません。神々の記述した奇跡のシェーダを拝見させていただく上では、見る側にもハイエンド GPU 装備という神界に訪れるための資格が必要です。

日本に住まう神のひとり、よっしんさんの作品（の移植）も Shadertoy にあります。GLSL を使って音まで作っちゃうぞ！

![006.jpg](https://qiita-image-store.s3.amazonaws.com/0/39638/92891e39-5a7a-89ee-489d-7c9a354e1850.jpeg)

リンク： [2nd stage BOSS by 0x4015](https://www.shadertoy.com/view/MsGGDK)


## GLSL を学ぶ

さて、いろいろな GLSL を実行できるウェブサイトが存在することはわかりましたが、しかし実際になにがどうしてこんな映像が生まれるのか、その仕組みを理解するのはなかなか大変そうですね。🏫

GLSL は割りとコンパクトというか、他の一般的なプログラミング言語と比較したらできることは非常に少ないです。これは、GPU という特殊なハードウェア上で実行されるシェーダのための言語である、ということが最も大きな要因だと言えるでしょう。

しかしコンパクトとは言っても、やはり最初はその概要を掴むのが難しいのがシェーダでもあります。そんなシェーダや GLSL について勉強するために、有用になりそうなサイトも紹介しておきましょう。


### The Book of Shaders

有志による日本語訳もある、シェーダの教科書的コンテンツ。

更新が止まって久しいのがちょっと残念ですが、既にアップロードされている序盤のチュートリアルだけでも読む価値が十分にあります。

特に、ノイズに関する項は非常に素晴らしいので、中級者以上を目指すならぜひ目を通しておきましょう。

[The Book of Shaders](https://thebookofshaders.com/)


### Geeks3D の Shader Library

シェーダの様々な実装について書かれている有名なサイトの当該記事一覧。

GLSL 単体に絞った内容ばかりというわけでもないのですが、非常に有用なテクニックがたくさん紹介されています。

[Shader Library - Geeks3D](http://www.geeks3d.com/shader-library/)


### glfx.js

glfx.js は、GLSL を使って二次元的なエフェクト処理を行うためのライブラリなのですが、Github で該当する GLSL コードが公開されていることなどもあって、勉強には非常にいいプロダクトになっています。

エフェクトの効果を見ているだけでも楽しめると思います。🌠

[glfx\.js](http://evanw.github.io/glfx.js/)


### Shaderific

GLSL のビルトイン関数について書かれたドキュメントです。

全編英語ですが、それほど難解でもないと思いますので、GLSL のビルトイン関数について調べたいときにはぜひ活用しましょう。

[Shaderific - GLSL Functions](http://www.shaderific.com/glsl-functions/)


### Khronos 公式 のドキュメント群

OpenGL を管理している Khronos の公式ドキュメントです。

当たり前ですが、仕様をしっかりと調べたいケースというのは往々にしてあるものです。最も信用のおける、公式ドキュメントを押さえておくことは当然ですね。

私は WebGL チートシートを年に 812 万回くらいは見てますね。（不安になってつい見ちゃうｗ）

* [webgl\-reference\-card\-1\_0\.pdf](https://www.khronos.org/files/webgl/webgl-reference-card-1_0.pdf)
* [opengles3\-quick\-reference\-card\.pdf](https://www.khronos.org/files/opengles3-quick-reference-card.pdf)


## GLSL の代表的な構文

様々な勉強用のサイトを見ていくにしても、最低限の GLSL の知識がないと、読むことさえままならないということもあるかもしれません。

ここからは本当に初歩の初歩、基本的な構文などについて簡単にですがまとめておきます。

なにごとも、暖を取るための準備というのは大変ですなあ。🍢

### 基本は C 言語ライク

GLSL は基本的に C 言語に似た構文になっています。

たとえば、GLSL のなかではエントリポイントとなる `main` 関数を必ず記述してやる必要があったり、関数の呼び出し前に定義が終わっている必要があったり、なにかと古風な感じです。

コメントなどの記述についても、基本は C や JavaScript と同じです。

そして、頂点シェーダとフラグメントシェーダで若干ですが使えるビルトイン変数等に違いがあります。ここでは例として、最も単純な頂点シェーダの例を見てみましょう。

```
attribute vec3 position;

void main(){
    gl_Position = vec4(position, 1.0);
}
```

先ほど書いたとおりで、GLSL ではシェーダ内に必ず `main` 関数を用意してやる必要があります。

これが、頂点シェーダであれば *頂点単位* で、フラグメントシェーダであれば *ピクセル単位* で実行される処理そのものということになります。

### 頂点シェーダとフラグメントシェーダ

頂点シェーダは、描くべき頂点の個数分だけ実行されます。つまり、大量の頂点を同時に描こうとすれば、それだけ頂点シェーダが実行される回数も増えるわけですね。

一方のフラグメントシェーダは、こちらはピクセル単位で実行されるシェーダです。ですから、スクリーンが非常に大きかったりすると、とても負荷の高い状態に陥りやすくなります。

先ほど、ドットバイドットの Retina ディスプレイでフルスクリーンは危険ですよみたいに書きましたが、これはフラグメントシェーダがスクリーンの大きさに依存して負荷を増減させるからだったんですね。当然、小さな描画領域であれば、処理すべきピクセルの絶対数が少なくなるわけですから、その分、負荷も抑えることができます。

### 特殊なデータ型たち

GLSL では、C 言語には存在しない特殊なデータ型があります。

代表的なところでは、ベクトルを扱うための `vec` 系の変数の型が挙げられるでしょう。3DCG にはベクトルは欠かせないものなので、普通に型が用意されているんですね。

その他にも、行列を扱うための `mat` 系の型や、画素データ（テクスチャ）を扱うための `sampler` 系の型などがあります。

### 型の厳密性

GLSL はデータ型の扱いが非常に厳密です。JavaScript 使いには信じられないくらい、厳密です。

まあこれも GLSL で暖まるためですから仕方ありませんね。☕

たとえば、整数型を表す `int` で宣言した変数に対して、小数点つきの数値を代入しようとすると、それだけで GLSL のコンパイルが通らなくなります。仮に通ったとしたら、ドライバのバグです。

```
int i = 1.0; // error!
```


### ビルトインの変数たち

GLSL には多くのビルトイン関数や、ビルトイン変数があります。

両者のうち、ビルトインの「変数」の方には、プレフィックスがついているのでわかりやすいでしょう。代表的なものには次のようなものがあります。

* `gl_Position`: 頂点シェーダで、頂点の座標を代入するための変数
* `gl_PointSize`: 頂点シェーダで描く点の大きさを指定するのに使う
* `gl_FragColor`: フラグメントシェーダで色を出力するための変数
* `gl_FragCoord`: フラグメントシェーダで処理ピクセルの座標を読み取るのに使う

上記のうち、特に `gl_Position` は、頂点シェーダで出力が必須になっています。意味から考えてみれば、当然と言えば当然ですよね。

頂点を描こうとしているのに、頂点がどこに存在するのかをシェーダから出力しなかったら、スクリーン上のどこに頂点を描けばいいのかわからなくなってしまいますものね。

また、`gl_FragColor` に対してフラグメントシェーダから RGBA に相当する値を出力すると、それがそのまま画面に塗られる色になります。


### スウィズル演算子

GLSL では、JavaScript でプロパティを参照するときのように、ピリオドを使ってベクトルの各要素にアクセスすることができます。

これをスウィズル演算子というのですが、これについては用法を見たほうが早いでしょう。

```
vec3 hoge = vec3(0.0, 1.0, 2.0);

float fuga = hoge.x; // fuga == 0.0
```

こんなふうに、`x` とか `y` とかを使って、ベクトルの要素にアクセスできるんですね。

このスウィズル演算子には、`xyzw` や `rgba` などが用意されていますが、これはあくまでも *何番目の要素にアクセスするか* を指定する意味しか持っていないので、いずれのスウィズル演算子を使っても意味は同じになります。

また、必ずしも順番通りに並んでいる必要は無く、以下のような記述も構文エラーにはなりません。

```
vec3 hoge = vec3(0.5, 1.0, 2.0);

vec4 fuga = hoge.xxzy; // fuga == (0.5, 0.5, 2.0, 1.0)
```

### 個性的な修飾子たち

GLSL には、変数に特殊な意味を持たせる修飾子というのが結構たくさんあります。

なかでも、特に重要なものには以下のようなものがあります。

* `attribute`: 頂点が持つ属性を参照するための変数に付く
* `uniform`: アプリケーションから値を受け取るための変数に付く
* `varying`: 頂点シェーダからフラグメントシェーダへ値を渡す参照変数

これらの詳細な意味はここでは触れませんが、それぞれの持つ意味をしっかりと理解した上で使うことが求められます。

ここまでに紹介してきたフラグメントシェーダベースのオンライン GLSL エディタの場合は、主に `uniform` 変数の使い方がキモです。なぜなら、実行されている JavaScript からリアルタイムに送られてくる「時間の経過」や「マウスカーソルの位置」といった情報は、常に `uniform` 変数を介して送られてくるからですね。


### その他のトピック

GLSL ではその他にも、`const` 修飾子を用いた定数の宣言、`#define` マクロの記述、精度修飾子を用いた数値の精度指定、配列の利用など、いくつかのトピックがありますが、そのへんはまあ、知らなくてもどうにかなります。とりあえず手っ取り早く始めてみたいという段階では、それほど重要ではないでしょう。

また、GLSL の制御構文には、一般的な `if` 文、`for` 文なども用意されています。書式は基本的に JavaScript などと同じです。

ただし、GLSL 全般に言えることですが、GPU 上で動作するシェーダの特性と言いますか、とにかく実行環境から受ける影響が非常に大きいという特徴があります。マシン A では通ったのにマシン B ではコンパイルできない、なんてことは日常茶飯事です。よしんばコンパイルエラーにならなくても、全く外見が変わってしまったなんてことも、起こりえます。👀

これは GLSL に特有の問題というよりは、3DCG 全般に言えることです。実際に動いているコードをよく観察しながら、創意工夫することが肝要です。

全ては GLSL で暖を取るために必要な儀式みたいなもんで、フロントエンドで言うならブラウザごとの挙動の違いや、モバイルブラウザでの怪しい動きをどうにかするというのと、根本的には同じです。積まれている GPU や、それを動かしているドライバが違ってしまうと、どうしてもこういうところは避けて通れないものになってしまいます。諦めずに、トライしていきましょう。


## まとめ

さて、GPU をぶん回して GLSL で暖を取る準備はもう万全ですね！？

このアドベントカレンダーでは、ここでは触れられなかったような、GLSL に関する多くの有用な知識が得られると思います。それらをときに駆使し、ときに活用しながら、少しずつで構いませんので GLSL に慣れ親しんでいきましょう。

どうしても、最初はシェーダってのはとても難しく感じるものです。私も最初は、よくわからんままコピペしてました（まじです）。

自分でシェーダをガリガリと記述するのが無理でも、この記事内で紹介したような、シェーダアートのウェブサイトを見ているだけでもすごく楽しめるはずです。食わず嫌いで触らないまま終わってしまうには、あまりにも惜しい、それほどのメリットやポテンシャルを持っているのが GLSL です。

ぜひみなさんも、GLSL を使って楽しいシェーダライフを満喫してください。

これで心置きなく、暖まれますね！

よろしくどうぞ！！！！！

🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥