precision highp float; uniform vec2 resolution; uniform vec2 mouse; uniform float time; uniform sampler2D backbuffer; // ------------------------------------------------------------------------------------ // Original Character By MikkaBouzu : https://twitter.com/mikkabouzu777 // ------------------------------------------------------------------------------------ #define saturate(x) clamp(x, 0.0, 1.0) #define MAX_MARCH 256 #define MAX_DIST 100. const float EPS = 1e-3; const float EPS_N = 1e-4; const float OFFSET = EPS * 10.0; #define M_PI 3.1415926 #define M_PI2 6.2831852 #define RAD90 (M_PI * 0.5) struct surface { float dist; vec4 albedo; int count; bool isHit; }; // Surface Data Define #define SURF_NOHIT(d) (surface(d, vec4(0), 0, false)) #define SURF_BLACK(d) (surface(d, vec4(0,0,0,1), 0, true)) #define SURF_FACE(d) (surface(d, vec4(1,0.7,0.6,1), 0, true)) #define SURF_MOUSE(d) (surface(d, vec4(1,0,0.1,1), 0, true)) #define SURF_CHEEP(d) (surface(d, vec4(1,0.3,0.4,1), 0, true)) vec3 hsv2rgb( in vec3 c ) { vec3 rgb = clamp( abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0 ); rgb = rgb*rgb*(3.0-2.0*rgb); // cubic smoothing return c.z * mix( vec3(1.0), rgb, c.y); } #define M_PI03 1.04719 #define M_PI06 2.09439 vec3 sinebow(float h) { vec3 r = sin((.5-h)*M_PI + vec3(0,M_PI03,M_PI06)); return r*r; } // 1 out, 3 in... float hash13(vec3 p3) { p3 = fract(p3 * .1031); p3 += dot(p3, p3.zyx + 31.32); return fract((p3.x + p3.y) * p3.z); } float noise(vec3 st) { vec3 ip = floor(st); vec3 fp = smoothstep(vec3(0.), vec3(1.), fract(st)); vec4 a = vec4(hash13(ip+vec3(0.)),hash13(ip+vec3(1.,0.,0.)),hash13(ip+vec3(0.,1.,0.)),hash13(ip+vec3(1.,1.,0.))); vec4 b = vec4(hash13(ip+vec3(0.,0.,1.)),hash13(ip+vec3(1.,0.,1.)),hash13(ip+vec3(0.,1.,1.)),hash13(ip+vec3(1.,1.,1.))); a = mix(a, b, fp.z); a.xy = mix(a.xy, a.zw, fp.y); return mix(a.x, a.y, fp.x); } mat3 m = mat3( 0.00, 0.80, 0.60, -0.80, 0.36, -0.48, -0.60, -0.48, 0.64 ); float fbm( vec3 p ) { float f; f = 0.5000*noise( p ); p = m*p*2.02; f += 0.2500*noise( p ); p = m*p*2.03; f += 0.1250*noise( p ); return f; } ///////////////////////////////////////////////////////////////////////////////////////////////// // Basic Distance function ///////////////////////////////////////////////////////////////////////////////////////////////// float sdRoundBox(vec3 p, vec3 size, float r) { return length(max(abs(p) - size * 0.5, 0.0)) - r; } float sdCapsule(vec3 p, vec3 a, vec3 b, float r) { vec3 pa = p - a, ba = b - a; float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0); return length(pa - ba*h) - r; } float sdEllipsoid( vec3 p, vec3 r ) { float k0 = length(p/r); float k1 = length(p/(r*r)); return k0*(k0-1.0)/k1; } float sdCappedTorus(in vec3 p, in vec2 sc, in float ra, in float rb) { p.x = abs(p.x); float k = (sc.y*p.x>sc.x*p.y) ? dot(p.xy,sc) : length(p.xy); return sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb; } float sdRoundedCylinder( vec3 p, float ra, float rb, float h ) { vec2 d = vec2( length(p.xz)-2.0*ra+rb, abs(p.y) - h ); return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rb; } vec3 rotate(vec3 p, float angle, vec3 axis) { vec3 a = normalize(axis); float s = sin(angle); float c = cos(angle); float r = 1.0 - c; mat3 m = mat3( a.x * a.x * r + c, a.y * a.x * r + a.z * s, a.z * a.x * r - a.y * s, a.x * a.y * r - a.z * s, a.y * a.y * r + c, a.z * a.y * r + a.x * s, a.x * a.z * r + a.y * s, a.y * a.z * r - a.x * s, a.z * a.z * r + c ); return m * p; } // Union, Subtraction, SmoothUnion (distance, Material) surface opU(surface d1, surface d2) { if(d1.dist < d2.dist){ return d1; } else { return d2; } } float opU( float d1, float d2 ) { return min(d1,d2); } surface opS( surface d1, surface d2 ) { if(-d1.dist > d2.dist){ d1.dist = -d1.dist; return d1; } else { return d2; } } surface opSU( surface d1, surface d2, float k ) { float h = clamp( 0.5 + 0.5*(d2.dist - d1.dist)/k, 0.0, 1.0 ); float d = mix( d2.dist, d1.dist, h ) - k*h*(1.0-h); vec4 albedo = mix( d2.albedo, d1.albedo, h ); return surface(d, albedo, d1.count, true); } float smin( float d1, float d2, float k ) { float h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 ); return mix( d2, d1, h ) - k*h*(1.0-h); } //https://www.shadertoy.com/view/NdS3Dh //SmoothSymmetricPolarMod aka smoothRot // //s repetitions //m smoothness (0-1) //c correction (0-1) //d object displace from center // vec2 smoothRot(vec2 p,float s,float m,float c,float d){ s*=0.5; float k=length(p); float x=asin(sin(atan(p.x,p.y)*s)*(1.0-m))*k; float ds=k*s; float y=mix(ds,2.0*ds-sqrt(x*x+ds*ds),c); return vec2(x/s,y/s-d); } ///////////////////////////////////////////////////////////////////////////////////////////////// // Mikka Boze Distance Function ///////////////////////////////////////////////////////////////////////////////////////////////// float sdEar(vec3 p) { p = rotate(p, RAD90+0.25, vec3(0,0,1)); return sdCappedTorus(p + vec3(0.05, 0.175, 0), vec2(sin(0.7),cos(0.7)), 0.03, 0.01); } #define EYE_SPACE 0.04 vec3 opBendXY(vec3 p, float k) { float c = cos(k*p.x); float s = sin(k*p.x); mat2 m = mat2(c,-s,s,c); return vec3(m*p.xy,p.z); } vec3 opBendXZ(vec3 p, float k) { float c = cos(k*p.x); float s = sin(k*p.x); mat2 m = mat2(c,-s,s,c); vec2 xz = m*p.xz; return vec3(xz.x, p.y, xz.y); } float sdMouse(vec3 p, float ms) { vec3 q = opBendXY(p, 2.0); ms += 0.00001; return sdEllipsoid(q - vec3(0,0,0.2), vec3(0.035, 0.01 * ms,0.05 * ms)); } float sdCheep(vec3 p) { const float x = 0.05; const float z = -0.175; const float r = 0.0045; const float rb1 = 100.; p = rotate(p, M_PI * -0.6 * (p.x - x), vec3(-0.2,0.8,0)); float d = sdCapsule(opBendXY(p + vec3(x, -0.01, z), rb1), vec3(-0.005,0.0,0.0), vec3(0.005, 0., 0.001), r); float d1 = sdCapsule(opBendXY(p + vec3(x+0.01, -0.01, z), 200.0), vec3(-0.0026,0.0,0), vec3(0.0026, 0., 0), r); float d2 = sdCapsule(opBendXY(p + vec3(x+0.019, -0.015, z), -rb1), vec3(-0.01,0.0,-0.01), vec3(0.0045, 0., 0.0), r); return opU(opU(d, d1), d2); } float sdEyeBrow(vec3 p) { const float x = 0.05; p = opBendXZ(p + vec3(0.02,0,-0.02), -6.5); return sdRoundBox(p + vec3(0.005, -0.14,-0.11), vec3(0.003,0.0025,0.05), 0.001); } surface sdBoze(vec3 p, vec3 sc, float ms) { surface result = SURF_NOHIT(1e5); float minsc = min(sc.x, min(sc.y, sc.z)); p /= sc; // head float d = sdCapsule(p, vec3(0,0.05,0), vec3(0, 0.11, 0), 0.125); float d1 = sdRoundedCylinder(p + vec3(0,0.025,0), 0.095, 0.05, 0.0); d = smin(d, d1, 0.1); vec3 mxp = vec3(-abs(p.x), p.yz); // ear float d2 = sdEar(mxp); d = opU(d, d2); surface head = SURF_FACE(d); // eye float d4 = sdCapsule(mxp, vec3(-EYE_SPACE, 0.06, 0.13), vec3(-EYE_SPACE, 0.08, 0.125), 0.0175); surface eye = SURF_BLACK(d4); // mouse float d6 = sdMouse(p, ms); surface mouse = SURF_MOUSE(d6); // cheep float d7 = sdCheep(mxp); surface cheep = SURF_CHEEP(d7); // eyebrows float d9 = sdEyeBrow(mxp); eye.dist = opU(eye.dist, d9); // integration mouse = opU(eye, mouse); result = opS(mouse, head); result = opU(cheep, result); result.dist *= minsc; return result; } ///////////////////////////////////////////////////////////////////////////////////////////////// // End of Mikka Boze ///////////////////////////////////////////////////////////////////////////////////////////////// // https://iquilezles.org/articles/mandelbulb/ surface map(vec3 p) { surface result = SURF_NOHIT(1e5); float ms = sin(time) * 0.5 + 0.5; vec3 z = p; float dz = 1.0; // square of the magnitude of z float m2 = dot(z,z); vec4 orbitTrap = vec4(abs(z), m2); //float deg = iTime*-0.5; float deg=-time*0.15; float d = 1.; float d2 = 0.; float repetitions=7.0; float smoothness=0.1; float correction=0.1; float displace= 0.5; p = rotate(p+vec3(0,0.1,0), RAD90+time*2.1, vec3(0.5, 0, 0.5)); for(int i=0; i<4; i++) { // extract sperical coordinate float r = length(z); float phi = deg*acos(z.y/r); float theta = deg*atan(z.x, z.z); // z = z^p+c z = pow(r,deg) * vec3(sin(phi)*sin(theta), cos(phi), sin(phi)*cos(theta)) + p; vec3 z2 = z; z2.z = abs(z2.z); z2.xy = smoothRot(z.xy, repetitions, smoothness, correction, displace); surface boze = sdBoze((z2) - vec3(0,0.1,0), vec3(3.), ms); result = opU(result, boze); } return result; } vec3 norm(in vec3 position) { // https://www.shadertoy.com/view/XltyRf vec4 n = vec4(0); for (int i = 0 ; i < 4 ; i++) { vec4 s = vec4(position, 0); s[i] += 0.001; n[i] = map(s.xyz).dist; } return normalize(n.xyz-n.w); } surface traceRay(in vec3 origin, in vec3 direction, float dist, out vec3 pos) { float t = 0.0; pos = origin; int count = 0; surface hit; float d; for (int i = 0; i < MAX_MARCH; i++) { hit = map(pos); d = hit.dist; if (d <= EPS || d >= MAX_DIST) { break; } t += d; pos = origin + direction * t; count++; } hit.dist = t; hit.count = count; pos = origin + direction * t; if(hit.isHit) { // Lighting vec3 normal = norm(pos); vec3 lightDir = normalize(vec3(cos(time), 1, sin(time))); vec3 lightColor = vec3(1.5); float NoL = saturate(dot(normal, lightDir)); vec3 ambientColor = vec3(0.1); hit.albedo.rgb *= NoL * lightColor + ambientColor; } if(d <= EPS){ hit.isHit = true; return hit; }else{ hit.isHit = false; return hit; } } vec3 render(vec3 p, vec3 ray, vec2 uv) { vec3 pos; surface mat = traceRay(p, ray, 0., pos); vec3 col = vec3(0,0,0); //vec3 sky = vec3(0.3); vec3 sky = sinebow(fbm(vec3(uv * 0.01, 0))*5.5+(time * M_PI2 * 0.5)*0.25)*0.5+0.25; col = mat.isHit ? mat.albedo.rgb : sky; return col; } mat3 camera(vec3 ro, vec3 ta, float cr ) { vec3 cw = normalize(ta - ro); vec3 cp = vec3(sin(cr), cos(cr),0.); vec3 cu = normalize( cross(cw,cp) ); vec3 cv = normalize( cross(cu,cw) ); return mat3( cu, cv, cw ); } void main() { vec2 r=resolution,p=(gl_FragCoord.xy*2.-r)/min(r.x,r.y); const float l = 3.; float t = time + RAD90; vec3 ro = vec3(cos(t) * l, 0.05, sin(t) * l); //vec3 ro = vec3(0, 0.05, 0.8); vec3 ta = vec3(0, -0.25, 0); mat3 c = camera(ro, ta, 0.0); vec3 ray = c * normalize(vec3(p, 1.5)); vec3 col = render(ro, ray, gl_FragCoord.xy); // Output to screen gl_FragColor = vec4(col,1.0); }