2次元ディスタンスフィールド使い方

# はじめに
[2次元ディスタンスフィールドまとめ](https://qiita.com/7CIT/items/fe33b9b341b9918b6c3d)では色々な距離関数(ディスタンスフィールド)について紹介しました。しかし、距離関数(ディスタンスフィールド)だけでは図形を描くことはできません。距離関数(ディスタンスフィールド)に距離を設定することではじめて図形を描くことができます。ここでは、距離関数(ディスタンスフィールド)に距離を設定して、塗り、線、グロウなど、様々な図形の描画方法を紹介します。

# 距離の設定と、線・塗り

## 距離を設定する(放射状グラデーション塗り)

まず、素のままの距離関数(ディスタンスフィールド)を可視化してみます。

![rawdist.png](https://qiita-image-store.s3.amazonaws.com/0/135381/c59df372-da98-72e5-8f2e-de62ae2a6ff6.png)

https://goo.gl/pnzkzZ

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

void main(void){
	vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
	float distanceFunc;
	float bright;
	float radius=.5;
	distanceFunc = length(p);
	// direct output
	bright = distanceFunc;
	// gradation circle  
	//bright = radius - distanceFunc;
	// circle fill
	//bright = step(0.,radius - distanceFunc);
	// circle stroke
	//bright = 1.-step(.005,abs(radius - distanceFunc));
	// circle fill + glow
	//bright = radius / distanceFunc;
	gl_FragColor = vec4(vec3(bright), 1.0);
}
```

この時点ではまだ図形が確定していません。

これに距離.5を与えてあげると半径0.5のグラデーションの円が描けます。

![gradcircle.png](https://qiita-image-store.s3.amazonaws.com/0/135381/373d75eb-13c2-5168-9258-1dc484726fe7.png)

```glsl
bright = radius - distanceFunc;
```

## べた塗り

グラデーションの塗りで0.以上を1.としてあげればベタ塗りが出来ます。

![fillcircle.png](https://qiita-image-store.s3.amazonaws.com/0/135381/b9dffda7-44e6-5227-b069-f48954759529.png)

```glsl
bright = step(0.,radius - distanceFunc);
```

## 線

![linecircle.png](https://qiita-image-store.s3.amazonaws.com/0/135381/76646b08-fe06-22ea-3a0b-5273d02571a9.png)

```
bright = step(abs(radius - distanceFunc),.005);
```

## 塗り+ glow
![glowfill.png](https://qiita-image-store.s3.amazonaws.com/0/135381/ba770000-6a5b-8000-b0da-c5f3853c4877.png)

```glsl
bright = radius / distanceFunc;
```

## glow

### グロウ

![glow.png](https://qiita-image-store.s3.amazonaws.com/0/135381/6c5f3c6e-cb93-d9c7-308e-b929710df953.png)

```glsl
bright = 0.01 / abs(distanceFunc - radius);
```

### グロウ(外側) 
![glowOuter.png](https://qiita-image-store.s3.amazonaws.com/0/135381/06e554d9-e7f6-8ad4-c527-af6e39c99872.png)

```glsl
bright = 0.01 / (distanceFunc - radius);
```

### グロウ(内側) 
![glowInner.png](https://qiita-image-store.s3.amazonaws.com/0/135381/59e9e46a-26a5-46fe-58af-31af13b55b3c.png)

```glsl
bright = 0.01 / -(distanceFunc - radius);
```

# アンチエイリアス

線や塗りで、stepのところをsmoothstepに変えて極小な範囲を設定するとアンチエイリアスを掛ける(ギザギザを無くす)ことができます。

![antifill.png](https://qiita-image-store.s3.amazonaws.com/0/135381/fc60e9b3-add8-810d-ab33-cdf317d3995e.png)

```glsl
bright = smoothstep(0.,.01,radius - distanceFunc);
```
![antiline.png](https://qiita-image-store.s3.amazonaws.com/0/135381/3db7321c-4777-1643-7fbe-5613fd21d391.png)

```glsl
	bright = 1.-smoothstep(.005,.015,abs(radius - distanceFunc));
```

# グラデーション

smoothstepの範囲を大きくすると任意の長さのグラデーションとして利用できます。

![gradfill.png](https://qiita-image-store.s3.amazonaws.com/0/135381/b47a9c37-d99b-edc0-274c-2cb63e0e06d0.png)

```glsl
bright = smoothstep(0.,.5,radius - distanceFunc);
```

![gradline.png](https://qiita-image-store.s3.amazonaws.com/0/135381/422d38cd-0005-600d-fcf7-cb9ad30a78c4.png)

```glsl
bright = 1.-smoothstep(.005,.5,abs(radius - distanceFunc));
```

## 参考
* [2Dの小技　動くお絵かき](https://qiita.com/gaziya5/items/29a51b066cb7d24983d6)
* [[連載]やってみれば超簡単！ WebGL と GLSL で始める、はじめてのシェーダコーディング（６）](https://qiita.com/doxas/items/00567758621bb506e584)