three.js超入門 第5回 シェーダー(GLSL)の基礎

# 概要
この記事では「three.js超入門」と題して、three.jsの基礎からシェーダーの利用までをやっていきます。
ターゲットは主に「canvas表現を触ったことがないフロントエンドエンジニア」を想定しているので、jsの構文などの説明は省略しています。
three.jsのバージョンは執筆時点で最新の[r98](https://github.com/mrdoob/three.js/releases/tag/r98)を使用します。

[three.js超入門 第0回 3Dコンピュータグラフィックスの基礎](https://qiita.com/watabo_shi/items/f7c559c3cdbcdd0f2629)
[three.js超入門 第1回 レンダリングまでの流れ](https://qiita.com/watabo_shi/items/bf9bcd4569b6d480c608)
[three.js超入門 第2回 アニメーションと時間ベースでの制御](https://qiita.com/watabo_shi/items/1c3c50429279eedec04e)
[three.js超入門 第3回 マウスやスクロールでのインタラクション](https://qiita.com/watabo_shi/items/0811d03390c18e46be86)
[three.js超入門 第4回 DOM要素との連携](https://qiita.com/watabo_shi/items/9ab12f62434a1e858226)
three.js超入門 第5回 シェーダー(GLSL)の基礎
[three.js超入門 第6回 ShaderMaterialでメッシュを変形、着色する](https://qiita.com/watabo_shi/items/c0d4ef11cba6f21189ed)
[three.js超入門 第7回 シェーダーに変数を渡す](https://qiita.com/watabo_shi/items/1b48ca54a9034f3614d8)
[three.js超入門 第8回 シェーダーをインタラクティブに動かす](https://qiita.com/watabo_shi/items/39d21d53ca16541fd498)
[three.js超入門 第9回 シェーダーでテクスチャにエフェクトをかける](https://qiita.com/watabo_shi/items/2fc671f2147e799787f9)

[リポジトリ](https://github.com/watab0shi/threejs-workshop)

シリーズで書いてはいるものの、脱線して小ネタ集みたいになってきてしまったので、そろそろちゃんとした記事を書こうと思い、今回からGLSLをやろうとおもいます。。（着地点定まってないですが、、w）

# GLSLとは
OpenGL Shading Language （OpenGLシェーディング言語）の略称です。
C言語がベースになっています。
「シェーディング」の名の通りモデルに陰影をつけるためのものですが、頂点やピクセル単位でいじれるので、陰影だけでなく様々な表現が可能です。
WebGL1.0では、「頂点シェーダー」「フラグメントシェーダー（ピクセルシェーダー）」の2つが利用可能です。
ファイルの拡張子は、頂点シェーダーは`.vert`（または`.glsl`）、ピクセルシェーダーは`.frag`（または`.glsl`）です。

# 人はなぜシェーダーを書くのか
CPUではなくGPUで処理される。
GPUは頂点やピクセルなど、大量の情報を一気に処理するのが得意。
CPUでやるとフレーム落ちするような重い処理を、GPUで実装するとサクサク動かせる。
「CPUはスポーツカー、GPUはバス」（堤さんの[スライド](https://www.slideshare.net/t26v0748/metal-iosdc)（P.34）より）
ポストエフェクトが短いコードで作れる。（グリッチやディストーションなど）

# シェーダーが実行されるタイミング
[第0回](https://qiita.com/watabo_shi/items/f7c559c3cdbcdd0f2629)のこの図を思い出してください。
![DQ2P8qcUMAE3VK7.jpg](https://qiita-image-store.s3.amazonaws.com/0/86966/d52e7f1d-7ef3-948b-a5f4-7106034ce29d.jpeg)
（画像は[床井先生のTwitter](https://twitter.com/tokoik/status/940566212118847490/photo/1)から引用）
CPU（JavaScript）で作った図形データ（線や面）を画面に表示する際に、ラスタ化処理が実行されます。
実は、このフローの中にシェーダーが隠れています。

## シェーダーの実行フロー
### 頂点データ
CPUで作成した頂点座標
↓
### （頂点シェーダー）
頂点データを処理（座標を動かしたり、パースをかけたり、）
↓
### ラスタライズ
頂点シェーダーで処理された頂点データを元に、線や面を画素データに変換
↓
### （ピクセルシェーダー）
ラスタライズされた画素データを処理（色を変えたり、テクスチャ座標をずらしたり、）
↓
### 画素データ
ピクセルシェーダーで決定した画素データを表示

# GLSLの書き方
頂点シェーダー、ピクセルシェーダー共に`main()`関数の中にひとつの頂点（またはピクセル）に対する処理を書いていきます。

```glsl
void main() {
  // ここに処理
}
```

## 頂点シェーダー
`gl_Position`に`vec4`型の座標を入れることで頂点を決定します。

```glsl
gl_Position = vec4( x, y, z, w );
```

## ピクセルシェーダー
`gl_FragColor`に`vec4`型の色を入れることでピクセル色を決定します。

```glsl
gl_FragColor = vec4( r, g, b, a );
```

## GLSL変数の型について
`int`：整数
`float`：小数
`vec2`：2つの小数値からなるベクトル（`xy`）
`vec3`：3つの小数値からなるベクトル（`xyz`, `rgb`）
`vec4`：4つの小数値からなるベクトル（`xyzw`, `rgba`）
`mat2`：`2x2`の`float`の行列
`mat3`：`3x3`の`float`の行列
`mat4`：`4x4`の`float`の行列
`sampler2D`：テクスチャ

### `vec`型の要素へのアクセス
`JavaScript`の`Object`と同じく、`vec.x`, `vec.y`, `vec.z`, `vec.w`でアクセスできるほか、`vec.r`, `vec.g`, `vec.b`, `vec.a`でも同じ数値にアクセスできます。
`vec.xy`, `vec.xyz`と書くことで`vec`型として値を取り出すこともできます。

## コーディング時の注意点
型に厳密なので、`float`を引数にとる型で`vec2(1, 1)`のように整数を書くとエラーになります。
`float`が入るところには少なくとも小数点を書かないとコンパイルが通りません。（例：`vec2(1., 1.)`）
GLSLで色を指定するときは、`0 ~ 255`ではなく、`0.0 ~ 1.0`で指定します。

# 参考URL
[The Book of Shaders](https://thebookofshaders.com/?lan=jp)
[第三回 WebGLスクール 「シェーダの基礎」](https://qiita.com/konweb/items/ec8fa8cd3bc33df14933#glsl%E3%81%AE%E5%9F%BA%E7%A4%8E)

次回は実際にthree.jsでGLSLを利用する方法をやります。