// Credit to iq: https://www.shadertoy.com/view/4sX3Rn // // Created by Sam Gondelman on 7/6/2016 // Copyright 2016 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // float maxcomp(in vec3 p ) { return max(p.x,max(p.y,p.z));} float sdBox( vec3 p, vec3 b ) { vec3 di = abs(p) - b; float mc = maxcomp(di); return min(mc,length(max(di,0.0))); } const mat3 ma = mat3( 0.60, 0.00, 0.80, 0.00, 1.00, 0.00, -0.80, 0.00, 0.60 ); vec4 map( in vec3 p ) { float d = sdBox(p,vec3(1.0)); vec4 res = vec4( d, 1.0, 0.0, 0.0 ); float ani = smoothstep( -0.2, 0.2, -cos(0.5*iGlobalTime) ); float off = 1.5*sin( 0.01*iGlobalTime ); float s = 1.0; for( int m=0; m<4; m++ ) { p = mix( p, ma*(p+off), ani ); vec3 a = mod( p*s, 2.0 )-1.0; s *= 3.0; vec3 r = abs(1.0 - 3.0*abs(a)); float da = max(r.x,r.y); float db = max(r.y,r.z); float dc = max(r.z,r.x); float c = (min(da,min(db,dc))-1.0)/s; if( c>d ) { d = c; res = vec4( d, min(res.y,0.2*da*db*dc), (1.0+float(m))/4.0, 0.0 ); } } return res; } vec4 intersect( in vec3 ro, in vec3 rd ) { float t = 0.0; float tmax = 40.0; vec4 res = vec4(-1.0); vec4 h = vec4(1.0); for( int i=0; i<64; i++ ) { if( h.x<0.002 || t>tmax ) break; h = map(ro + rd*t); res = vec4(t,h.yzw); t += h.x; } if( t>tmax ) res=vec4(-1.0); return res; } float softshadow( in vec3 ro, in vec3 rd, float mint, float k ) { float res = 1.0; float t = mint; float h = 1.0; for( int i=0; i<32; i++ ) { h = map(ro + rd*t).x; res = min( res, k*h/t ); t += clamp( h, 0.005, 0.1 ); } return clamp(res,0.0,1.0); } vec3 calcNormal(in vec3 pos) { vec3 eps = vec3(.001,0.0,0.0); vec3 nor; nor.x = map(pos+eps.xyy).x - map(pos-eps.xyy).x; nor.y = map(pos+eps.yxy).x - map(pos-eps.yxy).x; nor.z = map(pos+eps.yyx).x - map(pos-eps.yyx).x; return normalize(nor); } // light vec3 light = normalize(vec3(1.0,0.9,0.3)); vec3 render( in vec3 ro, in vec3 rd ) { vec3 col; vec4 tmat = intersect(ro,rd); if( tmat.x>0.0 ) { vec3 pos = ro + tmat.x*rd; vec3 nor = calcNormal(pos); float occ = tmat.y; float sha = softshadow( pos, light, 0.01, 64.0 ); float dif = max(0.1 + 0.9*dot(nor,light),0.0); float sky = 0.5 + 0.5*nor.y; float bac = max(0.4 + 0.6*dot(nor,vec3(-light.x,light.y,-light.z)),0.0); vec3 lin = vec3(0.0); lin += 1.00*dif*vec3(1.10,0.85,0.60)*sha; lin += 0.50*sky*vec3(0.10,0.20,0.40)*occ; lin += 0.10*bac*vec3(1.00,1.00,1.00)*(0.5+0.5*occ); lin += 0.25*occ*vec3(0.15,0.17,0.20); vec3 matcol = vec3( 0.5+0.5*cos(0.0+2.0*tmat.z), 0.5+0.5*cos(1.0+2.0*tmat.z), 0.5+0.5*cos(2.0+2.0*tmat.z) ); col = matcol * lin; } else { discard; } return pow( col, vec3(0.4545) ); } vec3 getProceduralColor() { vec3 worldEye = getEyeWorldPos(); // this will make it movable, scalable, and rotatable vec3 ro = _position.xyz; vec3 eye = (inverse(iWorldOrientation) * (worldEye - iWorldPosition)) / iWorldScale; // vec3 ro = iWorldOrientation * (_position.xyz * iWorldScale) + iWorldPosition; // world position of the current fragment // vec3 eye = worldEye; ro.x *= 2.0985; ro.y *= 2.0721; ro.z *= 2.0785; ro.x += -0.0015; ro.y += -0.0156; ro.z += 0.0070; eye.x *= 2.0985; eye.y *= 2.0721; eye.z *= 2.0785; eye.x += -0.0015; eye.y += -0.0156; eye.z += 0.0070; vec3 rd = normalize(ro - eye); // ray from camera eye to ro return render(eye, rd); } float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) { vec3 color = getProceduralColor(); diffuse = color.rgb; specular = color.rgb; shininess = 0.5; return 1.0; }