Fractal Marble
Log in to post a comment.
precision highp float; uniform float iTime; uniform vec2 iResolution; uniform float offset; // value=0, min=0, max=1, step=0.001 uniform float scale; // value=0.1, min=0.05, max=0.2, step=0.001 uniform float angle; // value=-0.85, min=-1, max=1, step=0.001 uniform float fracParam; // value=0.85, min=0.45, max=0.88, step=0.001 // Hash without Sine by David Hoskins // https://www.shadertoy.com/view/4djSRW float hash13(vec3 p3) { p3 = fract(p3 * .1031); p3 += dot(p3, p3.yzx + 33.33); return fract((p3.x + p3.y) * p3.z); } mat2 rot(float a) { return mat2(cos(a),sin(a),-sin(a),cos(a)); } float map(in vec3 p) { float a = 0.; p.zy *= rot(p.x * angle); vec3 c = p; for (int i = 0; i < 9; ++i) { // p = fracParam * abs(p)/dot(p,p) - fracParam; p = fracParam * abs(normalize(p)) - fracParam; p.xy = vec2(p.x*p.x - p.y*p.y, 2.*p.y*p.x); p = p.yzx; // smooth blending, see: http://www.fractalforums.com/3d-fractal-generation/kaliset-3d-fractal-used-as-coloring-and-bump-mapping-for-de-systems/ a += exp2(-20. * abs(dot(p, c))); // a += exp2(-20. * abs(dot(p, vec3(.5)))); // a += exp2(-20. * abs(length(p) -.5)); } return a; } vec3 iSphere( 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; float d = sqrt( max(0.0,1.-h)) - 1.; h = sqrt(max(0., h)); return vec3(d, -b-h, -b+h ); } vec3 getCol( float t ) { return .5 + .5 * cos(6.28318 * t + vec3(0.0, 0.6, 1.2)); } vec4 march( in vec3 ro, vec3 rd, float maxDist ) { float d = 0., c = 0.; float dt = 0.05; // scale ro *= 2.; maxDist *= 2.; // rotate ro.xz*=rot(0.1*iTime); ro.yz*=rot(0.2); rd.xz*=rot(0.1*iTime); rd.yz*=rot(0.2); vec3 col= vec3(0.); vec4 sum = vec4(0.0); for( int i=0; i<64; i++ ) { d += dt * exp2(-2. * c); if( d > maxDist) { return sum; } vec3 pos = ro+d*rd; c = map(pos); vec3 col = getCol(c*scale + offset) * sqrt(length(pos) * .5 + 0.01); // blend front to back // float a = min(0.2*dt*(c),1.) *(1.0-sum.a); // clear glass float a = min(0.2*dt*sqrt(c),1.) *(1.0-sum.a); // milky glass sum += vec4(col * a, a); } return sum; } void main() { const float N = 1./1.45; const vec3 L = normalize(vec3(.5, -1., .2)); vec2 p = (2. * gl_FragCoord.xy - iResolution) / iResolution.y; vec3 ro = vec3(0., 0., 2.5); vec3 rd = normalize( vec3(p.x, p.y, -1.8) ); vec3 isp = iSphere( ro, rd ); vec3 bgCol = vec3(0); vec3 col = bgCol; float s = max( 0.0, isp.x/isp.y ); float px = 3.6/iResolution.y; if (s < px) { vec3 pos0 = ro+isp.y*rd; vec3 nor0 = pos0; vec3 rfr0 = refract(rd, nor0, N); vec3 isp0 = iSphere(pos0, rfr0); vec4 data = march(pos0, rfr0, isp0.z - isp0.y); col = data.rgb * data.rgb * 20.; float diff = .5 - .5 *dot(L, nor0); col *= diff ; col = mix(bgCol, col, data.a); vec3 rfl0 = reflect(rd, nor0); float fre0 = .15 + (1. - .15) * pow(clamp(1. + dot(nor0, rd), 0., 1.), 5.); float spec0 = pow(max(dot(reflect(-L, nor0), rd), 0.0), 64.); col *= 1.-fre0; col += (.05 * smoothstep(-.1, .2, rfl0.y ) + spec0 * 5. ) * fre0; // refraction out vec3 pos1 = pos0 + isp0.z * rfr0; vec3 nor1 = -pos1; vec3 rfr1 = refract(rfr0, nor1, 1./N); float fre1 = .15 + (1. - .15) * pow(clamp(1. + dot(nor1,-rfr0), 0., 1.), 5.); float spec1 = pow(max(dot(reflect(-L, nor1), rfr1), 0.0), 64.); col += ((.1 * smoothstep(-.1, .2, rfr1.y ) + (spec1 * .6)) * (1.-fre0) * fre1 * (1. - data.a) * (1. - data.a)) * getCol(.75*scale + offset); col = mix(col, bgCol, clamp(s/px, 0., 1.)); } col = max( vec3(0), col - 0.004); col = (col*(6.2*col + .5)) / (col*(6.2*col+1.7) + 0.06); col += 4./255. * (hash13(vec3(gl_FragCoord.xy, iTime)) - .5); gl_FragColor = vec4(max(vec3(0), col), 1.0 ); }