1 day 9: fractals jeff parker oct 2011. 2 gallery i downloaded some images…

71
1 Day 9: Fractals Jeff Parker Oct 2011

Post on 21-Dec-2015

217 views

Category:

Documents


2 download

TRANSCRIPT

1

Day 9: Fractals

Jeff ParkerOct 2011

2

Gallery

I downloaded some images…

3

Gallery

Susan Powell – note textures for moon, ground

4

Gallery

Rad Ramin

5

Gallery

Adam Hartford

6

Gallery

Jamie Valencia

7

Gallery

Theresa Silver

8

Gallery

Brian Pierce

9

Gallery

Andrew Berg

10

Gallery

Juan Bustamante

11

Gallery

Andrew Davenport POVRay

12

Gallery

Andrew Davenport POVRayAndrew Davenport POVRay

13

Gallery

Andrew Davenport POVRayAndrew Davenport POVRay

14

Outline

We will be looking ahead to the next assignment – FractalsStart with Koch SnowflakeHeighway Dragon CurveLindenmayer Systems (aka L-Systems)

Application to drawing TreesMandelbrot Set

Three waysLook at Angel's example, which I want you to extend

If we have time, we will dip our toes into Chaos

15

Fractals - Snowflake curve

Koch Snowflake was discovered by Helge von Koch in 1904. Start with a triangle inscribed in the unit circleTo build the level n snowflake, we replace each edge in the

level n-1 snowflake with the following patternThe perimeter of each version is 4/3 as long

Infinite perimeter, but snowflake lies within unit circle, so has finite area

16

Recursive Step

void toEdge(int size, int num) {if (1 >= num)

turtleDrawLine(size);else {

toEdge(size/3, num-1);turtleTurn(300);toEdge(size/3, num-1);turtleTurn(120);toEdge(size/3, num-1);turtleTurn(300);toEdge(size/3, num-1);

}}

17

Turtle Library

/** Draw a line of length size */

void turtleDrawLine(GLint size)

glVertex2f(xPos, yPos);

turtleMove(size);

glVertex2f(xPos, yPos);

}

int turtleTurn(int alpha) {

theta = theta + alpha;

theta = turtleScale(theta);

return theta;

}

/** Move the turtle. Called to move and by DrawLine */

void turtleMove(GLint size) {

xPos = xPos + size * cos(DEGREES_TO_RADIANS * theta);

yPos = yPos + size * sin(DEGREES_TO_RADIANS * theta);

}

18

Dimension of Koch Curve

If we measure the length of this room with a yardstick and get 4 units, and measure again with a foot ruler, we would expect to see 12 units.

If we measure the area of this room with a unit yard square and get 30 units, and then measure with a unit foot square, we would expect to get 270 units.

The length is one dimensional, and the area is two dimensional

19

Length of Curve

How long is the perimeter?Assume I have a yardstick, and the original triangle edge is

36 inchesLength is 3 yards, or 9 feet

Now assume I have a foot ruler. Cannot span a yard: each edge is now 4 feet long

Length is 12 feet

If I use a smaller ruler, the length is even longer

20

How long is the coast of Britain?

How Long Is the Coast of Britain? Statistical Self-Similarity and Fractional Dimension, by Benoit Mandelbrot

21

How long is the coast of Britain?

22

Dimension of Koch Curve

If we measure the length of this room with a yardstick and get 4 units, and measure again with a foot ruler, we would expect to see 12 units.

If we measure the area of this room with a unit yard square and get 30 units, and then measure with a unit foot square, we would expect to get 270 units.

The length is one dimensional, and area is two dimensional

