double spiral
最終更新日時: 2025年08月25日 12:57
#ifdef GL_ESprecision mediump float;#endif
// Double Spiral 2017-11-28 modified by @hintz
uniform float time;uniform vec2 mouse;uniform vec2 resolution;
#define pi 3.141592653589793238462643383279#define pi_inv 0.318309886183790671537767526745#define pi2_inv 0.159154943091895335768883763372
vec2 complex_div(vec2 numerator, vec2 denominator){ return vec2(numerator.x*denominator.x + numerator.y*denominator.y, numerator.y*denominator.x - numerator.x*denominator.y)/ vec2(denominator.x*denominator.x + denominator.y*denominator.y);}
float sigmoid(float x){ return sin(x*.11)*exp(-x*x);}
float smoothcircle(vec2 uv, vec2 center, vec2 aspect, float radius, float sharpness){ return sigmoid((length((uv - center) * aspect) - radius) * sharpness);}
vec2 spiralzoom(vec2 domain, vec2 center, float n, float spiral_factor, float zoom_factor, vec2 pos){ vec2 uv = domain - center; float angle = atan(uv.y, uv.x); float d = length(uv);
return vec2(angle*n*pi2_inv + log(d)*spiral_factor, -log(d)*zoom_factor) + pos;}
vec2 mobius(vec2 domain, vec2 zero_pos, vec2 asymptote_pos){ return complex_div(domain - zero_pos, domain - asymptote_pos);}
float gear(vec2 domain, float phase, vec2 pos){ float angle = atan(domain.y - pos.y, domain.x - pos.x); float d = 0.2 + sin((angle + phase) * 10.)*0.;
return smoothcircle(domain, pos, vec2(1), d, 40.);}
float geartile(vec2 domain, float phase){ domain = fract(domain);
return gear(domain, -phase, vec2(-0.25,0.25)) + gear(domain, phase, vec2(-0.25,0.75)) + gear(domain, phase, vec2(1.25,0.25)) + gear(domain, -phase, vec2(1.25,0.75)) + gear(domain, -phase, vec2(0.25,-0.25)) + gear(domain, phase, vec2(0.75,-0.25)) + gear(domain, phase, vec2(0.25,1.25)) + gear(domain, -phase, vec2(0.75,1.25)) + gear(domain, phase, vec2(0.25,0.25)) + gear(domain, -phase, vec2(0.25,0.75)) + gear(domain, -phase, vec2(0.75,0.25)) + gear(domain, phase, vec2(0.75,0.75));}
void main(void){ vec2 uv = (gl_FragCoord.xy - .5*resolution) / resolution.x;
float phase = (time+10.)*0.5; float dist = 0.5; vec2 uv_bipolar = mobius(uv, vec2(-dist*0.5, 0.), vec2(dist*0.5, 0.)); uv_bipolar = spiralzoom(uv_bipolar, vec2(0.0), 5., -0.125*pi, 0.8, vec2(0.125,0.125)*phase*5.); uv_bipolar = vec2(-uv_bipolar.y,uv_bipolar.x); // 90° rotation
vec2 uv_spiral = spiralzoom(uv, vec2(0.5), 5., -0.125*pi, 0.8, vec2(-0.,0.25)*phase); vec2 uv_tilt = uv_spiral; float z = 1./(1.-uv_tilt.y)/(uv_tilt.y); uv_tilt = 0.5 + (uv_tilt - 0.5) * log(z);
float grid = geartile(uv_bipolar, -phase);
gl_FragColor = vec4(uv+vec2(0.5),0.0,1.0);
gl_FragColor = mix(vec4(0,0,1.0,0), gl_FragColor, 1.1+sin(uv_bipolar.y * pi * 2.0)); gl_FragColor += vec4(0.6*abs(uv_bipolar.x+uv_bipolar.y),0.8,1.0+(uv_bipolar.y * pi * 5.0),1.0)* -grid*500.0;}このコードは、複素数演算と極座標変換を利用して、**二重螺旋(Double Spiral)**のような視覚効果を生成する。
mobius()やspiralzoom()のような数学的な変換を適用し、歯車模様(geartile())を重ねることで、複雑なパターンを描画している。
コードの流れ
Section titled “コードの流れ”void main(void)
Section titled “void main(void)”1.座標の正規化
Section titled “1.座標の正規化”gl_FragCoord.xy(画素の座標)をresolution(画面解像度)で正規化し、画面中心を とする。
vec2 uv = (gl_FragCoord.xy - .5*resolution) / resolution.x;バイポーラ変換(Mobius変換)
Section titled “バイポーラ変換(Mobius変換)”mobius()関数を使用し、複素数除算で座標を変換する。zero_pos(極)とasymptote_pos(漸近線)を設定し、座標を変形。
vec2 uv_bipolar = mobius(uv, vec2(-dist*0.5, 0.), vec2(dist*0.5, 0.));スパイラル変換
Section titled “スパイラル変換”spiralzoom()を適用し、座標を極座標ベースのスパイラル形状に歪める。
uv_bipolar = spiralzoom(uv_bipolar, vec2(0.0), 5., -0.125*pi, 0.8, vec2(0.125,0.125)*phase*5.);座標の90度回転
Section titled “座標の90度回転”- を にすることで、座標を90°回転。
uv_bipolar = vec2(-uv_bipolar.y,uv_bipolar.x);もう一つのスパイラル変換
Section titled “もう一つのスパイラル変換”- もう一つの
spiralzoom()を適用し、異なるパターンを作成。
vec2 uv_spiral = spiralzoom(uv, vec2(0.5), 5., -0.125*pi, 0.8, vec2(-0.,0.25)*phase);座標のチルト変換
Section titled “座標のチルト変換”log(z)を使って、変換後の座標に非線形な歪みを与える。
vec2 uv_tilt = uv_spiral;float z = 1./(1.-uv_tilt.y)/(uv_tilt.y);uv_tilt = 0.5 + (uv_tilt - 0.5) * log(z);歯車パターン(geartile)適用
Section titled “歯車パターン(geartile)適用”geartile()で多数の歯車パターンを適用。
float grid = geartile(uv_bipolar, -phase);最終的な色の決定
Section titled “最終的な色の決定”- 青ベースのグラデーションを適用。
mix()を使い、スパイラルと歯車模様をブレンド。
gl_FragColor = vec4(uv+vec2(0.5),0.0,1.0);gl_FragColor = mix(vec4(0,0,1.0,0), gl_FragColor, 1.1+sin(uv_bipolar.y * pi * 2.0));gl_FragColor += vec4(0.6*abs(uv_bipolar.x+uv_bipolar.y),0.8,1.0+(uv_bipolar.y * pi * 5.0),1.0)* -grid*500.0;mobius()で座標を変形spiralzoom()で螺旋パターンを適用geartile()で歯車パターンを配置gl_FragColorで最終的な色を決定
結果として、バイポーラ変換・螺旋変換・歯車模様を組み合わせた、動的な二重螺旋のエフェクトが生まれる。