GLSLで旭日旗


[kodelife]((https://hexler.net/products/kodelife))を使って旭日旗を描いてみます
#円を描く


```glsl
float drawCircle(vec2 uv, vec2 pos, float radius){
    float check = 1.f - step(radius,length(uv - pos));
    return check;
}
```

この関数は**与えられた座標**と**円の中心の座標**の距離が**半径よりも小さい**場合``1.0``を、そうでない場合は``0.0``を返します。

```glsl
    step(radius,length(uv - pos));
```
この部分で二点間を結ぶベクトルのノルム(長さ)が`step`関数によって `1.0` もしくは　`0.0`の値に変換されます。

実際に使用した際のコードが以下です。

```glsl
float drawCircle(vec2 uv, vec2 pos, float radius){
    float check = 1.f - step(radius,length(uv - pos));
    return check;
}

void main(void)
{
    vec2 uv = -1. + 2. * inData.v_texcoord;
    vec4 lastCol = vec4(0.0,0.0,0.0,1.0);
    
    vec2 pos = vec2(0.0,0.0);
    float circle = drawCircle( uv, pos, 0.3);
    lastCol = vec4(1.0,0.0,0.0,1.0) * circle;
    
    fragColor = lastCol;
 }

```


drawCircle関数から返ってきた値と`vec4(1.0,0.0,0.0,1.0)`の積をとって出力すると



![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91881/5f812fd6-e2c7-de78-c8c0-8d8a8661ccd4.jpeg)

赤色の円が描画されました。

#放射模様を描く

先ほど作成したdrawCircleを用いて旭日旗の放射模様も描画してみます。
main文を少し変えてあげて

```glsl

void main(void)
{
    vec2 uv = -1. + 2. * inData.v_texcoord;
    vec4 lastCol = vec4(0.0,0.0,0.0,1.0);
    
    vec2 pos = vec2(0.0,0.0);
    vec2 centorVect = uv - pos;
    float rad = atan(centorVect.y/centorVect.x);
    
    float radiation = drawCircle(uv,pos,cos( rad * 12 ));
    float circle = drawCircle(uv, pos, 0.3);
    
    vec4 sun = vec4(clamp(circle + radiation, 0,1), 0.0, 0.0, 0.0);
    
    lastCol = vec4( 1.0, 0.0, 0.0, 1.0) * sun;
    
    fragColor = lastCol;
 }
```

出力結果がこちらです。

![a.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91881/0b33c91e-0d4d-94b9-b2a5-ae93b955bb69.jpeg)

要点だけ解説していきます。

###atanを用いた角度の算出

```glsl
    vec2 centorVect = uv - pos;
    float rad = atan(centorVect.y/centorVect.x);
```
``centorVect``が円の中心から各uv座標までのベクトルです。
このベクトルとタンジェントの逆関数`atan`を用いて**円の中心を基準としたuv座標の角度**を求めています。
`atan`関数について簡単に説明すると
![Trigonometry_triangle.svg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91881/5b33dd68-e9b8-6b77-d3ef-cf3404d968dd.png)
(画像はwikipediaから引用しています。)

上図の直角三角形において∠A = θ に対してtan(θ)は

```math
tan(θ) = a/b
```
と定義されています。これに対し、tan(θ)の逆関数は

```math
arctan(a/b) = θ  \quad(- \pi/2 < θ < \pi/2)
```
です。

arctanを用いれば、aとbが求められれば直角三角形のなす角∠Aを求めることができます。
ちなみにglslの`atan`は値域が

```math

    (- \pi < θ < \pi)
```

の範囲で返ってきます。aやbが負数の時もカバーしています。便利！


###放射模様

```glsl
    float radiation = drawCircle(uv,pos,cos( rad * 12 ));
```
ここで放射模様`radiation`を求めています。
この行が示す内容は **与えられた座標**と**円の中心の座標**の距離が**cos( rad * 12 )よりも小さい**場合``1.0``を、そうでない場合は``0.0``を返します。
少し分かりづらいので図を使って補足すると

![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91881/e70bcbd4-8d3e-aacc-4c31-df5998d787fa.jpeg)

**cos( rad * 12 )**はcos(rad)の周期が1/12になった、上図のような波形をしています。
つまり、半径の閾値を波形にすることで放射模様を描いています。


#放射模様をシャープに

```glsl
void main(void)
{
    vec2 uv = -1. + 2. * inData.v_texcoord;
    vec4 lastCol = vec4(0.0,0.0,0.0,1.0);
    
    vec2 pos = vec2(0.0,0.0);
    vec2 centorVect = uv - pos;
    float rad = atan(centorVect.y/centorVect.x);
    
    float radiation = drawCircle(uv,pos,ceil(cos( rad * 12 )));
    float circle = drawCircle(uv, pos, 0.3);
    
    vec4 sun = vec4(clamp(circle + radiation, 0,1), 0.0, 0.0, 0.0);
    
    lastCol = vec4( 1.0, 0.0, 0.0, 1.0) * sun;
    
    fragColor = lastCol;
 }
```

出力結果はこちら
![a.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91881/a7b17d5f-2dd6-a7c8-93da-297eb98e1ae2.jpeg)



書き換えたのはこの部分です。

```glsl
    float radiation = drawCircle(uv,pos,ceil(cos( rad * 12 )));
```
`ceil(x)`はx以上の最小の整数を返す関数です。


cos(θ)の値域は

```math
    - 1 \leqq cos(θ) \leqq 1
```
なので`ceil(cos(θ))`は

```math
    ceil(cos(θ)) = 0.0 \quad (-1.0 < cos(θ) \leqq 0.0 )  \\
    ceil(cos(θ)) = 1.0 \quad (0.0 < cos(θ) \leqq 1.0 )  
```
になります。


![dqdq.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91881/c1543b49-aae4-1e7d-61e2-aa006eb61693.jpeg)


変換前が赤線で変換後が青線です。(汚い図でごめんなさい)

#完成

あとは適当に色を変えたりuvを調整したりして完成です。

![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91881/92385b1c-dd66-671c-8521-a7f85df574d3.jpeg)

```glsl
#version 150

uniform float time;
uniform vec2 resolution;
uniform vec2 mouse;
uniform vec3 spectrum;

uniform sampler2D texture0;
uniform sampler2D texture1;
uniform sampler2D texture2;
uniform sampler2D texture3;
uniform sampler2D prevFrame;
uniform sampler2D prevPass;

in VertexData
{
    vec4 v_position;
    vec3 v_normal;
    vec2 v_texcoord;
} inData;

out vec4 fragColor;

float drawCircle(vec2 uv, vec2 pos, float width){
    float check = 1.f - step(width,length(uv - pos));
    return check;
}

void main(void)
{
    
    vec2 uv = gl_FragCoord.xy / min(resolution.x,resolution.y) - vec2(max(resolution.x,resolution.y)/min(resolution.x,resolution.y)*0.5,0.5);
    uv += vec2(0.16,0.0);
    
    vec4 lastCol = vec4(0.0,0.0,0.0,1.0);
    float voice = length(spectrum);
    
    
    float l = 0.0;
    vec2 pos_offset = vec2(-0.0,0.0);
    vec2 pos = vec2(l*cos(time),l*sin(time))+pos_offset;
    vec2 centVec = uv-pos;
    
    
    float rad = atan(centVec.y/centVec.x);
    float radiation = drawCircle(uv,pos,0.0+voice*10.0*ceil(cos(rad*12+ time*10)));
    float circle = drawCircle(uv,pos,0.2);
    vec4 sun = vec4(clamp(radiation+circle,0,1),0.0,0.0,0.0);
    
    lastCol += sun.r*vec4(0.97,0.0,0.12,0.0);
    lastCol += (1.f-sun.r)*vec4(1.0,0.988,0.87,0.0);
    
    fragColor = lastCol;
   
}
```