Fractals/shadertoy

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Shadertoy [1][2]

GLSL ES[edit | edit source]

The parts of GLSL ES that are relevant for Shadertoy :

Preprocessor: # #define #undef #if #ifdef #ifndef #else #elif #endif #error #pragma #extension #version #line
Operators: () + - ! * / % << >> < > <= >= == != && ||
Comments: // /* */
Types: void bool int float vec2 vec3 vec4 bvec2 bvec3 bvec4 ivec2 ivec3 ivec4 mat2 mat3 mat4 sampler2D
Function Parameter Qualifiers: [none], in, out, inout
Global Variable Qualifiers: const
Vector Components: .xyzw .rgba .stpq
Flow Control: if else for return break continue
Output: vec4 gl_FragColor
Input: vec4 gl_FragCoord

Types[edit | edit source]

There are four main types:[3]

  • float
  • int
  • bool
  • sampler
vec2, vec3, vec4			2D, 3D and 4D floating point vector
ivec2, ivec3, ivec4			2D, 3D and 4D integer vector
bvec2, bvec3, bvec4			2D, 3D and 4D boolean vectors
\\ matrix types:
mat2, mat3, mat4			2x2, 3x3, 4x4 floating point matrix
\\
sampler1D, sampler2D, sampler3D		1D, 2D and 3D texture
samplerCube				Cube Map texture
sampler1Dshadow, sampler2Dshadow	1D and 2D depth-component texture

Built-in Functions[edit | edit source]

type radians (type degrees)
type degrees (type radians)
type sin (type angle)
type cos (type angle)
type tan (type angle)
type asin (type x)
type acos (type x)
type atan (type y, type x)
type atan (type y_over_x)
type pow (type x, type y)
type exp (type x)
type log (type x)
type exp2 (type x)
type log2 (type x)
type sqrt (type x)
type inversesqrt (type x)
type abs (type x)
type sign (type x)
type floor (type x)
type ceil (type x)
type fract (type x)
type mod (type x, float y)
type mod (type x, type y)
type min (type x, type y)
type min (type x, float y)
type max (type x, type y)
type max (type x, float y)
type clamp (type x, type minV, type maxV)
type clamp (type x, float minV, float maxV)
type mix (type x, type y, type a)
type mix (type x, type y, float a)
type step (type edge, type x)
type step (float edge, type x)
type smoothstep (type a, type b, type x)
type smoothstep (float a, float b, type x)
mat matrixCompMult (mat x, mat y)
float length (type x)
float distance (type p0, type p1)
float dot (type x, type y)
vec3 cross (vec3 x, vec3 y)
type normalize (type x)
type faceforward (type N, type I, type Nref)
type reflect (type I, type N)
type refract (type I, type N,float eta)
bvec lessThan(vec x, vec y)
bvec lessThan(ivec x, ivec y)
bvec lessThanEqual(vec x, vec y)
bvec lessThanEqual(ivec x, ivec y)
bvec greaterThan(vec x, vec y)
bvec greaterThan(ivec x, ivec y)
bvec greaterThanEqual(vec x, vec y)
bvec greaterThanEqual(ivec x, ivec y)
bvec equal(vec x, vec y)
bvec equal(ivec x, ivec y)
bvec equal(bvec x, bvec y)
bvec notEqual(vec x, vec y)
bvec notEqual(ivec x, ivec y)
bvec notEqual(bvec x, bvec y)
bool any(bvec x)
bool all(bvec x)
bvec not(bvec x)
vec4 texture2D(sampler2D sampler, vec2 coord )
vec4 texture2D(sampler2D sampler, vec2 coord, float bias)
vec4 textureCube(samplerCube sampler, vec3 coord)
vec4 texture2DProj(sampler2D sampler, vec3 coord )
vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias)
vec4 texture2DProj(sampler2D sampler, vec4 coord)
vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias)
type dFdx( type x ), dFdy( type x )
type fwidth( type p )

Conversions[edit | edit source]

Converting Shadertoy shaders to :

  • GLSL Sandbox code[4]

Shader description[edit | edit source]

"Shaders are programs that are executed in the GPU. A shader actually consists of two programs: the vertex shader and the fragment (or pixel) shader." [5]

Shader is a " one program, to act on a single pixel, but then Shadertoy and WebGL run it (simultaneously) on every single pixel in the viewport ... thanks to the awesomeness of GPU acceleration" [6]

types of Shadertoy shaders :

  • Image shaders
  • sound shaders
  • VR shaders

mainImage function[edit | edit source]

Image shaders implement the mainImage() function in order to generate the procedural images by computing a color for each pixel.

This function is expected to be called once per pixel, and it is responsibility of the host application to provide the right inputs to it and get the output color from it and assign it to the screen pixel.

The prototype is:

void mainImage( out vec4 fragColor, in vec2 fragCoord );

inputs[edit | edit source]

uniforms[edit | edit source]

"Uniforms are for getting values from outside of the shader, into the shader.... Uniforms can be vectors, floats, float arrays, integers and integer arrays."[7]

Shader can be feed with different types of per-frame static information by using the following uniform variables ( shadertoy specific inputs ) :

