I've animated the colours and properties of the flower and added a history buffer to the recursion. The result is that there is more depth to the sketch. If you want to run the sketch then you will have to allocate more memory to Processing (from the preferences). I've allocated 256MBytes. The other option is to reduce the size of the display window or history buffer, but I think the sketch works best with a deep history buffer.
ß e n
//
// Jim v1.1.
//
import processing.opengl.*;
//
// Dimensions of screen.
//
int kWidth = 640 ; //480 ;
int kHeight = 480 ; // 480 ; // 320 ;
//
// Dimensions of texture.
// For fast PCs reduce or remove the denominator.
//
int kTextureWidth = kWidth / 2 ;
int kTextureHeight = kHeight / 2 ;
//
// Defining properties of the flower.
//
float kInnerRadius = 200 ;
int kInnerCircles = 20 ;
int kRings = 8 ;
int kPetals = 4 ;
//
// Define a history buffer of screen textures.
//
int kHistoryLength = 100 ;
PImage[] history ;
void setup()
{
size( kWidth, kHeight, JAVA2D ) ;
colorMode( RGB, 1.0 ) ;
smooth() ;
//
// CReate the history buffer.
//
history = new PImage[ kHistoryLength ] ;
for ( int i = 0 ; i < kHistoryLength ; ++ i )
history[ i ] = createImage( kTextureWidth, kTextureHeight, RGB ) ;
}
void draw()
{
float t = millis() * 0.0001 ;
//
// Draw the texture to the 4 quadrants with
// reflections in horizontal and vertical reflection transforms.
//
pushMatrix() ;
int index = frameCount % kHistoryLength ;
image( history[ index ], 0, 0, kWidth /2, kHeight / 2 ) ;
scale( -1.0, 1.0 ) ;
image( history[ index ], - kWidth, 0, kWidth /2, kHeight / 2 ) ;
scale( - 1.0, -1.0 ) ;
image( history[ index ], 0, - kHeight, kWidth /2, kHeight / 2 ) ;
scale( -1.0, 1.0 ) ;
image( history[ index ], - kWidth, - kHeight, kWidth /2, kHeight / 2 ) ;
popMatrix() ;
//
// Fade the background a bit.
//
fill( 0, 0, 0, 0.45 ) ;
rect( 0, 0, kWidth, kHeight ) ;
//
// Draw a flower like object.
//
// color innerColour = color( noise( t*2.3, 0.1 ), noise( t*0.7, 0.2 ), noise( t, 0.3 ), 1.0 ) ;
// color outerColour = color( noise( t * 0.7, 0.3 ), noise( t*0.7, 1.5 ), noise( t * 1.3, 2.0 ), 0.5 + 0.5*noise(t) ) ;
color centralInnerColour = smoothColour( 0.05, 0.03, 0.09, 1.0 ) ;
color centralOuterColour = smoothColour( 0.05, 0.03, 0.09, 0.3 ) ;
color innerColour = smoothColour( 0.03, 0.05, 0.07, 1.0 ) ;
color outerColour = smoothColour( 0.3, 0.5, 0.7, 0.8 ) ;
translate( kWidth/2, kHeight/2 ) ;
//
// Draw the centre part.
//
noStroke() ;
for ( int i = kInnerCircles ; i >= 1 ; i -- )
{
fill( blendColour( centralInnerColour, centralOuterColour, i * 0.1 ) ) ;
ellipse( 0, 0, i * kInnerRadius / kInnerCircles, i * kInnerRadius / kInnerCircles ) ;
}
rotate( t * 3.0 ) ;
for ( int j = kRings - 1 ; j >=0 ; j -- )
{
stroke( 0.2 ) ;
fill( blendColour( innerColour, outerColour, float( j )/ kRings ) ) ;
int petals = ( j + 1 ) * kPetals ;
for ( int i = 0 ; i < petals ; ++ i )
{
if ( i % 4 != 0 )
{
pushMatrix() ;
float length = (10.0 + 5.0* noise( t*10.0, i * 0.01 ) ) * j ;
float width = length * noise( t*10.0, i + j ) * 0.75 ;
rotate( 2.0 * PI * i / petals + j * noise(t,j,i) ) ;
ellipse( 15.0 * j, 0, length, width ) ; // 10.0 - ( 10.0 - 30.0 ) * ( j / 8.0 ) ) ;
popMatrix() ;
}
}
}
//
// Use the current frame as the texture for the
// mirror in the next frame.
//
history[ frameCount % kHistoryLength ].copy( get(), 0, 0, width, height, 0, 0, kTextureWidth, kTextureHeight ) ;
}
color smoothColour( float s1, float s2, float s3, float a )
{
float t= millis() * 0.001 ;
float r = 0.5f + 0.5f * sin( t * s1 ) ;
float g = 0.5f + 0.5f * sin( t * s2 ) ;
float b = 0.5f + 0.5f * sin( t * s3 ) ;
return color( r, g, b, a ) ;
}
color blendColour( color c1, color c2, float p )
{
float r = red( c1 ) - ( red( c1 ) - red( c2 ) ) * p ;
float g = green( c1 ) - ( green( c1 ) - green( c2 ) ) * p ;
float b = blue( c1 ) - ( blue( c1 ) - blue( c2 ) ) * p ;
float a = alpha( c1 ) - ( alpha( c1 ) - alpha( c2 ) ) * p ;
return color( r, g, b, a ) ;
}