The length of the Koch snowflake is neither 1 dimensional (length grows) 2 dimensional (doesn't grow fast enough)

It is given a fractional dimension:

ln 4

ln 3=1.26186

23

More images

24

More images

25

More images

26

More images

27

More images

28

More images

29

Dragon Curve

The Dragon Curve is due to Heighway

One way to generate the curve is to start with a folded piece of paper

We can describe a curve as a set of turtle directions

The second stage is simply

Take one step, turn Right, and take one step

The next stage is

Take one step, turn Right, take one step

Turn Right

Perform the original steps backwards, or

Take one step, turn Left, take one step

Since the step between turns is implicit, we can write this as RRL

The next stage is

30

Dragon Curve

The Dragon Curve is due to Heighway

One way to generate the curve is to start with a folded piece of paper

We can describe a curve as a set of turtle directions

The second stage is simply

Take one step, turn Right, and take one step

The next stage is

Take one step, turn Right, take one step

Turn Right

Perform the original steps backwards, or

Take one step, turn Left, take one step

Since the step between turns is implicit, we can write this as RRL

The next stage is

RRL R RLL

31

How can we program this?

We could use a large array representing the turnsRRL R RLL

To generate the next level, append an R and walk back to the head, changing L’s to R’s and R’s to L’s and appending the result to end of array

But there is another way.

Start with a lineAt every stage, we replace the line with a right angleWe have to remember which side of the line to decorate (use variable “direction”)One feature of this scheme is that the “head” and “tail” are fixed

R R L R R L L

32

Dragon Curve

void dragon(int size, int level, int direction, int alpha)

{

/* Add on left or right? */

int degree = direction * 45;

turtleSet(alpha);

if (1 == level) {

turtleDrawLine(size);

return;

}

size = size/scale; /* scale == sqrt(2.0) */

dragon(size, level - 1, 1, alpha + degree);

dragon(size, level - 1, -1, alpha - degree);

}

33

Dragon Curve

When we divide an int (size) by a real (sqrt(2.0)) there is roundoff error, and the dragon slowly shrinks

The on-line version of this program precomputes sizes per level and passes them through, as below

int sizes[] = {0, 256, 181, 128, 90, 64, 49, 32, 23, 16, 11, 8, 6, 4, 3, 2, 2, 1, 0};

...

dragon(sizes[level], level, 1, 0);

...

void dragon(int size, int level, int direction, int alpha)

{

...

/* size = size/scale; */

dragon(size, level - 1, 1, alpha + degree);

dragon(size, level - 1, -1, alpha - degree);

}

34

Gosper Flowsnake

35

Lindenmayer Systems

Rewriting rulesStart:

S Rewrite Rule

S -> S R S L L S R S

Lindenmayer's first systemStart

ARewrite

A -> ABB -> A

Start with SSS

36

Lindenmayer Systems

variables : 0, 1constants: [, ]Start: 0Rewrite Rules : (1 → 11), (0 → 1[0]0)Start: 01st recursion: 1[0]02nd recursion: 11[1[0]0]1[0]03rd recursion:1111[11[1[0]0]1[0]0]11[1[0]0]1[0]0

37

Lindenmayer Systems

variables : 0, 1constants: [, ]Start: 0Rewrite Rules : (1 → 11), (0 → 1[0]0)Start: 01st recursion: 1[0]02nd recursion: 11[1[0]0]1[0]03rd recursion: 1111[11[1[0]0]1[0]0]11[1[0]0]1[0]00: draw a line segment ending in a leaf1: draw a line segment[: push position and angle, turn left 45 degrees]: pop position and angle, turn right 45 degrees

Tree

This is harder to do from scratch

Jon Squire's fractalgl

static void drawbranch(float widthl, int x0, int y0, int x1, int y1){ if(widthl < 1.5f) { glLineWidth(1.0); glBegin(GL_LINES); glVertex2f(x0, y0); glVertex2f(x1, y1); glEnd(); } glLineWidth(widthl); glBegin(GL_LINES); glVertex2f(x0, y0); glVertex2f(x1, y1); glEnd(); return;}

Jon Squire's fractalgl

static void generate(float x, float y, float widtht, float height, float angle, int level){ ... if (level>0) { turtle_theta = point(x, y, x1, y01); turn(left_angle); generate(turtle_x, turtle_y, left_width_factor*widtht, left_height_factor*height, left_angle, level); turtle_theta = point(x, y, x1, y01); turn(-right_angle); generate(x1, y01, left_width_factor*widtht, left_height_factor*height, right_angle, level); }} /* end generate */

Jon Squire's fractalgl

static void generate(float x, float y, float widtht, float height, float angle, int level){ ... if(level<3) { glColor3f(0.0, 1.0, 0.0); drawbranch(widtht, (int)x, (int)y, (int)x1, (int)y01); } else { glColor3f(0.0, 0.0, 0.0); drawbranch(widtht, (int)x, (int)y, (int)x1, (int)y01); } ...} /* end generate */

Jon Squire's fractalgl

42

Mandlebrot Set

Interesting FractalSelf SimilarHas a wide range of interesting habitats

43

Mandelbrot Set

The Mandelbrot Set M is based on work by Fatou and JuliaDescription of set M is quite indirect

Define a function fc from the complex plane to itself

fc : C ---> C

fc(z) = z2 + c

44

Mandelbrot Set

fc : C ---> C

fc(z) = z2 + c

We look at iterations of fc upon the point z0 = 0

fc3(z0) = fc

3(0) = fc(fc(fc(0)))

We say c is in the Mandelbrot Set M if

lim fcn(z0) is finite as n goes to infinity

45

Let’s compute some short examples

Reminder: fc(z) = z2 + c

If c = 0, the sequence fcn(0) is f0(0) = z2 + 0 = 0

0, 0, 0, 0, 0, 0… So point 0 is in the set

If c = 1, the sequence fcn(0) is f1(0) = z2 + 1

0, 1, 2, 5, 26, … So point 1 is not in the set

(We start with fc0(0) = 0 in all examples)

If c = 1/2, the sequence fcn(0) is

0, 1/2, 3/4, 1 1/16, 1 161/256, … So 1/2 is not in the set

If c = -2, the sequence fcn(0) is

0, -2, 2, 2, 2… So point -2 is in the set

If c = -1, the sequence fcn(0) is periodic

0, -1, 0, -1, 0, -1… So point -1 is in the set

If c = i, the sequence fcn(0) is fi(0) = z2 + i

0, i, -1 + i, -i, -1 + i, -i… So point i is in the set

46

Computing Mandelbrot Set

We say c is in the Mandelbrot Set M if

lim fcn(0) does not go to infinity as n goes to infinity

Practically, we say that point c is not in M if for some k,

| fck(0) | > 2 where fc(z) = z2 + c

Our algorithm is:

For each c in the complex plane, build function fc

Iterate, computing fck(0) until magnitude is greater than 2, or k >

MAXColor the screen – here are three alternatives

Directly through glDrawPixels() call – Angel 5th EditionBuild a texture and pass it to the GPU – Angel 6th EditionLet the GPU color each point – Orange Book Frag. Shader

Angel's Version 6th edition/* default data*/#define CENTERX -0.5#define CENTERY 0.5#define HEIGHT 0.5#define WIDTH 0.5#define MAX_ITER 100

/* N x M array to be generated */#define N 512#define M 512

47

Generating an image by hand

48

Generating an image by hand

float x = i * ( width / (n - 1) ) + cx - width / 2;float y = j * ( height / ( m - 1 ) ) + cy - height / 2;Complex c( 0.0, 0.0 );Complex p( x, y );float v;for ( int k = 0; k < max; k++ ) {

// compute c = c^2 + pc *= c;c += p;v = norm( c );if ( v > 4.0 )

break; /* assume not in set if mag > 4 */}

49

Computing ColorsGLfloat image[N][M][3];

for ( int k = 0; k < max; k++ ) {c *= c; // compute c = c^2 + pc += p;v = norm( c );if ( v > 4.0 )

break; /* assume not in set if mag > 4 */}if ( v > 1.0 )

v = 1.0; /* clamp if > 1 */image[i][j][0] = v;image[i][j][1] = Random();image[i][j][1] = 2.0 * sin( v ) - 1.0;image[i][j][2] = 1.0 – v;

50

Computing ColorsGLfloat image[N][M][3];

for ( int k = 0; k < max; k++ ) {c *= c; // compute c = c^2 + pc += p;v = norm( c );if ( v > 4.0 )

break; /* assume not in set if mag > 4 */}if ( v > 1.0 )

v = 1.0; /* clamp if > 1 */image[i][j][0] = v;image[i][j][1] = Random();image[i][j][1] = 2.0 * sin( v ) - 1.0;image[i][j][2] = 1.0 – v;

51

init()glActiveTexture( GL_TEXTURE0 );GLuint texture;glGenTextures( 1, &texture );glBindTexture( GL_TEXTURE_2D, texture );glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, n, m, 0, GL_RGB,

GL_FLOAT, image );glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,