type name description
uniform vec3 iResolution The viewport resolution. iResolution has width/height set as x and y respectively. z is pixel aspect ratio, usually 1.0
uniform float iGlobalTime Current time in seconds
uniform float iChannelTime[4] Time for channel (if video or sound), in seconds
uniform vec3 iChannelResolution0..3 Input texture resolution for each channel
uniform vec4 iMouse xy = current pixel coords (if LMB is down). zw = click pixel
uniform sampler2D iChannel{i} Sampler for input textures i
uniform vec4 iDate Year, month, day, time in seconds in .xyzw
uniform float iSampleRate The sound sample rate (typically 44100)

Coordinate[edit | edit source]

Types :

  • pixel
    • x is from 0 to width
    • y is from 0 to height
  • normalized : from 0.0 to 1.0
  • world : arbitrary ranges

Input variable of mainImage() function is fragCoord ( = gl_FragCoord in GLSL )

It contains the current pixel position (coordinates) in pixels for which the shader needs to compute a color. We can access x and y values of it

The coordinates are in pixel units

The resolution is passed to the shader through the iResolution uniform (see above table).

To normalize the coordinate ( normalized device coordinates = NDC) do :

// Converting (x,y) to range [0,1]
float x = gl_FragCoord.x / iResolution.x; // 
float y = gl_FragCoord.y / iResolution.y;

"Now our x and y is in range 0..1 and we don’t care anymore about (screen) resolution, width or length."[8]

Aspect ratio[9]

x *= iResolution.x / iResolution.y;

outputs[edit | edit source]

Color[edit | edit source]

"For image shaders, the regular gl_FragColor is used as output channel. It is not for now mandatory but recommended to leave the alpha channel to 1.0;"

Examples[edit | edit source]

First image shader[edit | edit source]

// This shader computes the same color ( red = 1.0,0.0,0.0 ) for every pixel
// static image 
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	// color = r,g,b,a 
	// every value is in range [0.0, 1.0]
	fragColor = vec4(1.0,0.0,0.0,1.0);
}

color[edit | edit source]

Solid[edit | edit source]

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    float r = fragCoord.x / iResolution.x;
    float g = fragCoord.y / iResolution.y;
    float b = fragCoord.x / iResolution.y;
    fragColor = vec4(r,g,b,1.0);
}

Gradient[edit | edit source]

horizontal red gradient

// based on the code by Omar Shehata
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    float x = fragCoord.x; //We obtain our coordinates for the current pixel
    x = x / iResolution.x; //We divide the coordinates by the screen size
    // Now x is 0 for the leftmost pixel, and 1 for the rightmost pixel
    //Set its red component to the normalized x value = red gradient from left to right 
    fragColor = vec4(x, 0.0,  0.0, 1.0);
}

vertical green gradient

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    float y = fragCoord.y; //We obtain our coordinates for the current pixel
    y = y / iResolution.y; //We divide the coordinates by the screen size
    // Now y is 0 for the bottom pixel, and 1 for the up  pixel
    //Set its red component to the normalized x value
    fragColor = vec4( 0.0, y, 0.0, 1.0);
}

quadrants[edit | edit source]

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    
    float x = fragCoord.x/iResolution.x; // 0.0 < x < 1.0
    float y = fragCoord.y/iResolution.y; // 
    
    
    fragColor = vec4(0.0,1.0,0.0,1.0); // green = background
    
    if( x > 0.5 && y > 0.5) {fragColor = vec4(1.0,0.0,0.0,1.0);} // red = upper right
    if( x < 0.5 && y < 0.5) {fragColor = vec4(0.0,0.0,1.0,1.0);} // blue = lower left
}

Cross[edit | edit source]

// https://www.shadertoy.com/view/MssXWn
// bu Lukas Pukenis http://www.letsdive.in/2014/05/11/glsl-basics/
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {			
	float thicknessH = 0.01;
	float thicknessV = 0.01;
	
	float y = fragCoord.y / iResolution.y;
	float x = fragCoord.x / iResolution.x;

	float diffY = abs(0.5 - y);
	float diffX = abs(0.5 - x);
	
	if ( diffY < thicknessH || diffX < thicknessV) {
		fragColor = vec4(1.0, 0.0, 0.0, 1.0 );
	} else {
		fragColor = vec4(0.0, 0.0, 0.0, 1.0 );
	}
		
}

rectangle[edit | edit source]

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{   
    float x = fragCoord.x/iResolution.x; // 0.0 < x < 1.0
    float y = fragCoord.y/iResolution.y; // 
    vec2 center = vec2(0.5, 0.5); // center of the image
    
    fragColor = vec4(0.0,1.0,0.0,1.0); // green = background
    if( abs(center.x - x) < 0.2 && abs(center.y - y) < 0.2) {fragColor = vec4(1.0,0.0,0.0,1.0);} // red rectangle in center of image 
}

square[edit | edit source]

void mainImage( out vec4 fragColor, in vec2 fragCoord )
    
     
{   float ratio = iResolution.x / iResolution.y; // aspect ratio of the window : https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson3
    float x = ratio*fragCoord.x/iResolution.x; // 0.0 < x < 1.0*ratio
    float y = fragCoord.y/iResolution.y; //  0.0 < y < 1.0
    vec2 center = vec2(ratio*0.5, 0.5); // center of the image 
 
    fragColor = vec4(0.0,1.0,0.0,1.0); // green = background
    if( abs(center.x - x) < 0.2 && abs(center.y - y) < 0.2) {fragColor = vec4(1.0,0.0,0.0,1.0);} // red rectangle in center of image 
}

