0.00
60.0 fps

Fractal Marble

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 );
}