1 day 9: fractals jeff parker oct 2011. 2 gallery i downloaded some images…
Post on 21-Dec-2015
217 views
TRANSCRIPT
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
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
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);
}
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
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
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
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);}