GL_REPEAT );glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,

GL_REPEAT );glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,

GL_NEAREST );glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,

GL_NEAREST );

52

53

Color Scheme

We say c is in the Mandelbrot Set M if

lim fcn(0) does not go to infinity as n goes to infinity

Practically, we say that point c is not in M if for some k,

| fck(0) | > 2 where fc(z) = z2 + c

Our algorithm is:

For each c in the complex plane, build function fc

Iterate, computing fck(0) until magnitude is greater than 2, or k > MAX

If k is MAX, color point c black (c is in the set)If k is small, color point c blue (really cold: escaped quickly)If k is large, color point c red (really warm: almost made it into the set)

We use random green values at different levels to give contours

Assignment

Angel's version draws only a part of the set: start with the full set.

The current version does not present the standard view: modify it so that the curve is symmetric about the x axis rather than the y axis (below, right, rather than upper right)

Rework the color scheme. Usually items in the set are colored black, and points outside the set are given different colors depending on the number of iterations it takes to escape a circle of radius 2.

The current version uses floats: to explore the set in detail, you will want to use doubles to hold the values.

Revise the computation of x in the main loop to reduce the amount of work

Rewrite the evaluations of the function to reduce the number of floating point operations and function calls. This is the inner loop, and deserves attention. (See next slide)

