65 lines
3.4 KiB
TypeScript
65 lines
3.4 KiB
TypeScript
// GLSL for the particle sculpture
|
|
export const noiseGLSL = `
|
|
vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}
|
|
vec4 mod289(vec4 x){return x-floor(x*(1.0/289.0))*289.0;}
|
|
vec4 permute(vec4 x){return mod289(((x*34.0)+1.0)*x);}
|
|
vec4 taylorInvSqrt(vec4 r){return 1.79284291400159-0.85373472095314*r;}
|
|
float snoise(vec3 v){
|
|
const vec2 C=vec2(1.0/6.0,1.0/3.0); const vec4 D=vec4(0.0,0.5,1.0,2.0);
|
|
vec3 i=floor(v+dot(v,C.yyy)); vec3 x0=v-i+dot(i,C.xxx);
|
|
vec3 g=step(x0.yzx,x0.xyz); vec3 l=1.0-g; vec3 i1=min(g.xyz,l.zxy); vec3 i2=max(g.xyz,l.zxy);
|
|
vec3 x1=x0-i1+C.xxx; vec3 x2=x0-i2+C.yyy; vec3 x3=x0-D.yyy;
|
|
i=mod289(i);
|
|
vec4 p=permute(permute(permute(i.z+vec4(0.0,i1.z,i2.z,1.0))+i.y+vec4(0.0,i1.y,i2.y,1.0))+i.x+vec4(0.0,i1.x,i2.x,1.0));
|
|
float n_=0.142857142857; vec3 ns=n_*D.wyz-D.xzx;
|
|
vec4 j=p-49.0*floor(p*ns.z*ns.z); vec4 x_=floor(j*ns.z); vec4 y_=floor(j-7.0*x_);
|
|
vec4 x=x_*ns.x+ns.yyyy; vec4 y=y_*ns.x+ns.yyyy; vec4 h=1.0-abs(x)-abs(y);
|
|
vec4 b0=vec4(x.xy,y.xy); vec4 b1=vec4(x.zw,y.zw);
|
|
vec4 s0=floor(b0)*2.0+1.0; vec4 s1=floor(b1)*2.0+1.0; vec4 sh=-step(h,vec4(0.0));
|
|
vec4 a0=b0.xzyw+s0.xzyw*sh.xxyy; vec4 a1=b1.xzyw+s1.xzyw*sh.zzww;
|
|
vec3 p0=vec3(a0.xy,h.x); vec3 p1=vec3(a0.zw,h.y); vec3 p2=vec3(a1.xy,h.z); vec3 p3=vec3(a1.zw,h.w);
|
|
vec4 norm=taylorInvSqrt(vec4(dot(p0,p0),dot(p1,p1),dot(p2,p2),dot(p3,p3)));
|
|
p0*=norm.x;p1*=norm.y;p2*=norm.z;p3*=norm.w;
|
|
vec4 m=max(0.6-vec4(dot(x0,x0),dot(x1,x1),dot(x2,x2),dot(x3,x3)),0.0); m=m*m;
|
|
return 42.0*dot(m*m,vec4(dot(p0,x0),dot(p1,x1),dot(p2,x2),dot(p3,x3)));
|
|
}`;
|
|
|
|
export const vert = noiseGLSL + `
|
|
attribute vec3 aP0; attribute vec3 aP1; attribute vec3 aP2; attribute vec3 aP3; attribute vec3 aPH; attribute vec3 aPH2; attribute float aRand;
|
|
uniform float uProgress; uniform float uTime; uniform float uPR; uniform vec3 uMouse; uniform float uMouseOn; uniform float uIntro; uniform float uDim; uniform float uHover; uniform float uSwap;
|
|
varying float vA; varying float vHeat;
|
|
void main(){
|
|
float p=clamp(uProgress,0.0,3.0);
|
|
float s01=smoothstep(0.0,1.0,p), s12=smoothstep(1.0,2.0,p), s23=smoothstep(2.0,3.0,p);
|
|
vec3 pos = aP0*(1.0-s01) + aP1*(s01-s12) + aP2*(s12-s23) + aP3*s23;
|
|
float f=fract(p); float tr = (p>=3.0)?0.0:f*(1.0-f)*4.0; // 0 at rest, 1 mid-morph
|
|
// hover: the sculpture becomes the project under the cursor
|
|
vec3 hp = mix(aPH2, aPH, uSwap);
|
|
pos = mix(pos, hp, uHover);
|
|
tr = tr*(1.0-uHover) + max(uHover*(1.0-uHover)*4.0, uSwap*(1.0-uSwap)*4.0)*0.7;
|
|
vec3 nv = vec3(snoise(pos*0.45+uTime*0.12), snoise(pos*0.45+vec3(13.7)+uTime*0.12), snoise(pos*0.45+vec3(71.2)+uTime*0.12));
|
|
pos += nv*(0.07*(1.0-uHover*0.85) + tr*(2.2+aRand*2.0));
|
|
// intro: particles fall in from a scattered cloud
|
|
vec3 spread = (aRand-0.5)*vec3(30.0,20.0,30.0) + nv*6.0;
|
|
pos = mix(spread, pos, uIntro);
|
|
// mouse repulsion
|
|
vec3 d = pos - uMouse; float dist=length(d);
|
|
float rep = smoothstep(3.2,0.0,dist)*uMouseOn;
|
|
pos += (d/max(dist,0.001))*rep*1.6;
|
|
vec4 mv = modelViewMatrix*vec4(pos,1.0);
|
|
gl_Position = projectionMatrix*mv;
|
|
float size = (0.8+aRand*1.4)*uPR*(1.0+tr*1.0+rep*1.4);
|
|
gl_PointSize = min(size*(200.0/-mv.z), 9.0*uPR);
|
|
vA = (0.35+0.55*aRand)*uIntro*uDim*(1.0-tr*0.45);
|
|
vHeat = clamp(tr*0.9+rep+aRand*0.25,0.0,1.0);
|
|
}`;
|
|
export const frag = `
|
|
uniform vec3 uC1; uniform vec3 uC2; varying float vA; varying float vHeat;
|
|
void main(){
|
|
vec2 uv=gl_PointCoord-0.5; float d=length(uv); if(d>0.5) discard;
|
|
float a=smoothstep(0.5,0.12,d);
|
|
vec3 c=mix(uC1,uC2,vHeat);
|
|
gl_FragColor=vec4(c, a*vA);
|
|
}`;
|
|
|