Skip to content

Instantly share code, notes, and snippets.

@artemuzz
Created April 21, 2020 13:36
Show Gist options
  • Save artemuzz/b0a533b67923a0f96462f4ec618f58b4 to your computer and use it in GitHub Desktop.
Save artemuzz/b0a533b67923a0f96462f4ec618f58b4 to your computer and use it in GitHub Desktop.
Mechanic Polar Dream
<!-- https://github.com/halvves/shader-doodle -->
<!-- https://www.osar.fr/notes/logspherical/ -->
<shader-doodle>
<script type="x-shader/x-fragment">
precision mediump float;
#define MAX_STEPS 150.
#define MAX_DIST 45.
#define MIN_DIST .001
#define PI 3.14159
#define PI2 6.28318
// Change to 2 to for antialiasing
#define AA 1
#define ZERO 0
mat2 r2(float a){
float c = cos(a); float s = sin(a);
return mat2(c, s, -s, c);
}
vec3 hsv2rgb( in vec3 c ) {
vec3 rgb = clamp(abs(mod(c.x*6.+vec3(0.,4.,2.),6.)-3.)-1., 0., 1.);
return c.z * mix(vec3(1.), rgb, c.y);
}
vec3 get_mouse(vec3 ro) {
float x = -(u_mousedrag.y / u_resolution.y * 1. - .5) * PI;
float y = -(u_mousedrag.x / u_resolution.x * 1. - .5) * PI;
float z = 0.0;
ro.zy *= r2(x);
ro.xz *= r2(y);
return ro;
}
float sdTorus( vec3 p, vec2 t ) {
p.xy *= r2(PI*4.5);
p.yz *= r2(PI*4.5);
vec2 q = vec2(length(p.xz)-t.x,p.y);
return length(q)-t.y;
}
float sdBox( vec3 p, vec3 b ) {
vec3 q = abs(p) - b;
return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0);
}
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);
}
float shorten = 1.16;
float density = 10.;
vec4 map(in vec3 p) {
float thickness = 0.035;
float lpscale = floor(density)/PI;
vec2 res = vec2(100.,0.);
// forward log-spherical map
float r = length(p);
p = vec3(log(r), acos(p.z / length(p)), atan(p.y, p.x));
// scaling factor to compensate for pinching at the poles
float xshrink = 1.0/(abs(p.y-PI)) + 1.0/(abs(p.y)) - 1.0/PI;
// fit in the ]-pi,pi] interval
p *= lpscale;
p.x -= u_time *.35;
p.z += u_time *.45;
// tile coordinates
vec3 pi = floor((p + 1.)/2.);
p = mod(p+1.,2.) - 1.;
p.x *= xshrink;
float pole = length(p.xz) - thickness;
pole = min(length(p.yx) - thickness, pole);
if(pole<res.x) res = vec2(pole,3.);
p.xz *= r2(u_time*.5);
float ret = sdBox( abs(p)-vec3(0.,.5,0.), vec3(.2,.01,.2) );
ret = min(sdBox( abs(p)-vec3(0.,.5,0.), vec3(.2,.2,.01) ),ret);
ret = min(sdBox( abs(p)-vec3(0.,.5,0.), vec3(.01,.2,.2) ),ret);
if(ret<res.x) res = vec2(ret,1.);
float rings = sdTorus( p.yzx, vec2(.5,thickness) );
rings = min(sdTorus( p.zxy, vec2(.5,thickness) ),rings);
if(rings<res.x) res = vec2(rings,2.);
// compensate for the scaling that's been applied
float mul = r/lpscale/xshrink;
float d = res.x * mul / shorten;
return vec4(d,res.y, pi.xz);
}
vec3 get_normal(in vec3 p) {
float d = map(p).x;
vec2 e = vec2(.01,.0);
vec3 n = d - vec3(
map(p-e.xyy).x,
map(p-e.yxy).x,
map(p-e.yyx).x
);
return normalize(n);
}
vec4 get_ray( in vec3 ro, in vec3 rd ) {
float depth = 0.;
float mate = 0.;
float m = 0.;
vec2 bi = vec2(3.);
for (float i = 0.; i<MAX_STEPS;i++) {
vec3 pos = ro + depth * rd;
vec4 dist = map(pos);
mate = dist.y;
bi = dist.zw;
if(dist.x<.0001*depth) break;
depth += abs(dist.x*.65); // hate this but helps edge distortions
if(depth>MAX_DIST) {
depth = MAX_DIST;
break;
}
}
return vec4(depth,mate,bi);
}
float get_diff(vec3 p, vec3 lpos) {
vec3 l = normalize(lpos-p);
vec3 n = get_normal(p);
float dif = clamp(dot(n,l),0. , 1.);
float shadow = get_ray(p + n * MIN_DIST * 2., l).x;
if(shadow < length(p - lpos)) {
dif *= .1;
}
return dif;
}
vec3 get_color(float m, vec2 bi){
vec3 mate = vec3(.2);
if(m==1.) {
if(mod(bi.y,2.)<.1){
mate = hsv2rgb(vec3(.25+bi.x*.1,1.,.5));
}else{
mate = hsv2rgb(vec3(.5+bi.x*.1,1.,.5));
}
}
if(m ==2.) mate = hsv2rgb(vec3(bi.x*.1,1.,.5));
if(m ==3.) mate = vec3(1.1,1.3,1.3);
return mate;
}
vec3 render( in vec3 ro, in vec3 rd, in vec2 uv) {
vec3 color = vec3(0.0);
vec3 fadeColor = vec3(.1,.15,.20);
vec4 ray = get_ray(ro, rd);
float t = ray.x;
vec2 bi = ray.zw;
vec3 lcolor, dcolor, ccolor;
if(t<MAX_DIST) {
vec3 p = ro + t * rd;
vec3 tint = get_color(ray.y,ray.zw);
lcolor = vec3(.4,.4,.5);
dcolor = vec3(.4,.3,.4);
ccolor = vec3(.3,.3,.28);
vec3 lpos1 = vec3(-.5, 13.45, 3.0);
vec3 lpos2 = vec3(-1.5, 12.21, .1);
vec3 lpos3 = vec3(12.5, -11., -1.5);
vec3 diff1 = dcolor * get_diff(p, lpos1);
vec3 diff2 = lcolor * get_diff(p, lpos2);
vec3 diff3 = ccolor * get_diff(p, lpos3);
vec3 diff = diff1 + diff2 + diff3;
color += tint * diff;
}
//iq - saw it in a tutorial once
color = mix( color, fadeColor, 1.-exp(-0.005*t*t*t));
return pow(color, vec3(0.4545));
}
vec3 ray( in vec3 ro, in vec3 lp, in vec2 uv ) {
vec3 cf = normalize(lp-ro);
vec3 cp = vec3(0.,1.,0.);
vec3 cr = normalize(cross(cp, cf));
vec3 cu = normalize(cross(cf, cr));
vec3 c = ro + cf * .87;
vec3 i = c + uv.x * cr + uv.y * cu;
return i-ro;
}
void main( void ) {
vec3 color = vec3(0.);
vec2 uv;
//
#if AA>1
for( int m=ZERO; m<AA; m++ )
for( int n=ZERO; n<AA; n++ )
{
// pixel coordinates
vec2 o = vec2(float(m),float(n)) / float(AA) - 0.5;
uv = (2. * gl_FragCoord.xy - (u_resolution.xy+o))/u_resolution.y;
#else
uv = (2. * gl_FragCoord.xy - u_resolution.xy )/u_resolution.y;
#endif
// ray origin / look at point
vec3 lp = vec3(-0.5,0.1,0.);
vec3 ro = vec3(-0.15,-1.5,-2.15);
ro = get_mouse(ro);
// get ray direction
vec3 rd = ray(ro, lp, uv);
color += render(ro, rd, uv);
// AA from NuSan
#if AA>1
}
color /= float(AA*AA);
#endif
gl_FragColor = vec4(color,1.0);
}
</script>
</shader-doodle>
/**
Click and drag the ball around yo!
Experiments in Log Polar Warping - good read here!
https://www.osar.fr/notes/logspherical/
Zero webgl boilerplate, its all handled by shader-doodle.
https://github.com/halvves/shader-doodle
*/
<script src="https://unpkg.com/[email protected]"></script>
html {
font-size: 100%;
height: 100%;
}
body {
width: 100vw;
height: 100vh;
background: rgb(55, 55, 55);
overflow: hidden;
}
shader-doodle {
display: flex;
position: absolute;
width: 100%;
height: 100%;
bottom: 0px;
left: 0;
}
.info {
position: absolute;
font-family: "Righteous", cursive;
bottom: 10px;
right: 10px;
color: #fff;
text-shadow: 0 0 13px rgba(0, 0, 0, 0.5);
font-size: 0.95rem;
white-space: nowrap;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment