From 07d6d1dee5eee39f7efda183b4f938bcb6f1ca2d Mon Sep 17 00:00:00 2001 From: polyfloyd Date: Sat, 19 May 2018 16:58:26 +0200 Subject: [PATCH] Add spherical-polyhedra.glsl --- spherical-polyhedra.glsl | 254 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 spherical-polyhedra.glsl diff --git a/spherical-polyhedra.glsl b/spherical-polyhedra.glsl new file mode 100644 index 0000000..4f05b87 --- /dev/null +++ b/spherical-polyhedra.glsl @@ -0,0 +1,254 @@ +//Spherical polyhedra by nimitz (twitter: @stormoid) + +/* + Follow up to my "Sphere mappings" shader (https://www.shadertoy.com/view/4sjXW1) + + I was thinking about a cheap way to do icosahedral mapping and realized + I could just project on an axis and rotate the sphere for each projected + "facet". + + Here I am showing only tilings of the regular polyhedra but this technique can + be used for any tilings of the sphere, regular or not. (or even arbitrary projections) + + I omitted the tetraedron since the small number of projections + results in heavy deformation. + + Perhaps there is a way to make that process cheaper? Let me know. + */ + +#define time iTime + +mat2 mm2(in float a){float c = cos(a), s = sin(a);return mat2(c,-s,s,c);} +vec3 rotx(vec3 p, float a){ float s = sin(a), c = cos(a); + return vec3(p.x, c*p.y - s*p.z, s*p.y + c*p.z); } + vec3 roty(vec3 p, float a){ float s = sin(a), c = cos(a); + return vec3(c*p.x + s*p.z, p.y, -s*p.x + c*p.z); } + vec3 rotz(vec3 p, float a){ float s = sin(a), c = cos(a); + return vec3(c*p.x - s*p.y, s*p.x + c*p.y, p.z); } + + //---------------------------Textures-------------------------------- + //------------------------------------------------------------------- +vec3 texpent(in vec2 p, in float idx) +{ + float siz = iResolution.x *.007; + vec2 q = abs(p); + float rz = sin(clamp(max(max(q.x*1.176-p.y*0.385, q.x*0.727+p.y), + -p.y*1.237)*33.,0.,25.))*siz+siz; + vec3 col = (sin(vec3(1,1.5,5)*idx)+2.)*(rz+0.25); + col -= sin(dot(p,p)*10.+time*5.)*0.4; + return col; +} + +vec3 textri2(in vec2 p, in float idx) +{ + float siz = iResolution.x *.007; + vec2 q = abs(p); + float rz = sin(clamp(max(q.x*1.73205+p.y, -p.y*2.)*32.,0.,25.))*siz+siz; + vec3 col = (sin(vec3(1,1.7,5)*idx)+2.)*(rz+0.25); + col -= sin(p.x*20.+time*5.)*0.2; + return col; +} + +vec3 texcub(in vec2 p, in float idx) +{ + float siz = iResolution.x *.007; + float rz = sin(clamp(max(abs(p.x),abs(p.y))*24.,0.,25.))*siz+siz; + vec3 col = (sin(vec3(4,3.,5)*idx*.9)+2.)*(rz+0.25); + float a= atan(p.y,p.x); + col -= sin(a*15.+time*11.)*0.15-0.15; + return col; +} + +vec3 textri(in vec2 p, in float idx) +{ + float siz = iResolution.x *.001; + p*=1.31; + vec2 bp = p; + p.x *= 1.732; + vec2 f = fract(p)-0.5; + float d = abs(f.x-f.y); + d = min(abs(f.x+f.y),d); + + float f1 = fract((p.y-0.25)*2.); + d = min(d,abs(f1-0.5)); + d = 1.-smoothstep(0.,.1/(siz+.7),d); + + vec2 q = abs(bp); + p = bp; + d -= smoothstep(1.,1.3,(max(q.x*1.73205+p.y, -p.y*2.))); + vec3 col = (sin(vec3(1.,1.5,5)*idx)+2.)*((1.-d)+0.25); + col -= sin(p.x*10.+time*8.)*0.15-0.1; + return col; +} + +//---------------------------------------------------------------------------- +//----------------------------------Sphere Tilings---------------------------- +//---------------------------------------------------------------------------- + +//All the rotation matrices can be precomputed for better performance. + +//5 mirrored pentagons for the dodecahedron +vec3 dod(in vec3 p) +{ + vec3 col = vec3(1); + vec2 uv = vec2(0); + for (float i = 0.;i<=4.;i++) + { + p = roty(p,0.81); + p = rotx(p,0.759); + p = rotz(p,0.3915); + uv = vec2(p.z,p.y)/((p.x)); + col = min(texpent(uv,i+1.),col); + } + p = roty(p,0.577); + p = rotx(p,-0.266); + p = rotz(p,-0.848); + uv = vec2(p.z,-p.y)/((p.x)); + col = min(texpent(uv,6.),col); + + return 1.-col; +} + +//10 mirrored triangles for the icosahedron +vec3 ico(in vec3 p) +{ + vec3 col = vec3(1); + vec2 uv = vec2(0); + + //center band + const float n1 = .7297; + const float n2 = 1.0472; + for (float i = 0.;i<5.;i++) + { + if(mod(i,2.)==0.) + { + p = rotz(p,n1); + p = rotx(p,n2); + } + else + { + p = rotz(p,n1); + p = rotx(p,-n2); + } + uv = vec2(p.z,p.y)/((p.x)); + col = min(textri(uv,i+1.),col); + } + p = roty(p,1.048); + p = rotz(p,.8416); + p = rotx(p,.7772); + //top caps + for (float i = 0.;i<5.;i++) + { + p = rotz(p,n1); + p = rotx(p,n2); + + uv = vec2(p.z,p.y)/((p.x)); + col = min(textri(uv,i+6.),col); + } + + return 1.-col; +} + +//4 mirrored triangles for octahedron +vec3 octa(in vec3 p) +{ + vec3 col = vec3(1); + vec2 uv = vec2(0); + const float n1 = 1.231; + const float n2 = 1.047; + for (float i = 0.;i<4.;i++) + { + p = rotz(p,n1); + p = rotx(p,n2); + uv = vec2(p.z,p.y)/((p.x)); + col = min(textri2(uv*.54,i+1.),col); + } + + return 1.-col; +} + +//cube using the same technique for completeness +vec3 cub(in vec3 p) +{ + vec3 col = vec3(1); + vec2 uv = vec2(p.z,p.y)/((p.x)); + col = min(texcub(uv*1.01,15.),col); + p = rotz(p,1.5708); + uv = vec2(p.z,p.y)/((p.x)); + col = min(texcub(uv*1.01,4.),col); + p = roty(p,1.5708); + uv = vec2(p.z,p.y)/((p.x)); + col = min(texcub(uv*1.01,5.),col); + + return 1.-col; +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + +vec2 iSphere2(in vec3 ro, in vec3 rd) +{ + vec3 oc = ro; + float b = dot(oc, rd); + float c = dot(oc,oc) - 1.; + float h = b*b - c; + if(h <0.0) return vec2(-1.); + else return vec2((-b - sqrt(h)), (-b + sqrt(h))); +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 uv = (fragCoord.xy - iResolution.xy * 0.5) / max(iResolution.x, iResolution.y); + vec2 bp = uv+0.5; + vec2 um = iResolution.xy / max(iResolution.x, iResolution.y); + + //camera + vec3 ro = vec3(0.,0.,3.5); + vec3 rd = normalize(vec3(uv,-0.8)); + mat2 mx = mm2(time*0.25+um.x*6.); + mat2 my = mm2(time*0.27+um.y*6.); + ro.xz *= mx;rd.xz *= mx; + ro.xy *= my;rd.xy *= my; + + float sel = mod(floor((time+10.)*0.2),4.); + //sel=0.; + vec2 t = iSphere2(ro,rd); + vec3 col = vec3(0.); + float bg = clamp(dot(-rd,vec3(0.577))*0.3+.6,0.,1.); + if (sel == 0.) col = dod(rd)*1.2; + else if (sel == 1.) col = ico(rd)*1.2; + else if (sel == 2.) col = cub(rd)*1.2; + else if (sel == 3.) col = octa(rd)*1.2; + + if (t.x > 0.) + { + vec3 pos = ro+rd*t.x; + vec3 pos2 = ro+rd*t.y; + vec3 rf = reflect(rd,pos); + if (sel == 0.) + { + vec3 col2 = max(dod(pos)*2.,dod(pos2)*.6); + col = mix(max(col,col2),col2,0.6); + } + else if (sel == 1.) + { + vec3 col2 = max(ico(pos2)*0.6,ico(pos)*2.); + col = mix(max(col,col2),col2,0.6); + } + else if (sel == 2.) + { + vec3 col2 = max(cub(pos2)*0.6,cub(pos)*2.); + col = mix(max(col,col2),col2,0.6); + } + else if (sel == 3.) + { + vec3 col2 = max(octa(pos2)*0.6,octa(pos)*2.); + col = mix(max(col,col2),col2,0.6); + } + } + + fragColor = vec4(col, 1.0); +} + + +// https://www.shadertoy.com/view/4dBXWD