bloomcore · escribe y florece
wogl.io
#version 300 es
in vec2 p; void main(){ gl_Position=vec4(p,0.,1.); }
#version 300 es
precision highp float;
out vec4 frag;
uniform vec2 uRes;
uniform float uTime, uBloom, uSeed;
uniform sampler2D uTex;
uniform vec3 uGlow, uBg, uSpore, uPetal, uVine;
uniform int uSpores, uFbmOct, uBurstN;
uniform vec4 uBurst[6]; // xy=centro · z=nacimiento · w=semilla
float hash(vec2 p){ p=fract(p*vec2(123.34,456.21)); p+=dot(p,p+45.32); return fract(p.x*p.y); }
// Integer hash (PCG) on the float's bits: exact on every GPU, where sin() of a large argument is not.
uint pcg(uint v){ uint s=v*747796405u+2891336453u; uint w=((s>>((s>>28u)+4u))^s)*277803737u; return (w>>22u)^w; }
float hash1(float n){ return float(pcg(floatBitsToUint(n)))*(1.0/4294967295.0); }
float noise(vec2 p){ vec2 i=floor(p),f=fract(p);
float a=hash(i),b=hash(i+vec2(1,0)),c=hash(i+vec2(0,1)),d=hash(i+vec2(1,1));
vec2 u=f*f*(3.0-2.0*f); return mix(mix(a,b,u.x),mix(c,d,u.x),u.y); }
float fbm(vec2 p,int oct){ float v=0.0,a=0.55; for(int i=0;i<4;i++){ if(i>=oct) break; v+=a*noise(p); p=p*2.03+vec2(1.7,9.2); a*=0.5; } return v; }
vec3 wShoulder(vec3 c){
c = max(c, 0.0);
float p = max(c.r, max(c.g, c.b));
if (p <= 0.70) return c;
float s = 0.70 + 0.30 * (1.0 - exp(-(p - 0.70) / 0.30));
return c * (s / p);
}
void main(){
vec2 uv=gl_FragCoord.xy/uRes;
vec2 p=(gl_FragCoord.xy-0.5*uRes)/uRes.y;
float t=uTime;
float bloom=clamp(uBloom,0.0,1.0);
// ── jardín nocturno ──
vec3 col=mix(uBg*1.15, uBg*0.55, uv.y);
float fol=fbm(p*2.2+vec2(0.0,t*0.03), uFbmOct);
col+=uBg*0.7*pow(fol,2.0);
// ── polen bioluminiscente subiendo ──
for(int i=0;i<16;i++){ if(i>=uSpores) break;
float fi=float(i); vec2 rr=vec2(hash1(fi*3.1),hash1(fi*7.7));
float yy=fract(rr.y - t*(0.04+rr.x*0.05));
vec2 sp=vec2((rr.x-0.5)*2.0*(uRes.x/uRes.y),(yy-0.5)*1.05);
float d=length(p-sp);
col+=uSpore*(0.0005/(d*d+0.0004))*(0.4+0.6*sin(t*2.0+fi));
}
// ── enredaderas que crecen desde las esquinas ──
for(int v=0;v<2;v++){
float fv=float(v);
float bx=(v==0?-0.72:0.72);
float tipH=mix(-0.5,0.34,smoothstep(0.0,1.0,bloom));
float hh=(p.y+0.5)/(tipH+0.5+1e-3); float hc=clamp(hh,0.0,1.0);
float cx=bx*(1.0-hc*0.7)+sin(hc*8.0+fv*3.0+t*0.4)*0.05*hc;
float w=mix(0.013,0.002,hc);
float dx=p.x-cx;
float dseg=length(vec2(dx,(hh-hc)*(tipH+0.5)))-w;
float m=smoothstep(0.004,0.0,dseg)*step(hc,0.999);
col=mix(col, uVine*(0.5+0.6*hc), m);
// hojitas
float leaf=smoothstep(0.02,0.0,length(vec2(dx*1.6,(fract(hc*5.0)-0.5)*0.10)))*step(0.1,hc)*step(hc,0.95);
col=mix(col, uVine*1.2, leaf*0.5*m>0.0?leaf*0.4:0.0);
}
// ── flores de luz que amanecen del fondo · de atrás hacia adelante ──
for(int i=0;i<12;i++){
float fi=float(i);
float depth=1.0 - fi/11.0; // i=0 lejos · i=11 al frente
float rev=smoothstep((1.0-depth)-0.16,(1.0-depth)+0.16, bloom); // atrás amanece primero
if(rev<0.01) continue;
vec2 fc=vec2((hash1(fi*4.3+uSeed)-0.5)*1.28, (hash1(fi*9.1+uSeed)-0.5)*0.74);
fc.y+=sin(t*0.4+fi)*0.012; // respira (vivo)
float near=1.0-depth;
float r=mix(0.03,0.12, near); // lejos pequeñas · cerca grandes
float b=mix(0.26,1.0, near); // lejos tenues · cerca brillantes
vec3 fcol=mix(uPetal, uSpore, hash1(fi*2.0+uSeed));
float d=length(p-fc);
float halo=exp(-d*d/(r*r*2.2));
float core=smoothstep(r*0.5,0.0,d);
col=mix(col, fcol, core*0.85*b*rev); // núcleo de la flor
col+=fcol*halo*0.5*b*rev; // bokeh de jardín
}
// ── LA PALABRA (textura) · brota y florece ──
float sc=mix(0.62,1.0, smoothstep(0.0,1.0,bloom));
vec2 tp=p/sc;
float halfW=0.60; float availHalf=(uRes.x/uRes.y)*0.5*0.92; float fit=min(1.0,availHalf/halfW);
vec2 tuv=vec2(tp.x/(1.2*fit)+0.5, 0.5 - tp.y/(0.6*fit));
// halo neón
float glow=0.0;
for(int i=0;i<6;i++){ float a=6.2831*float(i)/6.0; glow+=texture(uTex,tuv+vec2(cos(a),sin(a))*0.014).a; }
col=mix(col, uGlow, clamp(glow/6.0,0.0,1.0)*0.55*bloom);
// texto (aparece al florecer)
vec4 tc=texture(uTex,tuv);
float ta=tc.a*smoothstep(0.0,0.28,bloom);
col=mix(col, tc.rgb, ta);
// rocío (brillo de borde)
float dew=clamp(texture(uTex,tuv+vec2(-0.006,0.009)).a - tc.a,0.0,1.0);
col+=dew*vec3(0.9,1.0,0.92)*0.3*ta;
// ── ráfagas de partículas al tocar / arrastrar ──
for(int b=0;b<6;b++){ if(b>=uBurstN) break;
vec4 B=uBurst[b]; float age=t-B.z;
if(age<0.0 || age>1.2) continue;
float fade=1.0-age/1.2;
for(int j=0;j<6;j++){
float a=6.2831*float(j)/6.0 + B.w*6.28;
float rr=age*0.55*(0.6+hash1(B.w*13.0+float(j)));
vec2 pp=B.xy+vec2(cos(a),sin(a))*rr+vec2(0.0,age*0.12);
float d=length(p-pp);
col+=uSpore*(0.0006/(d*d+0.0003))*fade;
}
}
// acabado suave
col*=mix(0.68,1.0, smoothstep(1.32,0.2,length(p)));
col+=(hash(gl_FragCoord.xy+fract(t))-0.5)*0.02;
frag=vec4(wShoulder(col),1.0);
}