ツイッターで書いた以下の #つぶやきGLSL の作成ログです。
#つぶやきGLSL
void main(){mat3 m=mat3(.5);vec2 p=(gl_FragCoord.xy*2.-r)/r;float y=mod(t,6.),c=floor(y/2.);y-=c*2.;gl_FragColor.rgb=c<.1?m[2]:c<2.?m[0]:m[1];if(2.-y*4.<p.x+p.y)for(float i=-2.;i<2.;i+=.2)if(abs(p.x-p.y+i)<max(y-1.,.2)*.1)gl_FragColor.rgb=c<.1?m[0]:c<2.?m[1]:m[2];} pic.twitter.com/67saR3nF1d— Narumium (@Nr_Narumium) November 9, 2020
斜めに線を描く
とりあえず点 p を中心を原点にした -1 から 1 の座標にします。
右上 (1, 1) から左下 (-1, -1) へと動かすことを考えるとこうなります。
1 2 3 4 5 6 7 |
precision highp float; uniform vec2 resolution; uniform float time; void main(){ vec2 r=resolution,p=(gl_FragCoord.xy*2.-r)/r; if(2.-time<p.x+p.y)gl_FragColor=vec4(0,.5,0,1); } |
斜めの線状にするには x = y である部分だけ描画する。
1 2 3 4 5 6 |
void main(){ vec2 r=resolution,p=(gl_FragCoord.xy*2.-r)/r; if(2.-time<p.x+p.y) if(abs(p.x-p.y)<.01) gl_FragColor=vec4(0,.5,0,1); } |
線を複数にするために y = ax + b の式に当てはめます。
1 2 3 4 5 6 7 |
void main(){ vec2 r=resolution,p=(gl_FragCoord.xy*2.-r)/r; if(2.-time<p.x+p.y) for(float i=-2.;i<2.;i+=.1) if(abs(p.x-p.y+i)<.01) gl_FragColor=vec4(0,.5,0,1); } |
ここまでのコードは時間が過ぎると動きがなくなります。
4秒で書き終わるようなので mod() でリピートするようにします。
1 2 3 4 5 6 |
void main(){ vec2 r=resolution,p=(gl_FragCoord.xy*2.-r)/r; if(2.-mod(time,4.)<p.x+p.y) for(float i=-2.;i<2.;i+=.1)if(abs(p.x-p.y+i)<.01) gl_FragColor=vec4(0,.5,0,1); } |
線を膨らませる
現在の線の間隔は 0.1 なので線の太さを0.05 にすると塗りつぶせる。
time * 0.03 の部分で速度を調整しています。
1.7 * 0.03 = 0.051 の太さになるところでリピートするようにしました。
1 2 3 4 5 6 |
void main(){ vec2 r=resolution,p=(gl_FragCoord.xy*2.-r)/r; for(float i=-2.;i<2.;i+=.1) if(abs(p.x-p.y+i)<mod(time,1.7)*.03) gl_FragColor=vec4(0,.5,0,1); } |
要素の合成
単純に混ぜ合わせるだけでもなんとなく面白い。
この場合はリピートを mod でなく三角関数を使った方が自然かもしれない。
1 2 3 4 5 6 |
void main(){ vec2 r=resolution,p=(gl_FragCoord.xy*2.-r)/r; if(2.-mod(time,4.)<p.x+p.y) for(float i=-2.;i<2.;i+=.1)if(abs(p.x-p.y+i)<mod(time,2.)*.025) gl_FragColor=vec4(0,.5,0,1); } |
時間をいじると2つを順に描画できる。
1 2 3 4 5 6 7 8 |
void main(){ vec2 r=resolution,p=(gl_FragCoord.xy*2.-r)/r; float y=mod(time,6.); if(2.-y<p.x+p.y) for(float i=-2.;i<2.;i+=.1) if(abs(p.x-p.y+i)<max((y-4.)*.025,.01)) gl_FragColor=vec4(0,.5,0,1); } |
秒数や線の間隔などを調整しつつ色を変える。
最近気づいたけど RGB の使い分けに mat3
は便利です。
引数1つだと対角行列になるので m[0], m[1], m[2]
が RGB になる。
1 2 3 4 5 6 7 8 9 |
void main(){ mat3 m=mat3(.5); vec2 r=resolution,p=(gl_FragCoord.xy*2.-r)/r,v=vec2(.5,0); float y=mod(time,6.),c=floor(y/2.);y=mod(y,2.); if(2.-y*4.<p.x+p.y) for(float i=-2.;i<2.;i+=.2) if(abs(p.x-p.y+i)<max((y-1.)*.1,.02)) gl_FragColor.rgb=c==0.?m[0]:c==1.?m[1]:m[2]; } |
背景色も同様に変化させつつ、モードを geeker に変えて文字数を削減。
最終的にはこの形。
1 2 3 4 5 |
void main(){ mat3 m=mat3(.5);vec2 p=(gl_FragCoord.xy*2.-r)/r;float y=mod(t,6.),c=floor(y/2.);y-=c*2.; gl_FragColor.rgb=c<.1?m[2]:c<2.?m[0]:m[1]; if(2.-y*4.<p.x+p.y)for(float i=-2.;i<2.;i+=.2)if(abs(p.x-p.y+i)<max(y-1.,.2)*.1)gl_FragColor.rgb=c<.1?m[0]:c<2.?m[1]:m[2]; } |
今回は色選択の三項演算時部分の省略が大きかったです。
1 2 |
gl_FragColor.rgb=c==0.?m[0]:c==1.?m[1]:m[2]; gl_FragColor.rgb=c<.1?m[0]:c<2.?m[1]:m[2]; |