GLSLの数学的な関数で感じたこと

どうもGLSLビギナーの[@muripo_life](https://twitter.com/muripo_life)です。
とりあえず、なんか書いてみます。

# はじめに
今回は、何かしらの作品を作ってのっけようかと思いつつ、時間が迫っていたので、断念…
GLSLで使用する数学的な関数がどんな関数なのかを軽く書いていこうと思います。
あくまで、ざっくりしたイメージなので、厳密的な突っ込みをされると厳しいです…

# 関数一覧
* sin, cos, tan : 三角関数
	* radius(x):「度数方→弧度法」
	* degrees(x):「弧度法→度数方」
* asin, acos, atan:逆三角関数
* max(x, y)、min(x, y):最大最小値を返す
* exp:ネイピア数のべき乗
* log,log2:対数
* pow(x, y):xのy乗
* sqrt(x):平方根
* inverssqrt(x):1/sqrt(x)を返す
* abs(x):絶対値
* sign(x):xが正なら+1.0、0.0なら0.0、負なら-1.0を返す
* floor(x):x以下の最大の整数を返す
* ceil(x):x以上の最小の整数を返す
* fract(x):x-floor(x)を返す
* mod(x, y):x-y*floor(x/y)を返す
* clamp(x, a, b):上限値
* step(a, x):aはしきい値、xはチェックされる値。しきい値以下の場合は0.0を、それ以上の場合は1.0の二値化を行う関数
* mix(x, y, a):線形補間
* smoothstep(e0, e1, x):エルミート補完

# sin,cos,tan
<b>-1～1で繰り返す関数、周期的に繰り返す処理は、これを使うといい</b>
言わずと知れた、高校生が、数学で始めにつまずくやつ1位な気がする。

`sin`,`cos`は、何かしら `int`、`float` などを入れたら、-1.0～1.0の値を返してくれます。

`sin`のグラフ(`cos`は,1.57横にスライド)
![sin.PNG](https://qiita-image-store.s3.amazonaws.com/0/102634/1f270715-cff4-b6de-d5fe-5940c7dbeb2a.png)

`tan`のグラフ
![tan.PNG](https://qiita-image-store.s3.amazonaws.com/0/102634/2e85c8ba-a09e-4071-6623-e3e3fb57f4e1.png)

# arcsin,arccos,arttan
* 三角関数の逆関数(ざっくり言うと `y = x` について、対称な関数、ま～いろいろまだ条件はありますが…)
* グラフの書き方は、三角関数を書いて、90度傾けて、x軸とy軸の文字書き換えたらいいです。
* 取る値が、`asin→[-90,90]`, `acos→[0,180]`ごとに切れるのには、気を付けよう.

`arcsin`のグラフはこんな感じ
![asin.PNG](https://qiita-image-store.s3.amazonaws.com/0/102634/772818a6-9655-bce5-7f29-1d188a418893.png)

`arctan`のグラフはこんな感じ
![atan.PNG](https://qiita-image-store.s3.amazonaws.com/0/102634/8bf77b3f-27f1-c3fe-5769-9a4c437c4e71.png)


# exp

グラフはこんな感じ
![exp.PNG](https://qiita-image-store.s3.amazonaws.com/0/102634/f6b15361-07c1-5a08-de10-0d9dfe5c1a98.png)

とりあえず、ヌルヌル動かしたい処理はこれを使おうと思います。

なぜ、ヌルヌル動くかは、expを[Taylor展開](https://ja.wikipedia.org/wiki/%E3%83%86%E3%82%A4%E3%83%A9%E3%83%BC%E5%B1%95%E9%96%8B)すればわかります。

多項式に展開した時に、オーダーが小さい(一番細かく分解されて、近似できるから)からですね（たぶん）…

# abs
絶対値です。
入れた値がマイナスならプラスにします。

とりあえず、グラフはこんな感じ
![abs.PNG](https://qiita-image-store.s3.amazonaws.com/0/102634/56303567-6742-755a-be69-46e249a56af9.png)

# min,max
最大値、最小値を返します。

# clamp
`min(max(x, a), b) `
上限値があることには、割と驚きです。（shader書くときにいつ使うんだろ?）
どうも、[被写界深度](https://wgld.org/d/webgl/w059.html)で、出てくるみたいです.
ちなみに、数学では、`sup` と表します（込み入った微分積分の話で出てきます）
よくよく考えたら、一番いい例なのか…

# mod
数学では、[合同式](https://ja.wikipedia.org/wiki/%E6%95%B4%E6%95%B0%E3%81%AE%E5%90%88%E5%90%8C)と言います。
合同式の使い方は、普段整数値しか使いません。（深いところだと、実数まで使うかもしれませんが…）
glslだと、「x-y*floor(x/y)を返す」と`float`を使っていて、かなり驚きました。

# glslの式を触ってみた所感
## arctanは重要な気がする…
atanは、ライティングでとてつもなく重要だと思ったりしています…

例えば、ライティングの時の光の減衰を考えるときに、距離減衰関数という関数を用いるようですが…

* constantAtt : 定数減衰(constant attenuation)
* linearAtt : 線形減衰(linear attenuation)
* quadraticAtt : 2次減衰(quadratic attenuation)
* r: 光源距離

|光|式|
|:---|:---|
|現実世界光の減衰|`1/(r^2)`|
|ライティングの光の減衰|`1/(constantAtt + linearAtt * r + quadraticAtt * r^2)`|

となりますが…

```math
1/(constantAtt + linearAtt * r + quadraticAtt * r^2)
```
 → 

```math
1/二次関数
```
の形となっており積分は

```math
arctan
```
なんです…

ここら辺の話は、今後書いていこうと思います…

# つ…つぎは…
作品かglslのまともな記事あげます…
ちなみに、グラフもglslで、作りたかったものの…
断念(Mathematicaオンラインで書きました…)…
物を作るって難しい…

#参考記事
* [GLSLについてのメモ](http://qiita.com/edo_m18/items/71f6064f3355be7e4f45)
* [OpenGL ESシェーディング言語](http://ec.nikkeibp.co.jp/nsp/dl/08513/HTML5GAMES_AppC.pdf)
* [wgld.org_被写界深度](https://wgld.org/d/webgl/w059.html)
* [実践プログラミングWebGL HTML & JavaScriptによる3Dグラフィックス開発](https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0WebGL-HTML-JavaScript%E3%81%AB%E3%82%88%E3%82%8B3D%E3%82%B0%E3%83%A9%E3%83%95%E3%82%A3%E3%83%83%E3%82%AF%E3%82%B9%E9%96%8B%E7%99%BA-Programmer%E2%80%99s-SELECTION/dp/4798129534)