Add a mouse handler to control zooming in and out. You will find it simplest to take a mouse click, translate to model coordinates, and then recalibrate.

A single click should zoom in.

A shift click should zoom out.

Add comments to explain what Angel is doing.

54

55

Prior Version

/* complex iteration */for(k=0; k<max; k++){

mult(c,c,d);add(d,c0,c);v=mag2(c); /* Compute mag squared */if (v > 4.0)

break; /* assume not in set if mag > 4 */}

if ( v > 1.0) v=1.0; /* clamp if > 1 */

image[i][j]=255*v;

What is the effect of Angel's use of color?

56

Utilities

void add(complex a, complex b, complex p){ p[0]=a[0]+b[0]; p[1]=a[1]+b[1];}

void mult(complex a, complex b, complex p){ p[0]=a[0]*b[0]-a[1]*b[1]; p[1]=a[0]*b[1]+a[1]*b[0];}

float mag2(complex a){ return(a[0]*a[0]+a[1]*a[1]);}

57

Color Ramp

/* define pseudocolor maps, ramps for red and blue, random for green */

for(i=0;i<256;i++){

redmap[i]=i/255.;greenmap[i]=rand()%255;bluemap[i]=1.0-i/255.;

}

glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, redmap);glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, greenmap);glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 256, bluemap);

58

Loopfor (i=0; i<n; i++)

