Made from summed inversions and a basic kaleidoscopic ifs.

Code in comments.

  • DumbAceDragon@sh.itjust.works
    link
    fedilink
    English
    arrow-up
    3
    ·
    4 months ago

    Shader art is underappreciated imo. I’ve dabbled in it a bit myself but I’ve never done anything this incredible. Awesome work!

    • Waveform@lemmy.worldOP
      link
      fedilink
      English
      arrow-up
      2
      ·
      4 months ago

      Thank you. Yeah, shaders are great. Lots of awesome stuff over at the shadertoy website.

  • Waveform@lemmy.worldOP
    link
    fedilink
    English
    arrow-up
    2
    ·
    edit-2
    4 months ago

    The code (sorry, I can’t combine a spoiler tag with a code block):

    // 2024 Waveform
    // Code adapted for Shader Editor (Android).
    
    #extension GL_OES_standard_derivatives : enable
    
    #ifdef GL_FRAGMENT_PRECISION_HIGH
    precision highp float;
    #else
    precision mediump float;
    #endif
    
    uniform vec2 resolution;
    uniform float time;
    
    #define pi 3.14159
    
    #define rotate(p, a) vec2(p.x*cos(a) - p.y*sin(a), p.x*sin(a) + p.y*cos(a))
    
    // hash without sine
    // https://www.shadertoy.com/view/4djSRW
    #define MOD3 vec3(443.8975, 397.2973, 491.1871) // uv range
    float hash11(float p) {
    	vec3 p3  = fract(vec3(p) * MOD3);
    	p3 += dot(p3, p3.yzx + 19.19);
    	return fract((p3.x + p3.y) * p3.z);
    }
    
    vec2 c_inv(vec2 p, vec2 o, float r) {
    	return (p-o) * r * r / dot(p-o, p-o) + o;
    }
    
    float grid(in vec2 p){ p = abs(fract(p+.5)-.5); return 2. * min(p.x, p.y); }
    
    void invArc(in vec2 p, inout vec2 pg, float n, float arc, float rad, float seed) {
    	for(float i=0.; i<n; i++) {
    		float rnd = .65 * hash11(i+seed);
    		pg +=
    			c_inv(
    				p,
    				rad*vec2(
    					sin(2.*arc*pi*(i+rnd)/n),
    					cos(2.*arc*pi*(i+rnd)/n)
    				),
    				1.25-.5*hash11(i-seed)
    			);
    	}
    }
    
    void main(void) {
    	vec2 res = resolution.xy;
    	vec2 fc = gl_FragCoord.xy;
    	vec2 p = (fc-res/2.) / res.y;
    	vec3 o = vec3(-1., 0., 1.);
    	float f;
    
    	// zoom
    	p *= 1.3;
    
    	// building coords from summed-up circle inversions
    	vec2 pg = vec2(0.);
    
    	// dot number/density
    	float N = 80.;
    
    	// outer circle
    
    	invArc(p, pg, N, 1., .25, 1.);
    
    	// inner semicircles
    	invArc(p-o.yx*.125, pg, N/4., -.5, .125, N);
    	invArc(p-o.yz*.125, pg, N/4., -.5, -.125, -N);
    	// dots
    	pg *= -1.;
    	invArc(p-o.yx*.125, pg, N/8., 1., 1./48., 2.*N);
    	invArc(p-o.yz*.125, pg, N/8., 1., 1./48., -2.*N);
    	pg *= -1.;
    
    	// p's value is now summed inversions
    	p = pg / 18.;
    
    	// new time value
    	float T = 10.;// + .15 * time;
    
    	// fractalize
    	vec2 p3 = p;
    	for(float i=0.; i<14.; i++) {
    		p3 += 1.7 * i * vec2(1., .77);
    		p3 = rotate(p3, pi/1.55+.2*sin(.15*i-.1));
    		p3 = abs(mod(p3, 10.)-5.);
    	}
    
    	// apply grid
    	f = grid(p3+T);
    
    	// give lines an even thickness
    	f /= .05 * res.x * length(vec2(dFdx(p.x), dFdx(p.y)));
    
    	// value adjustment
    	f = min(1., f+.73);
    
    	// trying to make a distinction between yin and yang
    	f += .05 + .02 * (p.y-p.x);
    
    	vec3 RGB = vec3(f);
    
    	// faux lighting
    	f += 1. * (.014 * length(p+15.) - .85);
    
    	// final color
    	RGB +=
    		mix(
    			vec3(.2, .1, .4),
    			1.7*vec3(1., .5, .15),
    			f
    		)-.7;
    
    	gl_FragColor = vec4(RGB, 1.);
    }