Luciferins

Handing color changes

Processing is an excellent environment for prototyping and working. It’s a great way for me to start to see how things can work together, as well as thinking through how to structure things programmatically.

Initially, I started working with color and working with different ways to change color. While at Eyeo 2013, I attended Memo Akten’s workshop – The Black Art of Manipulating Numbers – and Moritz Stefaner’s workshop – Smart Insects. Attendance to Eyeo and the workshops was possible with the support of my department – Design, Art & Technology at UArts.

Both workshops gave me different ideas for handling color changes and developing clouds of color.

//Info: http://processingjs.org/reference
float px, py;
float numPoints = 3000;
void setup() {
size(400, 400);
frameRate(5);
colorMode(RGB, 1.0);
background(0);
stroke(1, 1, 1);
strokeWeight(10);
}
void draw() {
background(0);

float curTime = millis()/1000.0;
//float theta = sin(curTime * 0.23) * TWO_PI; // play with this to
float theta = 0;
px = width/2;
py = height/2;

beginShape(LINES);
for (int i=0; i<numPoints; i++) {
stroke(
sin(curTime * 0.8f + i * 0.0011f) * 0.5f + 0.5f, //R
sin(curTime * 0.7f + i * 0.0013f) * 0.5f + 0.5f, //G
sin(curTime * 0.3f + i * 0.0017f) * 0.5f + 0.5f //B
);

theta += sin(curTime * 0.5f) * i * 0.00002; //everytime move, rotate a bit

float cos_t = cos(theta);
float sin_t = sin(theta);

px += cos_t * 0.3;
py += sin_t * 0.3;
vertex(px, py);
}

endShape();
}

I wanted to get a feeling of how this would look, projected on the felt strips. Without getting into protection mapping, I started to think through how this might transpire. The goals being: to have the colors projected only on the felt, and only upon disturbance (from the viewer). I put together this sketch to help give me a rough idea of the final output. I tweaked some parameters to get this timing and colors right.

//Info: http://processingjs.org/reference
import java.util.*; //need this for random
Random generator;

PGraphics g;

float num, x, y;
float sd, mean;

float theta, incrementer, rand, op;
int stepY, stepX;
void setup() {
size(400, 400, P2D);
frameRate(5);
colorMode(HSB, 1.0, 100, 100, 100);
sd = width/2;
mean = width/5;

g = createGraphics(width, height, P2D);
generator = new Random();

colorMode(HSB, 1.0, 100, 100);
rand = random(0.5, 0.6);

g.beginDraw();
g.background(0);

g.noStroke();
for (int i = 0; i < 15; i++) {
y = random(height/2, height-50);
num = (float) generator.nextGaussian();
x = sd * num + mean; //give it a random location within a range and mean
if (x < 0) { //make sure it doesn't go off the screen
x = x*(-1);
}
op = int(random(65, 95));
g.fill(255, op); //it'd be cool to get the opacity working on depth
g.rect(x, 0, 20, y);
}

g.endDraw();
}
void draw() {
//change the shift of color so it isn't in such a hard line. randomize it. blur it
//randomize X and Y within a given location

//shift the colors across the screen from right to left
noStroke();
float curTime = millis()/10000.0;
curTime = rand * curTime;
stepX = 2;
stepY = 2;
for (int gridY = 0; gridY < height; gridY += stepY) {
for (int gridX = 0; gridX < width; gridX += stepX) {
fill(sin(curTime * 0.8f + gridX * 0.0011f) * 0.5f + 0.5f, 100, 100);
rect(gridX, gridY, stepX, stepY);
}
}

// mask the original rectangles over the color field
blend(g, 0, 0, width, height, 0, 0, width, height, MULTIPLY);
}

After watching this run for a bit and thinking about the scale of the installation, I thought it wise to consider CPU and proper usage. It’s best to probably split the program across the GPU and CPU. I’m going to take a look at shaders and openGL. I’ve heard about them, seen their magic, but never used them. Diving in.