Circle[edit | edit source]

Circle using pixel coordinate :

// https://www.shadertoy.com/view/Mdf3Df
// circle using pixel coordinate
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	
    // the center of the texture
    vec2 center = vec2(iResolution.x/2.0,iResolution.y/2.0); 
	
    // current pixel location
    vec2 loc = fragCoord.xy;
	
    // how far we are from the center
    float radius=length(loc-center);
	
    
    if (radius<100.0)
        fragColor = vec4(1,0,0,1); // if we are within our circle, paint it red
    else
        fragColor = vec4(0,0,0,1); // black background
}

Circle using world coordinate and center/radius plane description:

vec2 center = vec2(0.0,0.0); // center of the image in world units
float radius = 2.0; // Radius is defined as "the difference in imaginary coordinate between the center and the top of the axis-aligned view rectangle".

vec2 GiveCoordinate(vec2 center, float radius, vec2 fragCoord, vec3 iResolution)
{
  // from pixel to world coordinate   
  // start with pixel coordinate : now point=(0,0) is left bottom and point=(iResolution.x, iResolution.y) is right top   
  float x = (fragCoord.x -  iResolution.x/2.0)/ (iResolution.y/2.0);
  float y = (fragCoord.y -  iResolution.y/2.0)/ (iResolution.y/2.0);
  vec2 c = vec2(center.x + radius*x, center.y + radius*y) ;  
  return c ; // now coordinate are measured in world units : from 0.0 t 1.0
}

vec3 GiveColor ( vec2 c, vec2 circle_center, float circle_radius)
{
    vec3 color = vec3(1.0, 0.0, 035); // background 
    // draws a circle centered at circle_center 
    if ( length(circle_center-c)< circle_radius) {color = vec3(0.0, 0.0, 0.0);}
    return color;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord)
{   
    vec2 c =  GiveCoordinate(center, radius, fragCoord, iResolution);
    vec3 color = GiveColor(c, vec2(0.0, 0.9), 1.5);     
    fragColor = vec4(color,1.0); //   
}

Julia set[edit | edit source]

LSM[edit | edit source]

Julia set :

  • integer escape time and Level set Method for exterior
  • solid color for interior ( red)
// based on the code by gltracy
// https://www.shadertoy.com/view/XsS3Rm

const int i_max = 2055;
vec2 c = vec2( -0.12256, 0.74486);
float er2 = 4.0; // er= er*er escape radius

vec2 complex_square( vec2 v ) {
	return vec2(
		v.x * v.x - v.y * v.y,
		v.x * v.y * 2.0
	);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    
    // compute coordinate 
	vec2 z = fragCoord.xy - iResolution.xy * 0.5;
	z *= 2.5 / min( iResolution.x, iResolution.y );
	

	
	
	float scale = 0.1;

	int count = 0;
	
    
    // iterations 
	for ( int i = 0 ; i < i_max; i++ ) {
        
		z = c + complex_square( z );
		count = i;
        if ( dot(z,z) > er2 ) {  break; }
	}
	
    // color 
    if (count == i_max-1) {fragColor = vec4(1.0, 0.0,0.0,1.0);} // filled-in Julia set = red
    else  fragColor = vec4(1.0- float( count ) * scale ); // exterior 
}

orbit trap[edit | edit source]

Orbit trap , parabolic checkerboard

// https://www.shadertoy.com/view/4dy3RR
// Orbit trapped julia by maeln
#define MAXITER 128

vec2 cmul(vec2 i1, vec2 i2) 
{
    return vec2(i1.x*i2.x - i1.y*i2.y, i1.y*i2.x + i1.x*i2.y);
}

vec3 julia(vec2 z, vec2 c)
{
    int i = 0;
    vec2 zi = z;
    
    float trap1 = 10e5;
    float trap2 = 10e5;
    
    for(int n=0; n < MAXITER; ++n)
    {
        if(dot(zi,zi) > 4.0)
            break;
        i++;
        zi = cmul(zi,zi) + c;
		
        // Orbit trap
        trap1 = min(trap1, sqrt(zi.x*zi.y));
        trap2 = min(trap2, sqrt(zi.y*zi.y));
    }
    
    return vec3(i,trap1,trap2);
}

vec4 gen_color(vec3 iter)
{
    float t1 = 1.0+log(iter.y)/8.0;
    float t2 = 1.0+log(iter.z)/16.0;
    float t3 = t1/t2;
    
    //vec3 comp = vec3(t1,t1,t1);
    vec3 red = vec3(0.9,0.2,0.1);
    vec3 black = vec3(1.0,1.0,1.0);
    vec3 blue = vec3(0.1,0.2,0.9);
    vec3 comp = mix(blue,black,vec3(t2));
    comp = mix(red,comp,vec3(t1));
    
    return vec4(comp, 1.0);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 z = 2.*(2.*fragCoord.xy - iResolution.xy) / iResolution.x;
    // Display the julia fractal for C = (-0.8, [0.0;0.3]).
    vec3 iter = julia(z, vec2(cos(iTime/5.0), mix(0.0, 0.3, sin(iTime))));
	fragColor = gen_color(iter);
}


dynamics[edit | edit source]

Dynamics for quadratic 1D polynomials fc(z)=z²+c

// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// 
//-----------------https://www.shadertoy.com/view/MdX3zN-------------------------------------------
//
// Dynamics for quadratic 1D polynomials fc(z)=z²+c
//
// * Orange: the Fatou set Kc. 
// * Black: the Julia set Jc.
// * Checkerboard distortion: the Boettcher map phi(z). 
// * Checkerboard shadowing: the gradient of the Green's function, log|phi(z)|
// * Blue: the two fixed points. 
// * Green, the period 2 fixed points.
// * White: c
// * Yellow: the Koening coordinates
//
// Some theory:
//
// * c (white) belongs to Kc (orange), for these are all connected Julia sets. 
//
// * When both fixed points (blue) are in Jc but not in Kc, or in other words, when both points
//   are repeling (derivative of fc(z) is bigger than one), c does not belong to the Mandelbrot 
//   set's main cardioid, but to bulbs of higher period. In that case Kc (orange) is made of several 
//   branches (as many as the period of the bul)
//
// * When one of the two fixed points (blue dots) is inside Kc, meanins it is attractive (derivative
//   of fc(z) < 1), then c belongs to the main cardiod of the Mandelbrot set, and Kc is a single piece 
//   shape.
//
// * When the period 2 fixed points are always repelling (belong to Jc, not to Kc) except for the sets 
//   that have c belonging to the period-2 bulb of the Mandelbrot set. In those cases, the green dots
//   become attrative and sit inside the orange area Kc.
// 
// * The Koening coordinates can only been seen when c belongs to the main cariod of the Madelbrot set
//
//------------------------------------------------------------

// complex number operations
vec2 cadd( vec2 a, float s ) { return vec2( a.x+s, a.y ); }
vec2 cmul( vec2 a, vec2 b )  { return vec2( a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x ); }
vec2 cdiv( vec2 a, vec2 b )  { float d = dot(b,b); return vec2( dot(a,b), a.y*b.x - a.x*b.y ) / d; }
vec2 csqrt( vec2 z ) { float m = length(z); return sqrt( 0.5*vec2(m+z.x, m-z.x) ) * vec2( 1.0, sign(z.y) ); }
vec2 conj( vec2 z ) { return vec2(z.x,-z.y); }
vec2 cpow( vec2 z, float n ) { float r = length( z ); float a = atan( z.y, z.x ); return pow( r, n )*vec2( cos(a*n), sin(a*n) ); }

//------------------------------------------------------------

float argument( in vec2 p )
{
	float f = atan( p.y, p.x );
	if( f<0.0 ) f += 6.2831;
	f = f/6.2831;
	return f;
}

float grid( in vec2 p )
{
	vec2 q = 16.0*p;
	vec2 r = fract( q );
    float fx = smoothstep( 0.05, 0.06, r.x ) - smoothstep( 0.94, 0.95, r.x );
    float fy = smoothstep( 0.05, 0.06, r.y ) - smoothstep( 0.94, 0.95, r.y );
		
    return 0.5 + 0.5*mod( floor(q.x)+floor(q.y), 2.0 );
}

float cross( vec2 a, vec2 b )
{
    return a.x*b.y - a.y*b.x;
}

bool isInTriangle( in vec2 p, in vec2 a, in vec2 b, in vec2 c )
{
    vec3 di = vec3( cross( b - a, p - a ), 
				    cross( c - b, p - b ), 
				    cross( a - c, p - c ) );
			
    return all(greaterThan(di,vec3(0.0)));
}

float distanceToSegment( vec2 a, vec2 b, vec2 p )
{
	vec2 pa = p - a;
	vec2 ba = b - a;
	float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
	
	return length( pa - ba*h );
}

vec3 circle( vec3 bcol, vec3 col, in vec2 a, in vec2 b )
{
	float rr = 0.04;
	
	vec3 res = mix( bcol, col, 1.0 - smoothstep( rr-0.01, rr, length(a-b) ) );
	
	float f = smoothstep( rr-0.01, rr, length(a-b) ) - smoothstep( rr, rr+0.01, length(a-b) );
		
	return mix( res, vec3(0.0), f );
}

