Newton Fractal Shader Sketch

Previously Newton Fractal Sketch I shared some regular JRubyArt sketches of the Newton fractal. Here I present a Shadertoy sketch wrapped for PiCrate (ruby-processing for the RaspberryPI).


The sketch

require 'picrate'
#---------------------------------------------------------
# ShaderToy: https://www.shadertoy.com/view/ltB3WW by tholzer
# Newton fractal with 3 or 4 or 5  symmetry (change #define NEWTON #).
# Press mouse button to change formula constants.
# info:     http://en.wikipedia.org/wiki/Newton_fractal
#---------------------------------------------------------

class NewtonFractal < Processing::App
  attr_reader :last_mouse_position, :mouse_click_state, :mouse_dragged
  attr_reader :newton

  def settings
    size(600, 600, P2D)
  end

  def setup
    sketch_title 'Newton Fractal Shader'
    @mouse_dragged = false
    @mouse_click_state = 0.0
    # Load the shader file from the "data" folder
    @newton = load_shader(data_path('newton_shader.glsl'))
    # Assume the dimension of the window will not change over time
    newton.set('iResolution', width.to_f, height.to_f, 0.0)
    @last_mouse_position = Vec2D.new(mouse_x.to_f, mouse_y.to_f)
  end

  def draw
    # mouse pixel coords. xy: current (if MLB down), zw: click
    if mouse_pressed?
      @last_mouse_position = Vec2D.new(mouse_x.to_f, mouse_y.to_f)
      @mouse_click_state = 1.0
    else
      @mouse_click_state = 0.0
    end
    newton.set('iMouse', last_mouse_position.x, last_mouse_position.y, mouse_click_state, mouse_click_state)
    # Apply the specified shader to any geometry drawn from this point
    shader(newton)
    # Draw the output of the shader onto a rectangle that covers the whole viewport.
    rect(0, 0, width, height)
  end
end

NewtonFractal.new

The wrapped shader:-

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

// ----------------------
// SHADERTOY UNIFORMS  -
// ----------------------

uniform vec3      iResolution;           // viewport resolution (in pixels)
uniform int       iFrame;                // shader playback frame

uniform vec4      iMouse;                // mouse pixel coords. xy: current (if MLB down), zw: click

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

void main() {
    mainImage(gl_FragColor,gl_FragCoord.xy);
}

// ------------------------------
//  SHADERTOY CODE BEGINS HERE  -
// ------------------------------


//---------------------------------------------------------
// Shader:   Newton5Fractal.glsl  by tholzer
// Newton fractal with 3 or 4 or 5  symmetry (change #define NEWTON #).
// Press mouse button to change formula constants.
//           v1.0  2015-04-14
//           v1.1  2017-04-06  define NEWTON added
// tags:     2d, attractor, newton, fractal, complex, number
// info:     http://en.wikipedia.org/wiki/Newton_fractal
//---------------------------------------------------------

#define ITER 12
#define NEWTON 3   // 2,3,4,5

//---------------------------------------------------------
vec2 cinv(in vec2 a)            { return vec2(a.x, -a.y) / dot(a, a); }

vec2 cmul(in vec2 a, in vec2 b) { return vec2(a.x*b.x - a.y*b.y,   a.x*b.y + a.y*b.x); }

vec2 cdiv(in vec2 a, in vec2 b) { return cmul(a, cinv(b)); }
//---------------------------------------------------------
vec2 newton( in vec2 z )
{
  for (int i = 0; i < ITER; i++)
  {
    vec2 z2 = cmul(z, z);
    vec2 z3 = cmul(z2, z);
    vec2 z4 = cmul(z2, z2);
    vec2 z5 = cmul(z3, z2);

//---> change z calculation by uncomment different lines
#if NEWTON==2
    z -= cdiv(z3 - 1.0, 3.0 * z2);                      // original: z^3 - 1  / ( 3*z^2)
#elif NEWTON==3
    z -= cdiv(z3 - 0.5+0.05*iMouse.y, (0.5+0.01*iMouse.x) * z2);  // z^3 - my / (mx*z^2)
#elif NEWTON==4
    z -= cdiv(z4 - 0.5+0.05*iMouse.y, (0.5+0.01*iMouse.x) * z3);  // z^4 - my / (mx*z^3)
#elif NEWTON==5
    z -= cdiv(z5 - 0.5+0.05*iMouse.y, (0.5+0.1*iMouse.x) * z4);  // z^5 - my / (mx*z^4)
#endif
  }
  return z;
}
//---------------------------------------------------------
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
  vec2 uv = -1.0 + 2.0 * fragCoord.xy / iResolution.xy;
  uv.x *= iResolution.x / iResolution.y;
  vec2 z = newton(uv);
  fragColor = vec4(z.x, z.y, -z.y, 1.0);
}


// ----------------------------
//  SHADERTOY CODE ENDS HERE  -
// ----------------------------
3 Likes

Maybe it’s not the same tholtzer, but I found these Desert sand waves very impressive.

1 Like