glsl で描く基本波形まとめ

# はじめに

glslでよく使う、波形関数をまとめています。

![780px-Waveforms.svg.png](https://qiita-image-store.s3.amazonaws.com/0/135381/cec46057-2f58-9223-ca5a-0dcc51b4b3bc.png)
出典 https://ja.wikipedia.org/wiki/%E7%9F%A9%E5%BD%A2%E6%B3%A2#/media/File:Waveforms.svg

# 正弦波

まずは、基本の正弦波、組み込み関数のsinだけで大丈夫、周期を引数-1.0～1.0の範囲で収めるためにはPIを掛ける必要がある。

![sin.png](https://qiita-image-store.s3.amazonaws.com/0/135381/a972f903-110c-1abe-e22f-41d7ee243994.png)
https://goo.gl/VJMmsV

```glsl
precision mediump float;
uniform vec2  m;       // mouse
uniform float t;       // time
uniform vec2  r;       // resolution
uniform sampler2D smp; // prev scene

const float PI  = 3.14;
const float PI2 = PI* 2.;

void main(void){
	vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
	float l=length(vec2(0,p.y+sin(p.x*PI)));
	gl_FragColor = vec4(vec3(l), 1.0);
}
```

# 矩形波

基本の矩形波2通りの作り方がある

sin波のパターンは極座標系で、それ以外はfractのものを使った方がいいでしょう。

## sinとstepを組み合わせたパターン

こちらは分かりやすい

![square.png](https://qiita-image-store.s3.amazonaws.com/0/135381/17760241-658b-c69a-6c80-5bf6a893aa10.png)
https://goo.gl/MLHG5T

```glsl
precision mediump float;
uniform vec2  m;       // mouse
uniform float t;       // time
uniform vec2  r;       // resolution
uniform sampler2D smp; // prev scene

const float PI  = 3.14;
const float PI2 = PI* 2.;

float sqr(float x){
	return 2.*(step(0.,sin(x*PI))-.5);
}

void main(void){
	vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
	float l=length(vec2(0,p.y+sqr(p.x)));
	gl_FragColor = vec4(vec3(l), 1.0);
}
```

## fractとstepを組み合わせたパターン

恐らくこちらの方が軽い

```glsl
precision mediump float;
uniform vec2  m;       // mouse
uniform float t;       // time
uniform vec2  r;       // resolution
uniform sampler2D smp; // prev scene

const float PI  = 3.14;
const float PI2 = PI* 2.;

float sqr(float x){
	//return 2.*(step(0.,sin(x*PI))-.5);
	return -2.*(step(.5,fract(x*.5))-.5);
}

void main(void){
	vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
	float l=length(vec2(0,p.y+sqr(p.x)));
	gl_FragColor = vec4(vec3(l), 1.0);
}
```
https://goo.gl/Zv3CQB

# のこぎり波

ようするにfract関数やmod関数ですね。 使いやすいように位相をずらしてます。

![saw.png](https://qiita-image-store.s3.amazonaws.com/0/135381/4d2572db-5b2e-0a4a-6c87-2202ee465d8a.png)

```
precision mediump float;
uniform vec2  m;       // mouse
uniform float t;       // time
uniform vec2  r;       // resolution
uniform sampler2D smp; // prev scene

const float PI  = 3.14;
const float PI2 = PI* 2.;

float saw(float x){
	return fract(-x*.5)*2.-1.;
}

void main(void){
	vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
	float l=length(vec2(0,p.y+saw(p.x)));
	gl_FragColor = vec4(vec3(l), 1.0);
}
```

# 三角波
![tri.png](https://qiita-image-store.s3.amazonaws.com/0/135381/ffa33b38-94e3-eee8-2083-27a7733a9778.png)
https://goo.gl/LwJ1iK

```glsl
precision mediump float;
uniform vec2  m;       // mouse
uniform float t;       // time
uniform vec2  r;       // resolution
uniform sampler2D smp; // prev scene

const float PI  = 3.14;
const float PI2 = PI* 2.;

float tri(float x){
	return abs(2.*fract(x*.5-.25)-1.)*2.-1.;
}

void main(void){
	vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
	float l=length(vec2(0,p.y+tri(p.x)));
	gl_FragColor = vec4(vec3(l), 1.0);
}
```

* sinとasinを使った三角波、周期がPIのときはこっちが良さそう

```glsl
precision mediump float;
uniform vec2  m;       // mouse
uniform float t;       // time
uniform vec2  r;       // resolution
uniform sampler2D smp; // prev scene

const float PI  = 3.14;
const float PI2 = PI* 2.;

float tri(float x){
    return asin(sin(x*PI))*2./PI;
	//return abs(2.*fract(x*.5-.25)-1.)*2.-1.;
}

void main(void){
	vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
	float l=length(vec2(0,p.y+tri(p.x)));
	gl_FragColor = vec4(vec3(l), 1.0);
}
```
* 参考 http://glslsandbox.com/e#46779.0

# 最後に
より複雑な波形を作るときにはiq先生がエディターを作っているので、こちらの [Graph Toy](http://www.iquilezles.org/apps/graphtoy/) を活用すると良いでしょう。

# 参考
* [第１２回 模様を付ける](http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20090920)
* [三角波の描き方](https://thndl.com/triangle-waves.html)