//------------------------------------------------------------

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	vec2 uv = fragCoord.xy/iResolution.xy;
	
	vec2 p = -1.0 + 2.0*uv;
	p.x *= iResolution.x/iResolution.y;
	
	float at = mod( (iTime+.5)/5.0, 8.0 );

	vec2 c =    vec2(-0.800, 0.100);
	c = mix( c, vec2( 0.280,-0.490), smoothstep(0.0,0.1,at) );
	c = mix( c, vec2(-0.500,-0.500), smoothstep(1.0,1.1,at) );
	c = mix( c, vec2(-0.160, 0.657), smoothstep(2.0,2.1,at) );
	c = mix( c, vec2(-0.650, 0.100), smoothstep(3.0,3.1,at) );
	c = mix( c, vec2(-0.114, 0.650), smoothstep(4.0,4.1,at) );
	c = mix( c, vec2(-0.731, 0.166), smoothstep(5.0,5.1,at) );
	c = mix( c, vec2(-0.100,-0.660), smoothstep(6.0,6.1,at) );
    c = mix( c, vec2(-0.800, 0.100), smoothstep(7.0,7.1,at) );
	
	// get the 2 fixed points
	vec2 one = vec2( 1.0, 0.0 );

    vec2 fix1_1 = 0.5*( one + csqrt( one - 4.0*c ) );
    vec2 fix1_2 = 0.5*( one - csqrt( one - 4.0*c ) );
	vec2 fix2_1 = -(csqrt(-4.0*c-3.0*one)+one)/2.0;
	vec2 fix2_2 =  (csqrt(-4.0*c-3.0*one)-one)/2.0;
	vec2 fix2_3 = -(csqrt( one-4.0*c)-one)/2.0;
	vec2 fix2_4 =  (csqrt( one-4.0*c)+one)/2.0;

		
	vec2 z = p;
	vec2 dz = vec2( 1.0, 0.0 );

	vec2 ph = z;
	vec2 gr = vec2( log(length(z)), atan(z.y,z.x) );
	float t = 0.0;

	for( int i=0; i<512; i++ )
	{
		if( dot(z,z)>10000.0 ) continue;

        t += 1.0;

        // derivative
        dz = 2.0*cmul( z, dz );

        // point
        z = cmul(z,z) + c;

        vec2 a = cdiv(z,z-c);
        float s = pow( 0.5, t );

        // phi
        ph = cmul( ph, cpow(a, s) );
		
        // green
        gr.x += log(length(a)) * s;
        float aa = atan(a.y,a.x);
        if( isInTriangle( z, vec2(0.0), fix1_2, c ) )
        {
            aa -= sign(aa)*2.0*3.14159;
        }
        gr.y += aa * s;
	}
	
	
	vec3 col = vec3(1.0,0.65,0.10);
	
	if( t<511.0 )
	{
        float s = pow( 0.5, t );
        vec2  phib = cpow( z, s );
        float phiR = length( phib );
        float greenR = log(length(z)) * s;
        float greenI = argument(z*s);
        float d = log( length(z) ) * length(z) / length(dz);
        vec2  gradG = -conj(cmul( dz, conj(z) ));
        float n = t/50.0;
        float sn = -log2(abs(greenR))/50.0;
	
        col = vec3( 0.6 + 0.4*dot(normalize(-gradG),vec2(0.707)) );

        col *= vec3( grid( ph ) );
        col *= vec3(1.0)*clamp(d*50.0,0.0,1.0);
	}
	else
	{
		z = p;

		float t = 0.0;
		for( int i=0; i<200; i++ )
		{
			if( length(z-fix1_2)>0.001 )
			{
			z = cmul(z,z) + c;
			t += 1.0;
			}
		}
		vec2 fix = fix1_2;
		if( length(2.0*fix1_1)<1.0 ) fix=fix1_1;
		if( length(2.0*fix)<1.0 )
		{
		    vec2 ph = cdiv( z - fix, cpow(2.0*fix,t) );
		    float g = log(length(ph));
		    float l = 1.0 - 0.1*smoothstep( 0.7, 0.71, sin(48.0*g) );
		    col += 0.1*(abs(g));
		    ph = 1.0*vec2( length(ph), atan(ph.y,ph.x)/3.14 );
			col *= l;
		}
		
	}

	// color depending of attractive/repulsive fixed point
	col = circle( col, vec3(1.0,1.0,1.0), p, c );

	vec3 col2 = vec3(0.0,1.0,0.0);
	col = circle( col, col2, p, fix2_1 );
	col = circle( col, col2, p, fix2_2 );
	col = circle( col, col2, p, fix2_3 );
	col = circle( col, col2, p, fix2_4 );

	vec3 col1 = vec3(0.0,0.7,1.0);
	col = circle( col, col1, p, fix1_1 );
	col = circle( col, col1, p, fix1_2 );

	fragColor = vec4( col, 1.0 );
}

Mandelbrot set[edit | edit source]

Boolean escape time[edit | edit source]

Mandelbrot set set :

  • boolean escape time method
    • solid color for exterior background_color = vec3(1.0, 0.0, 035);
  • solid color for interior mandel_color = vec3(0.0, 0.0, 0.0);

Plane description using :

short version[edit | edit source]

// https://www.shadertoy.com/view/4sVGWz
// Simple_Mandelbrot by Created by r1nat in 2016-Jan-29

//Based on explanation http://www.hiddendimension.com/fractalmath/Divergent_Fractals_Main.html
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 c = fragCoord.xy / iResolution.xy;
    //scaling real axis to [-2.5, 1.5] and  imaginary axis to  [-1.5, 1.5]
    c = c * vec2(4,3) - vec2(2.5, 1.5); 

    vec2 z = vec2(0);
    fragColor = vec4(0);
    
    for (int i=0;i<100;i++)
    {
        if (z.x * z.x + z.y * z.y >= 4.) 
        {
            fragColor = vec4(1);
            break;
        }
        
       z = vec2(z.x*z.x - z.y*z.y, 2.*z.x*z.y) + c;
    }
}


long version[edit | edit source]

// image parameters in world coordinate 
vec2 center = vec2(-0.75,0.0); // center of the image in world units : http://mightymandel.mathr.co.uk/gallery.html
float radius = 1.25; // Radius is defined as "the difference in imaginary coordinate between the center and the top of the axis-aligned view rectangle".

// escape time algorithm
 float er2 = 40.0; // square of escape radius :  er2 = er*er  so er = 2.0  
 #define imax 1000

// rgb colors 
vec3 background_color = vec3(1.0, 0.0, 035);
vec3 mandel_color = vec3(0.0, 0.0, 0.0);

