← Daily shaders~/adventure-log/shaders/2026-10-14

Warm Light Behind Wet Glass

Warm Light Behind Wet GlassRaindrops slide down the glass, each one cupping the warm glow waiting inside. · Rain 18–21°C
Sourcesliding grid raindrops with trailing droplets acting as inverted lenses over drifting warm bokeh discs, fbm haze and fogged glass
2026-10-14.frag
precision mediump float;
uniform vec2 u_resolution;
uniform float u_time;

float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}
float noise(vec2 p){
  vec2 i=floor(p),f=fract(p);f=f*f*(3.0-2.0*f);
  return mix(mix(hash(i),hash(i+vec2(1.0,0.0)),f.x),mix(hash(i+vec2(0.0,1.0)),hash(i+vec2(1.0,1.0)),f.x),f.y);
}
float fbm(vec2 p){
  float v=0.0,a=0.5;
  for(int i=0;i<4;i++){v+=a*noise(p);p=p*2.03+vec2(1.7,9.2);a*=0.5;}
  return v;
}

vec3 scene(vec2 p){
  vec3 col=mix(vec3(0.30,0.36,0.44),vec3(0.56,0.59,0.64),smoothstep(-0.5,0.6,p.y));
  col+=(fbm(p*1.6+vec2(u_time*0.02,0.0))-0.5)*0.14;
  vec2 gc=p-vec2(0.12,-0.08);
  float g=exp(-dot(gc,gc)*4.5);
  col=mix(col,vec3(1.0,0.70,0.40),g*0.55*(0.92+0.08*sin(u_time*0.5)));
  for(int i=0;i<9;i++){
    float fi=float(i);
    vec2 c=vec2((hash(vec2(fi,1.3))-0.5)*1.3,(hash(vec2(fi,7.1))-0.5)*0.9);
    c+=0.04*vec2(sin(u_time*0.2+fi),cos(u_time*0.17+fi*1.3));
    float r=0.06+0.06*hash(vec2(fi,3.7));
    float d=length(p-c);
    float disk=1.0-smoothstep(r-0.02,r,d);
    float rim=smoothstep(r-0.035,r-0.005,d)*disk;
    float h=hash(vec2(fi,5.5));
    vec3 bc=mix(vec3(1.0,0.60,0.34),vec3(1.0,0.86,0.56),h);
    if(h<0.25) bc=vec3(0.55,0.76,0.80);
    col=mix(col,bc,disk*(0.26+0.16*rim)*(0.85+0.15*sin(u_time*0.4+fi*2.0)));
  }
  return col;
}

vec3 dropLayer(vec2 p,float t,vec2 g,float r){
  vec2 q=p*g;
  q.y+=t*0.25;
  vec2 id=floor(q);
  float n=hash(id);
  vec2 st=fract(q)-0.5;
  float tt=t+n*6.28;
  float y=-sin(tt+sin(tt+sin(tt)*0.5))*0.36;
  float x=(n-0.5)*0.6+sin(tt*0.7+n*10.0)*0.04;
  vec2 d=(st-vec2(x,y))/g;
  float m=1.0-smoothstep(r*0.6,r,length(d));
  float dy=st.y-y;
  float trail=smoothstep(0.0,0.08,dy)*(1.0-smoothstep(0.05,0.45,dy));
  vec2 td=vec2(st.x-x,fract(st.y*5.0)-0.5)/vec2(g.x,g.y*5.0);
  float rt=r*0.45;
  float tm=(1.0-smoothstep(rt*0.55,rt,length(td)))*trail*step(0.3,hash(id+3.1));
  return vec3(d*m+td*tm,max(m,tm));
}

void main(){
  vec2 p=(gl_FragCoord.xy-0.5*u_resolution)/u_resolution.y;
  float t=u_time*0.35;
  vec3 a=dropLayer(p,t,vec2(5.0,2.5),0.035);
  vec3 b=dropLayer(p+vec2(0.37,0.11),t*0.8+3.0,vec2(8.0,4.0),0.024);
  vec2 off=a.xy+b.xy;
  float mask=max(a.z,b.z);
  vec3 col=scene(p-off*6.0);
  vec3 fogc=vec3(0.62,0.66,0.71);
  col=mix(col,fogc,0.24*(1.0-mask));
  float e=length(off)/0.035;
  col*=1.0-0.22*mask*smoothstep(0.45,1.0,e);
  vec2 nd=normalize(off+vec2(0.0001));
  col+=0.22*mask*smoothstep(0.55,1.0,dot(nd,vec2(-0.7,0.7)))*smoothstep(0.25,0.75,e);
  col+=0.04*mask*vec3(1.0,0.85,0.6);
  vec2 v=p*vec2(0.8,1.0);
  col*=1.0-0.35*dot(v,v);
  col=clamp(col,0.0,0.95);
  gl_FragColor=vec4(col,1.0);
}