step
step関数はシェーダーで利用できる関数。パラメータを2つ与え、大小の判定をして1か0を返却する。
この性質のため、条件分岐や論理演算の代用として使用されるケースがある。
個人的にこのことをstep芸と呼んでる。
https://gyazo.com/6c4e53bb3465d9ddf45ab1bf696385f2.png
if文をstep()で書き換える
trueを1、falseを0として扱う。
code:IfStep.HLSL
// if文
if(x <= 0.1) {
return 1.0;
} else {
return 0.0;
}
// step()
return step(x, 0.1);
x >= c
step(c, x);
x < c
1.-step(c, x)
x != c
abs(sign(x - c));
x == c
1.-abs(sign(x - c));
X && Y
step(X)*step(Y);
X || Y
step(.5, step(X)+step(Y));
reference
条件分岐のためにstep関数を使う時の考え方をまとめてみた
code:a<=x<=b.GLSL
(1-step(b, x))*step(a, x)
※step(a, b) == 1 - step(b, a)
step(a,x)-step(b,x)
(b-a)/2-abs(x-(a+b)/2)
https://gyazo.com/6c4e53bb3465d9ddf45ab1bf696385f2.png
smoothstep
エルミート補完/Hermite Interpolation
3次関数の値を使った補完。GLSLのSmoothstep実装として利用される。
code:SmoothstepHermite.GLSL
t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
https://gyazo.com/6c4e53bb3465d9ddf45ab1bf696385f2.png
図形を描く
円
step(length(p), size);
四角形
step(max(abs(p.x), abs(p.y)), size);
code:GLSL
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
float d = 0.0;
// Remap the space to -1. to 1.
st = st *2.-1.;
// Number of sides of your shape
int N = 3;
// Angle and radius from the current pixel
float a = atan(st.x,st.y)+PI;
float r = TWO_PI/float(N);
// Shaping function that modulate the distance
d = cos(floor(.5+a/r)*r-a)*length(st);
color = vec3(1.0-smoothstep(.4,.41,d));
// color = vec3(d);
gl_FragColor = vec4(color,1.0);
}
https://gyazo.com/6c4e53bb3465d9ddf45ab1bf696385f2.png
2つの色から片方を選択する
float t = mod(time, 4.0);
step(t, 2.0) * a + step(2.0, t) * b;
code:SeigaihaAndSayagata.GLSL
precision mediump float;
uniform float time;
uniform vec2 resolution;
const float PI=acos(-1.0);
vec2 rot(vec2 p,float a){return vec2(p.x*cos(a)-p.y*sin(a),p.x*sin(a)+p.y*cos(a));}
//-----
vec3 circle(vec2 p,float r){
// 瑠璃色
vec3 ruriiro=vec3(42.,92.,170.)/255.;
vec3 white=vec3(1.);
if(length(p)>6./6.*r) return white;
if(length(p)>5./6.*r) return ruriiro;
if(length(p)>4./6.*r) return white;
if(length(p)>3./6.*r) return ruriiro;
if(length(p)>2./6.*r) return white;
if(length(p)>1./6.*r) return ruriiro;
return white;
}
vec3 seigaiha(vec2 p,float r){
// 青海波
vec2 q=p;
float f=floor(p.x);
q=fract(q);
float dif=step(1.,mod(f,2.))*r;
q.x-=dif;
if(length(q+vec2(.0,r/2.))<r) return circle(q+vec2(.0,r/2.),r);
if(length(q+vec2(-r,.0))<r) return circle(q+vec2(-r,.0),r);
if(length(q+vec2(r,.0))<r) return circle(q+vec2(r,.0),r);
if(length(q+vec2(.0,-r/2.))<r) return circle(q+vec2(.0,-r/2.),r);
return vec3(1.);
}
//-----
float rect(vec2 p, float x1, float y1, float x2, float y2) {
float d = .00001; // 線のエッジ
return (
smoothstep(x1, x1 + d, p.x) * smoothstep(x2, x2 - d, p.x) *
smoothstep(y1, y1 + d, p.y) * smoothstep(y2, y2 - d, p.y)
);
}
vec3 sayaUnit(vec2 p,vec2 rev){
// 紺
vec3 kon=vec3(.0,26.,67.)/255.;
// 瑠璃紺
vec3 rurikon=vec3(34.,75.,144.)/255.;
// note
// p : 0.0-1.0
// rev : border
vec2 q=p;
q.x=step(.5,rev.x)*q.x+step(rev.x,.5)*(1.-q.x);
q.y=step(.5,rev.y)*q.y+step(rev.y,.5)*(1.-q.y);
float pat = .0;
float block = 1./5.;
float u=.5*block;
pat=clamp(
rect(q,.0,.0,u,9.*u)
+rect(q,u,7.*u,7.*u,9.*u)
+rect(q,3.*u,5.*u,5.*u,7.*u)
,.0,1.);
q=1.-q;
pat=clamp(pat+
rect(q,.0,.0,u,9.*u)
+rect(q,u,7.*u,7.*u,9.*u)
+rect(q,3.*u,5.*u,5.*u,7.*u)
,.0,1.);
return kon*pat+rurikon*step(pat,.1);
}
vec3 sayagata(vec2 p,float m){
// 紗綾形
vec2 q=p*m;
vec2 ind=floor(p*m);
q=fract(q);
vec2 rev=step(.0,(mod(ind,2.)-1.));
vec3 col=sayaUnit(q,rev);
return col;
}
//-----
void main(void)
{
vec3 col = vec3(.0);
//-----
vec2 p = (gl_FragCoord.xy*2.0-resolution.xy)/resolution.y;
p*=5.;
vec3 colSeigaiha=vec3(0.);
float r=1.;
colSeigaiha=seigaiha(p,r);
//-----
p = (gl_FragCoord.xy*2.0-resolution)/min(resolution.x,resolution.y);
vec3 colSayagata = vec3(.0);
vec2 q=p;
q*=vec2(.75,1.75);
q=rot(q,PI/4.+.00001);
colSayagata=sayagata(q, 3.);
//-----
float t = mod(time, 4.0);
col = step(t, 2.0) * colSeigaiha + step(2.0, t) * colSayagata;
gl_FragColor = vec4(col, 1.);
}
https://gyazo.com/6c4e53bb3465d9ddf45ab1bf696385f2.png
glitch
glitchを描く
座標に対してブロックを定義/モザイクのアルゴリズムと同様
ブロックを元にノイズを求める
ノイズに対して閾値でstepを求める *1
時間によるホワイトノイズを求める *2
*1 と *2を乗算したものをテクスチャ座標に加える
code:stepGlitch.GLSL
precision mediump float;
uniform float time;
uniform vec2 resolution;
const float PI=acos(-1.0);
vec2 rot(vec2 p,float a){return vec2(p.x*cos(a)-p.y*sin(a),p.x*sin(a)+p.y*cos(a));}
//-----
vec3 circle(vec2 p,float r){
// 瑠璃色
vec3 ruriiro=vec3(42.,92.,170.)/255.;
vec3 white=vec3(1.);
if(length(p)>6./6.*r) return white;
if(length(p)>5./6.*r) return ruriiro;
if(length(p)>4./6.*r) return white;
if(length(p)>3./6.*r) return ruriiro;
if(length(p)>2./6.*r) return white;
if(length(p)>1./6.*r) return ruriiro;
return white;
}
vec3 seigaiha(vec2 p,float r){
// 青海波
vec2 q=p;
float f=floor(p.x);
q=fract(q);
float dif=step(1.,mod(f,2.))*r;
q.x-=dif;
if(length(q+vec2(.0,r/2.))<r) return circle(q+vec2(.0,r/2.),r);
if(length(q+vec2(-r,.0))<r) return circle(q+vec2(-r,.0),r);
if(length(q+vec2(r,.0))<r) return circle(q+vec2(r,.0),r);
if(length(q+vec2(.0,-r/2.))<r) return circle(q+vec2(.0,-r/2.),r);
return vec3(1.);
}
//-----
float rect(vec2 p, float x1, float y1, float x2, float y2) {
float d = .00001; // 線のエッジ
return (
smoothstep(x1, x1 + d, p.x) * smoothstep(x2, x2 - d, p.x) *
smoothstep(y1, y1 + d, p.y) * smoothstep(y2, y2 - d, p.y)
);
}
vec3 sayaUnit(vec2 p,vec2 rev){
// 紺
vec3 kon=vec3(.0,26.,67.)/255.;
// 瑠璃紺
vec3 rurikon=vec3(34.,75.,144.)/255.;
// note
// p : 0.0-1.0
// rev : border
vec2 q=p;
q.x=step(.5,rev.x)*q.x+step(rev.x,.5)*(1.-q.x);
q.y=step(.5,rev.y)*q.y+step(rev.y,.5)*(1.-q.y);
float pat = .0;
float block = 1./5.;
float u=.5*block;
pat=clamp(
rect(q,.0,.0,u,9.*u)
+rect(q,u,7.*u,7.*u,9.*u)
+rect(q,3.*u,5.*u,5.*u,7.*u)
,.0,1.);
q=1.-q;
pat=clamp(pat+
rect(q,.0,.0,u,9.*u)
+rect(q,u,7.*u,7.*u,9.*u)
+rect(q,3.*u,5.*u,5.*u,7.*u)
,.0,1.);
return kon*pat+rurikon*step(pat,.1);
}
vec3 sayagata(vec2 p,float m){
// 紗綾形
vec2 q=p*m;
vec2 ind=floor(p*m);
q=fract(q);
vec2 rev=step(.0,(mod(ind,2.)-1.));
vec3 col=sayaUnit(q,rev);
return col;
}
//-----
vec2 rand(vec2 x){return fract(sin(x*567.+123.)*98.);}
float rand1(vec2 x){return 1.-(.9*step(.88,fract(time*33.)))*fract(dot(sin(x.x*567.+123.*time)*98.,sin(x.y*567.+123.*time)*98.));}
vec2 coordGlitch(){
vec2 p = (gl_FragCoord.xy*2.0-resolution.xy)/min(resolution.x,resolution.y);
vec2 b = floor(p*10.)/10.;
vec2 i=floor(b),f=fract(p);
vec2 n=mix(rand(i),rand(i+1.),f)*fract(.5*time);
n=1.-(.9*step(.88,fract(time*13.)))*n*b;
return p*n;
}
//-----
void main(void)
{
vec3 col = vec3(.0);
//-----
vec2 p;
p=coordGlitch();
p*=5.;
vec3 colSeigaiha=vec3(0.);
float r=1.;
colSeigaiha=seigaiha(p,r);
//-----
p=coordGlitch();
vec3 colSayagata = vec3(.0);
vec2 q=p;
q*=vec2(.75,1.75);
q=rot(q,PI/4.+.00001);
colSayagata=sayagata(q, 3.);
//-----
float t = mod(time, 4.0);
col = step(t, 2.0) * colSeigaiha + step(2.0, t) * colSayagata;
//-----
p = (gl_FragCoord.xy*2.0-resolution)/min(resolution.x,resolution.y);
col *= rand1(p);
gl_FragColor = vec4(col, 1.);
}