// compute pixel coordinate in world units 
vec2 GiveCoordinate(vec2 center, float radius, vec2 fragCoord, vec3 iResolution)
{
  // from pixel to world coordinate   
  // start with pixel coordinate : now point=(0,0) is left bottom and point=(iResolution.x, iResolution.y) is right top   
  float x = (fragCoord.x -  iResolution.x/2.0)/ (iResolution.y/2.0);
  float y = (fragCoord.y -  iResolution.y/2.0)/ (iResolution.y/2.0);
  vec2 c = vec2(center.x + radius*x, center.y + radius*y) ;  
  return c ; // now coordinate are measured in world units : from 0.0 t 1.0
}
 
// square of vector ( = complex number) 
vec2 complex_square( vec2 v ) {
	return vec2(
		v.x * v.x - v.y * v.y,
		v.x * v.y * 2.0
	);
}

bool CheckIfIsInsideMandelbrot(vec2 c)
{
    int count=0;
    vec2 z = vec2(0.0, 0.0); // initial value is a critical point 
    
    // iterations 
    for ( int i = 0 ; i < imax; i++ ) {
 	z = c + complex_square( z ); // z = fc(z) = z^2+c
	count = i;
        if ( dot(z,z) > er2 ) {  break; } 
	}
    if (count==imax-1) 
         {return true;}
         else return false;
}

vec3 GiveColor ( vec2 c )
{
    bool IsInside =  CheckIfIsInsideMandelbrot(c); 
     
    if ( IsInside) {return mandel_color; }
    else return background_color;
}
 
void mainImage( out vec4 fragColor, in vec2 fragCoord)
{   
    vec2 c =  GiveCoordinate(center, radius, fragCoord, iResolution);
    vec3 color = GiveColor(c);     
    fragColor = vec4(color,1.0); //   
}

LSM[edit | edit source]

Mandelbrot set set :

Plane description using :

Result is here

// image parameters in world coordinate 
//vec2 center = vec2(-0.75,0.0); // center of the image in world units : http://mightymandel.mathr.co.uk/gallery.html
//float radius = 1.25; // Radius is defined as "the difference in imaginary coordinate between the center and the top of the axis-aligned view rectangle".
 vec2 center = vec2(-0.771139525,-0.115216065);
 float radius = 0.001;

// escape time algorithm
 float er2 = 4.0; // square of escape radius :  er2 = er*er  so er = 2.0  
 #define imax 500

// compute pixel coordinate in world units 
vec2 GiveCoordinate(vec2 center, float radius, vec2 fragCoord, vec3 iResolution)
{
  // from pixel to world coordinate   
  // start with pixel coordinate : now point=(0,0) is left bottom and point=(iResolution.x, iResolution.y) is right top   
  float x = (fragCoord.x -  iResolution.x/2.0)/ (iResolution.y/2.0);
  float y = (fragCoord.y -  iResolution.y/2.0)/ (iResolution.y/2.0);
  vec2 c = vec2(center.x + radius*x, center.y + radius*y) ;  
  return c ; // now coordinate are measured in world units : from 0.0 t 1.0
}
 
// based on the code by gltracy https://www.shadertoy.com/view/XsS3Rm
// square of vector ( = complex number) 
vec2 complex_square( vec2 v ) {
	return vec2(
		v.x * v.x - v.y * v.y,
		v.x * v.y * 2.0	);
}

// based on the code by gltracy https://www.shadertoy.com/view/XsS3Rm
int GiveLevel(vec2 c)
{
    int final_i = 0; // level
    vec2 z = vec2(0.0, 0.0); // initial value is a critical point 
    
  // iterations 
	for ( int i = 0 ; i < imax; i++ ) {
 
		z = c + complex_square( z ); // z = fc(z) = z^2+c
		final_i = i;
        if ( dot(z,z) > er2 ) {  break; } 
	}
  return final_i;          
    
}

vec3 GiveColor ( int i)
{
    
    vec3 color;
    
    if ( i < imax ) 
     // level set method  = LSM/M 
     // based on https://www.weheartswift.com/fractals-xcode-6/ by Silviu Pop 
     {  color.r = sin(float(i) / 3.0); // exterior of Mandelbrot set
        color.g = cos(float(i) / 6.0);
        color.b = cos(float(i) / 12.0 + 3.14 / 4.0);
    } 
    else color= vec3(0.0, 0.0, 0.0); // interior of mandelbrot set
    
    return color;
}
 
void mainImage( out vec4 fragColor, in vec2 fragCoord)
{   
    vec2 c =  GiveCoordinate(center, radius, fragCoord, iResolution);
    int level = GiveLevel(c );
    vec3 color = GiveColor(level);     
    fragColor = vec4(color,1.0); //   
}

binary decomposition[edit | edit source]

// image parameters in world coordinate 
vec2 center = vec2(-0.75,0.0); // center of the image in world units : http://mightymandel.mathr.co.uk/gallery.html
float radius = 1.5; // Radius is defined as "the difference in imaginary coordinate between the center and the top of the axis-aligned view rectangle".

// escape time algorithm
 float er2 = 100000.0; // square of escape radius :  er2 = er*er  so er = 1000.0;  
 #define imax 1000

// rgba colors 
vec4 up_color = vec4(1.0, 1.0, 1.0, 1.0);// target set up
vec4 down_color = vec4(0.0, 0.0, 0.0, 1.0); // target set down
vec4 mandel_color = vec4(0.0, 0.0, 0.0, 1.0); // inside

