#define GLSLIFY 1 //Lava lamp. uniform float time; uniform float seed; uniform vec2 resolution; float noise3D(vec3 p){ return fract(sin(dot(p,vec3(12.9898,78.233,128.852)))*43758.5453)*2.-1.; } float simplex3D(vec3 p){ float f3=1./3.; float s=(p.x+p.y+p.z)*f3; int i=int(floor(p.x+s)); int j=int(floor(p.y+s)); int k=int(floor(p.z+s)); float g3=1./6.; float t=float((i+j+k))*g3; float x0=float(i)-t; float y0=float(j)-t; float z0=float(k)-t; x0=p.x-x0; y0=p.y-y0; z0=p.z-z0; int i1,j1,k1; int i2,j2,k2; if(x0>=y0) { if(y0>=z0){i1=1;j1=0;k1=0;i2=1;j2=1;k2=0;}// X Y Z order else if(x0>=z0){i1=1;j1=0;k1=0;i2=1;j2=0;k2=1;}// X Z Y order else{i1=0;j1=0;k1=1;i2=1;j2=0;k2=1;}// Z X Z order } else { if(y0<z0){i1=0;j1=0;k1=1;i2=0;j2=1;k2=1;}// Z Y X order else if(x0<z0){i1=0;j1=1;k1=0;i2=0;j2=1;k2=1;}// Y Z X order else{i1=0;j1=1;k1=0;i2=1;j2=1;k2=0;}// Y X Z order } float x1=x0-float(i1)+g3; float y1=y0-float(j1)+g3; float z1=z0-float(k1)+g3; float x2=x0-float(i2)+2.*g3; float y2=y0-float(j2)+2.*g3; float z2=z0-float(k2)+2.*g3; float x3=x0-1.+3.*g3; float y3=y0-1.+3.*g3; float z3=z0-1.+3.*g3; vec3 ijk0=vec3(i,j,k); vec3 ijk1=vec3(i+i1,j+j1,k+k1); vec3 ijk2=vec3(i+i2,j+j2,k+k2); vec3 ijk3=vec3(i+1,j+1,k+1); vec3 gr0=normalize(vec3(noise3D(ijk0),noise3D(ijk0*2.01),noise3D(ijk0*2.02))); vec3 gr1=normalize(vec3(noise3D(ijk1),noise3D(ijk1*2.01),noise3D(ijk1*2.02))); vec3 gr2=normalize(vec3(noise3D(ijk2),noise3D(ijk2*2.01),noise3D(ijk2*2.02))); vec3 gr3=normalize(vec3(noise3D(ijk3),noise3D(ijk3*2.01),noise3D(ijk3*2.02))); float n0=0.; float n1=0.; float n2=0.; float n3=0.; float t0=.5-x0*x0-y0*y0-z0*z0; if(t0>=0.) { t0*=t0; n0=t0*t0*dot(gr0,vec3(x0,y0,z0)); } float t1=.5-x1*x1-y1*y1-z1*z1; if(t1>=0.) { t1*=t1; n1=t1*t1*dot(gr1,vec3(x1,y1,z1)); } float t2=.5-x2*x2-y2*y2-z2*z2; if(t2>=0.) { t2*=t2; n2=t2*t2*dot(gr2,vec3(x2,y2,z2)); } float t3=.5-x3*x3-y3*y3-z3*z3; if(t3>=0.) { t3*=t3; n3=t3*t3*dot(gr3,vec3(x3,y3,z3)); } return 96.*(n0+n1+n2+n3); } /* Sphere - exact (https://www.shadertoy.com/view/Xds3zN) */ float sdSphere(vec3 p,float s) { return length(p)-s; } float opSmoothUnion(float d1,float d2,float k) { float h=clamp(.5+.5*(d2-d1)/k,0.,1.); return mix(d2,d1,h)-k*h*(1.-h); } #define MAX_DIST 3. #define CLOSE_ENOUGH.001 #define K.2 const vec3 liquidColor=vec3(.1,0.,.17); const vec3 hotColor=vec3(1.,1.,0.); const vec3 waxColor=vec3(1.,0.,0); const float blobRate=.2; const float blobFreq=3.; const float blobAmp=.02; const int blobCount=5; const float blobScaleVariance=.05; const float moveRate=.1; struct ray{ vec3 o; vec3 d; }; struct hit{ float sdf; float heat; vec3 col; }; struct light{ vec3 d; float i; }; float sdBlob(vec3 p,float s,float u){ p+=simplex3D(vec3(p.x*blobFreq+time*blobRate*.237128+u*.24184,p.y*blobFreq+time*blobRate*.214717+u*-.124918,p.z*blobFreq+time*blobRate*.187461+u*.125817))*blobAmp; return sdSphere(p,s); } float sdScene(vec3 p){ float d=float(MAX_DIST); float bd=0.,bm=float(blobCount-1); float ix,is,fi; vec3 nx=vec3(sin(time*moveRate*.01489198)+seed*24.1581), ny=vec3(sin(time*moveRate*.01612878)-seed*15.15918), nz=vec3(sin(time*moveRate*.011232245)+seed*51.1491), ns=vec3(sin(time*moveRate*.0070712)-seed*14.187), center; vec3 id; for(int i=0;i<blobCount;++i){ fi=float(i); id=vec3(i*16,i*32,i*25); ix=(fi/bm)-.5; center=vec3( simplex3D(nx+id*13.1384)*.35+sin(id.x*11.418+time*moveRate)*.15, simplex3D(ny+id*10.11424)*.16+sin(id.y*4.127-fi*14.19+time*moveRate)*.28, 1.+simplex3D(nz+id*12.35172)*.02+sin(id.z*1.1487+time*moveRate)*.02 ); bd=sdBlob( center-p, .1+simplex3D(ns+id)*blobScaleVariance, fi*5.13816 ); d=opSmoothUnion(bd,d,K); } return d; } hit scene(vec3 p){ float sd=sdScene(p); float heat=pow(max(-sd,0.),.2); vec3 col=mix(waxColor,hotColor,heat); return hit(sd,heat,col); } //from iq https://iquilezles.org/articles/normalsSDF vec3 calcNormal(in vec3 p){ const vec2 k=vec2(1,-1); return normalize(k.xyy*sdScene(p+k.xyy*CLOSE_ENOUGH)+ k.yyx*sdScene(p+k.yyx*CLOSE_ENOUGH)+ k.yxy*sdScene(p+k.yxy*CLOSE_ENOUGH)+ k.xxx*sdScene(p+k.xxx*CLOSE_ENOUGH)); } void main(){ vec2 uv=gl_FragCoord.xy/resolution.xy; //normalize uv uv-=vec2(.5); uv*=min(vec2(resolution.x/resolution.y,1.),vec2(1.,resolution.y/resolution.x)); //water effect (sorta) //uv+=vec2(noise(vec3(uv*3.,time*.28257))*.01,noise(vec3(uv*3.,time*.11248))*.01); light l=light(normalize(vec3(1.,1.,1.)),1.); ray r=ray(vec3(uv,0.),normalize(vec3(uv,4.))); float d=0.; float b=0.; vec3 n=vec3(0.); hit h; float minSdf=100.; while(d<MAX_DIST){ vec3 rp=r.o+r.d*d; h=scene(rp); minSdf=min(minSdf,h.sdf); if(h.sdf<CLOSE_ENOUGH){ n=calcNormal(rp); break;//h and n remains } d+=max(rp.z,CLOSE_ENOUGH); } vec3 color=vec3(0.); if(d>MAX_DIST){ float radiantHeat=max(1.-pow(minSdf,.2),0.); color=liquidColor; color=mix(color,waxColor,-uv.y*.3-pow(abs(uv.x),4.)); color=mix(color,waxColor,pow(radiantHeat,1.4)); }else{ color=h.col; //color=mix(color,waxColor,(1.-max(dot(l.d,n),0.))*.3);//shadows } gl_FragColor=vec4(color,1.); }