なにかお手伝いできることがあればご連絡ください。
お問い合わせはこちらから
※Googleフォームが表示されます
GLSL Tech Night 2018
というイベントで、モーフィングのデモをみて感動したので挑戦してみました。
探してみると参考になる記事が結構沢山ありました。
まずはモーフィングさせるシェイプを描くために必要な距離関数について調べてみました。
その名の通り中心座標からの特定の座標(ピクセル)までの距離(長さ)を返す関数です。
//円の距離関数
float circle(vec2 p) {
return length(p);
}
void main( void ) {
vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
float d = circle(p);
vec3 color = vec3(smoothstep(0.5,0.51,d));
gl_FragColor = vec4(color, 1.0);
}
サンプル
//正方形の距離関数
float square(vec2 p){
return max(abs(p.x),abs(p.y));
}
void main( void ) {
vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
float d = square(p);
vec3 color = vec3(smoothstep(0.5,0.51,d));
gl_FragColor = vec4(color, 1.0);
サンプル
//正方形の距離関数
float square(vec2 p){
return abs(p.x) + abs(p.y);
}
void main( void ) {
vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
float d = square(p);
vec3 color = vec3(smoothstep(0.5,0.51,d));
gl_FragColor = vec4(color, 1.0);
}
サンプル
const float PI = 3.141592653589793;
const float PI2 = PI * 2.;
float lPolygon(vec2 p,int n){
float a = atan(p.x,p.y)+PI;
float r = PI2/float(n);
return cos(floor(.5+a/r)*r-a)*length(p);
}
void main( void ) {
vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
//5角形を描く
float d = lPolygon(p,5);
vec3 color = vec3(smoothstep(0.4,0.41,d));
gl_FragColor = vec4(color, 1.0);
}
サンプル
const float PI = 3.141592653589793;
const float PI2 = PI * 2.;
float lPolygon(vec2 p,int n){
float a = atan(p.x,p.y)+PI;
float r = PI2/float(n);
return cos(floor(.5+a/r)*r-a)*length(p);
}
mat2 mRotate(float a){
float c=cos(a);
float s=sin(a);
return mat2(c,-s,s,c);
}
float lStarPolygon(vec2 p,int n,float o){
return (lPolygon(p,n) - lPolygon(p * mRotate(PI2 / float(n) / 2.),n) * o) / (1.-o);
}
void main( void ) {
vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
float d = lStarPolygon(p,5,.6);
vec3 color = vec3(smoothstep(0.4,0.41,d));
gl_FragColor = vec4(color, 1.0);
}
サンプル
モーフィングはmix関数を利用して行います。 mix関数は線形補間を行うので、第三引数の値を変えることでモーフィングを実現できるみたいです。 イメージは以下の感じです。
閾値は0.0 ~ 1.0のサイン波になるようにします。
float a = sin(time * 5.0) * 0.5 + 0.5;
サンプル
一部だけ抜粋します。 ポイントは、
float getShape(vec2 p, int i) {
if (i == 0) {
return circle(p);
} else if (i == 1) {
return square(p);
} else if (i == 2) {
return lStarPolygon(p,5,.6)* 1.5;
} else if (i == 3) {
return square2(p);
} else {
return lPolygon(p,3) * 1.5;
}
}
void main() {
vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
float t0 = mod(time , 5.0);
float t1 = mod(time + 1.0, 5.0);
int i0 = int(floor(t0));
int i1 = int(floor(t1));
float f = fract(t0);
float d = mix(getShape(p,i0), getShape(p,i1), f);
vec3 color = vec3(smoothstep(0.5,0.51,d*1.5));
gl_FragColor = vec4(color, 1.0);
}
サンプル
なにかお手伝いできることがあればご連絡ください。
※Googleフォームが表示されます