// compute pixel coordinate in world units 
vec2 GiveCoordinate(vec2 center, float radius, vec2 fragCoord, vec3 iResolution)
{
  // from pixel to world coordinate   
  // start with pixel coordinate : now point=(0,0) is left bottom and point=(iResolution.x, iResolution.y) is right top   
  float x = (fragCoord.x -  iResolution.x/2.0)/ (iResolution.y/2.0);
  float y = (fragCoord.y -  iResolution.y/2.0)/ (iResolution.y/2.0);
  vec2 c = vec2(center.x + radius*x, center.y + radius*y) ;  
  return c ; // now coordinate are measured in world units : from 0.0 t 1.0
}
 
// square of vector ( = complex number) 
vec2 complex_square( vec2 v ) {
	return vec2(
		v.x * v.x - v.y * v.y,
		v.x * v.y * 2.0
	);
}

int CheckType(vec2 c)
{
    int count=0;
    vec2 z = vec2(0.0, 0.0); // initial value is a critical point 
    
    // iterations 
    for ( int i = 0 ; i < imax; i++ ) {
 	z = c + complex_square( z ); // z = fc(z) = z^2+c
	count = i;
        if ( dot(z,z) > er2 ) {  break; } 
	}
    if (count==imax-1) 
         {return 0;}
         else 
              if (z.x>0.0) return 1; 
                         else return 2;
}

vec4 GiveColor ( vec2 c )
{
    int colorType =  CheckType(c); 
     
    if ( colorType==0) {return mandel_color; }
    if (colorType==1) return up_color;
    return down_color;
}
 
void mainImage( out vec4 fragColor, in vec2 fragCoord)
{   
    vec2 c =  GiveCoordinate(center, radius, fragCoord, iResolution);
    fragColor = GiveColor(c);     
       
}

Smooth coloring[edit | edit source]

//see http://linas.org/art-gallery/escape/escape.html for more info on normalizing the Mandelbrot escape
// Smooth Mandelbrot Created by Justaway in 2015-Jan-2
// https://www.shadertoy.com/view/ltXGDN

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    float e=100.0;
	vec2 c = vec2(
        (fragCoord.x-iResolution.x/2.0)/iResolution.y,
        (fragCoord.y-iResolution.y/2.0)/iResolution.y);
    c*=2.5;
    int ic=0;
    vec2 tz;
    vec2 z=vec2(0.0);
    for(int i=0;i<32;i++){
        if(length(z)<e){
            tz=z;
            z.x=tz.x*tz.x-z.y*tz.y+c.x;
            z.y=2.0*tz.x*tz.y+c.y;
            ic++;
        }
    }
    float m=float(ic)-(log(log(length(z))))/log(2.0);
    fragColor=vec4(abs(sin(m/5.0)));
}


// Mandelbrot set zoom, with smooth coloring (Douady-Hubbard) by iq]
// https://www.shadertoy.com/view/lllGWH 
// Created by inigo quilez - iq/2015
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

void mainImage( out vec4 f, in vec2 p )
{
    float n = 0.;
    vec2 c = vec2(-.745,.186) + 3. * (p.xy/iResolution.y-.5)*pow(.01,1.+cos(.2*iGlobalTime)), z=c*n;
    
    for( int i=0; i<128; i++ )
    {
        z = vec2( z.x*z.x - z.y*z.y, 2.*z.x*z.y ) + c;

        if( dot(z,z)>1e4 ) break;

        n++;
    }
    
    f = .5 + .5*cos( vec4(3,4,11,0) + .05*(n - log2(log2(dot(z,z)))) );
}

DEM[edit | edit source]

unrolled cardioid[edit | edit source]

// https://www.shadertoy.com/view/ldfSW4
// The trees are breathing Created by jld in 2014-May-24

#define M_PI 3.14159265358979323846
#define N 53

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	vec2 rth = fragCoord.xy / iResolution.xy * 2.0 * M_PI;
	rth.y *= iResolution.y / iResolution.x;
	rth.x += (iTime / 60.0) * 2.0 * M_PI;
	vec2 z0 = (1.0 + rth.y) * vec2(cos(rth.x), sin(rth.x)) / 2.0;
	vec2 z1 = vec2(1.0, 0.0) - z0;
	vec2 c = vec2(z0.x * z1.x - z0.y * z1.y, z0.x * z1.y + z0.y * z1.x);
	vec2 a = c;
	float g = 1.0;
	float thresh = 10.0 + 6.0 ;
	vec3 color = vec3(1.0, 1.0, 1.0);

	// color += (1.0 + cos (iTime)) * vec3(0.0, 0.007, 0.01) * clamp(z1.x - z0.x, -2.0, 3.0);
	
	for (int i = 0; i < N; ++i) {
		if (dot(a, a) > thresh) {
			break;
		}
		g *= 0.9;
	    a = vec2(a.x * a.x - a.y * a.y, 2.0 * a.x * a.y) + c;
	}

	fragColor = vec4(g * color, 1.0);
}

bof61[edit | edit source]

// https://www.shadertoy.com/view/4st3Wn 
// Filled Mandelbrot created by Kramin in 2015-Dec-1
#define AA 2

#define maxIteration 300
#define CX -0.75
#define CY 0.0
#define INVZOOM 2.5
#define T 20.0