for(j=0; j<m; j++) {

/* starting point */x= i *(width/(n-1)) + cx -width/2;y= j *(height/(m-1)) + cy -height/2;

form(0,0,c);form(x,y,c0);/* complex iteration */for(k=0; k<max; k++){

mult(c,c,d);add(d,c0,c);...

59

Inner Loopfor (i=0; i<n; i++)

for(j=0; j<m; j++) {

.../* complex iteration */for(k=0; k<max; k++){

mult(c,c,d);add(d,c0,c);v=mag2(c);if(v>4.0) break; /* assume not in set if mag > 4 */

}

60

Color Rampfor (i=0; i<n; i++)

for(j=0; j<m; j++) { ...

for(k=0; k<max; k++){

mult(c,c,d);add(d,c0,c);v=mag2(c);if(v>4.0) break; /* not in set if mag > 4 */

}/* assign gray level to point based on its magnitude */if(v>1.0) v=1.0; /* clamp if > 1 */image[i][j]=255*v;

}

61

Displayvoid form(float a, float b, complex p){

p[0]=a;p[1]=b;

}

void display(){

glClear(GL_COLOR_BUFFER_BIT);glDrawPixels(n, m, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image);

glFlush();}

62

Faster inner loop (look at prior version)for(k=0; k<max; k++)

{

mult(c,c,d);

add(d,c0,c);

v=mag2(c);

if (v > 4.0)

break; /* assume not in set if mag > 4 */

}

void mult(complex a, complex b, complex p)

{

p[0]=a[0]*b[0]-a[1]*b[1];

p[1]=a[0]*b[1]+a[1]*b[0];

}

void add(complex a, complex b, complex p)

{

p[0]=a[0]+b[0];

p[1]=a[1]+b[1];

}

float mag2(complex a)

{

return(a[0]*a[0]+a[1]*a[1]);

}

But we have a special multiplication: z*z, so a[0] = b[0] and a[1] =b[1]

This is the inner loop: it may pay to undwind it, avoiding the 3 function calls

Note that Angel avoids taking square root

Mouse Callback

When the user clicks on the screen, want to map from screen coordinates back to world coordinates

Take that as the new center, and change the width we display

Halve size if shift is not down (zoom in)Double size if shift is down (zoom out)

It may be simplest to keep the center of the screen and a "radius"

When we click hereZoom in centered on this point

64

Mapping back

How do you take a position and map back to the real coordinates?

What does a click here mean?Map this back to the x and y coordinate

Image is N pixels wide

65

Orange Bookstatic struct uniform_info Uniforms[] = {

/* vertex */{ "LightPosition", 3, GL_FLOAT, { 0.1, 0.1, 9.0, 0}, -1 },{ "SpecularContribution", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },{ "DiffuseContribution", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },{ "Shininess", 1, GL_FLOAT, { 20.0, 0, 0, 0 }, -1 },/* frag */{ "MaxIterations", 1, GL_FLOAT, { 12, 0, 0, 0 }, -1 },{ "Zoom", 1, GL_FLOAT, { 0.125, 0, 0, 0 }, -1 },{ "Xcenter", 1, GL_FLOAT, { -1.5, 0, 0, 0 }, -1 },{ "Ycenter", 1, GL_FLOAT, { .005, 0, 0, 0 }, -1 },{ "InnerColor", 3, GL_FLOAT, { 1, 0, 0, 0 }, -1 },{ "OuterColor1", 3, GL_FLOAT, { 0, 1, 0, 0 }, -1 },{ "OuterColor2", 3, GL_FLOAT, { 0, 0, 1, 0 }, -1 },

66

Orange Book//// Vertex shader for drawing the Mandelbrot set//// Authors: Dave Baldwin, Steve Koren, Randi Rost// based on a shader by Michael Rivero//// Copyright (c) 2002-2005: 3Dlabs, Inc.//// See 3Dlabs-License.txt for license information//

uniform vec3 LightPosition;uniform float SpecularContribution;uniform float DiffuseContribution;uniform float Shininess;

67

Orange Bookvarying float LightIntensity;varying vec3 Position;

void main(){

vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Vertex);vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal);vec3 lightVec = normalize(LightPosition - ecPosition);vec3 reflectVec = reflect(-lightVec, tnorm);vec3 viewVec = normalize(-ecPosition);float spec = max(dot(reflectVec, viewVec), 0.0);spec = pow(spec, Shininess);LightIntensity = DiffuseContribution * max(dot(lightVec, tnorm), 0.0) +

SpecularContribution * spec;Position = vec3(gl_MultiTexCoord0 - 0.5) * 5.0;gl_Position = ftransform();

}

68

Orange Book// Fragment shader for drawing the Mandelbrot set// Authors: Dave Baldwin, Steve Koren, Randi Rost// based on a shader by Michael Rivero//// Copyright (c) 2002-2005: 3Dlabs, Inc.//// See 3Dlabs-License.txt for license informationvarying vec3 Position;varying float LightIntensity;

uniform float MaxIterations;uniform float Zoom;uniform float Xcenter;uniform float Ycenter;uniform vec3 InnerColor;uniform vec3 OuterColor1;uniform vec3 OuterColor2;

69

Count to 12void main(){

float real = Position.x * Zoom + Xcenter;float imag = Position.y * Zoom + Ycenter;float Creal = real; // Change this line...float Cimag = imag; // ...and this one to get a Julia set

float r2 = 0.0;float iter;

for (iter = 0.0; iter < 12 && r2 < 4.0; ++iter){

float tempreal = real;

real = (tempreal * tempreal) - (imag * imag) + Creal;imag = 2.0 * tempreal * imag + Cimag;r2 = (real * real) + (imag * imag);

}

70

Colorvoid main(){

...// Base the color on the number of iterationsvec3 color;

if (r2 < 4.0)color = InnerColor;

elsecolor = mix(OuterColor1, OuterColor2, fract(iter * 0.05));

color *= LightIntensity;

gl_FragColor = vec4(color, 1.0);}

71

Summary

Fractals arise in Nature