float getColourValue(float mu, float s, float m, float e)
{
    if (mu<s) {
        return 0.0;
    } else if (mu<m) {
        return (mu - s)/(m-s);
    } else if (mu<e) {
        return 1.0 - (mu - m)/(e-m);
    }
    return 0.0;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    float modtime = iTime*1.5; //controls the slight pulsating
    float sinsq1 = max(0.0,sin(modtime)); sinsq1 = sinsq1*sinsq1;
    float sinsq2 = max(0.0,sin(modtime+0.75)); sinsq2 = sinsq2*sinsq2;
    float sinsq3 = max(0.0,sin(modtime+1.5)); sinsq3 = sinsq3*sinsq3;
    float sinsq4 = max(0.0,sin(modtime+2.25)); sinsq4 = sinsq4*sinsq4;
    float izoom = INVZOOM;
    vec3 colour = vec3(0.0,0.0,0.0);
#if AA>1
    for( int m=0; m<AA; m++ )
    for( int n=0; n<AA; n++ )
    {
    vec2 c = vec2(CX,CY) + (fragCoord+vec2(float(m),float(n))/float(AA)-iResolution.xy/2.0)*izoom/iResolution.y;
    float w = float(AA*m+n);
#else
    vec2 c = vec2(CX,CY) + (fragCoord-iResolution.xy/2.0)*izoom/iResolution.y;
#endif
	vec2 z = c;
	float iteration = float(maxIteration);
	
	float zlen = length(z);
	float minz = zlen;
	int minziter = 0;
	
	for (int i = 0; i<maxIteration; i++) {
        if (zlen > 3000.0) {
            iteration = float(i);
            break;
        }
        
		if (zlen < minz){
		  minziter = i;
		  minz = zlen;
		}
		
		// do z = z^2 + c
		z = mat2(z,-z.y,z.x)*z + c;
		
		zlen = length(z);
	}
    
	if (iteration < float(maxIteration)){
		//smooth colouring
		float mu = float(iteration) - log(log(length(vec2(z))))/0.6931471805599453; //log(2.0) = 0.6931471805599453
    	mu = max(mu,0.0);
		//transform to between 0 and 1
		//mu/(mu+constant) goes to 1 as mu goes to infinity and to 0 as mu goes to 0.
		//This transformation is much better than a simple mu = mu/maxIteration because it 
		//is independent of maxIteration
		mu=mu/(mu+T);
		
		//colour.x += getColourValue(mu,0.5,1.0,1.0) + getColourValue(mu,0.0,0.5,1.0)*0.9 + getColourValue(mu,-1.0,-0.5,0.5)*0.3;
		//colour.y += getColourValue(mu,0.5,1.0,1.0) + getColourValue(mu,0.0,0.5,1.0)*0.1 + getColourValue(mu,-1.0,-0.5,0.5)*0.0;
		//colour.z += getColourValue(mu,0.5,1.0,1.0) + getColourValue(mu,0.0,0.5,1.0)*0.1 + getColourValue(mu,-1.0,-0.5,0.5)*0.4;
        colour += getColourValue(mu,0.5+0.05*(-0.5*sinsq2+0.5),1.0,1.0) + (0.2*sinsq2+0.8)*getColourValue(mu,0.0,0.5,1.0)*vec3(0.867,0.282,0.078) + (0.2*sinsq1+0.8)*getColourValue(mu,-1.0,-0.5,0.5)*vec3(0.302,0.114,0.208);
	}
	else {
	  float mu = float(minziter);
	  mu = (0.5+0.25*(-0.2*sinsq4+0.8))*10.0/(mu+10.0)+0.25*(-0.2*sinsq3+0.8)*sqrt(minz);//sqrt(minz) adds a little gradient to the interior 
	  //colour.x += getColourValue(mu,0.0,0.7,1.0)*0.1 + getColourValue(mu,0.0,0.4,0.7)*0.0 + getColourValue(mu,0.0,0.1,0.5);
	  //colour.y += getColourValue(mu,0.0,0.7,1.0)*0.0 + getColourValue(mu,0.0,0.4,0.7)*0.6 + getColourValue(mu,0.0,0.1,0.5);
	  //colour.z += getColourValue(mu,0.0,0.7,1.0)*0.2 + getColourValue(mu,0.0,0.4,0.7)*0.8 + getColourValue(mu,0.0,0.1,0.5);
      colour += getColourValue(mu,0.0,0.7,1.0)*vec3(0.302,0.114,0.208) + getColourValue(mu,0.0,0.4,0.7)*vec3(0.867,0.282,0.078) + getColourValue(mu,0.0,0.1,0.5);
	}
#if AA>1
    }
    colour /= float(AA*AA);
#endif
  fragColor = vec4( colour.x, colour.y, colour.z, 1.0 );
}

References[edit | edit source]

  1. Shardertoy
  2. A Beginner's Guide to Coding Graphics Shaders by Omar Shehata15 Apr 2015
  3. NeHe : GLSL: An Introduction
  4. converting ShaderToy shaders
  5. Shader basic by Xor
  6. Shadertoy Primer for Non-Graphics Programmers by Michael Mara
  7. BLUR SHADERS #5 PART 2 by Xor
  8. Glsl Basics by Lukas Pukenis
  9. Shader Lesson by Matt DesLauriers edited this page on 12 Jul 2014