Our three words are:
Our idea was to create an alternate reality where multiple things are getting revealed and also lost as time passes by. We thought of an analogy for life, where things change forever and others return in some kind of cycle. Pointing towards each of our elements:
The color and the window number, in this case, are representing the ciclic element that goes away but also come back in some form of another. We can think about it as any kind of past-trauma that comes back in a variety of ways to teach us to overcome it.
The video camera content can just change inadvertently and forever. Meaning that whatever image was shown before may not be shown again at all or not in the same precise way. This infinite possibilities represent the things in life that just were and don’t come back.
We got inspired by the effect of a cube when is being illuminated by different angles and how a rotating light would lit differently each face as it rotates. Resulting in subtle but noticeable levels of brightness and darkness. We tried something about it at first. However, we thought that we were deviating a little too much from the pixels practice and what we learn in class for this assignment. The following code is some kind of prototype of what we intended at first.
let capture;
let grid = 3;
let cellWidth, cellHeight;
let flashOffset = 0;
const ASPECT_RATIO = 4 / 3;
function setup() {
createCanvas(800, 600);
pixelDensity(1);
colorMode(RGB, 255);
// colorMode(HSB);
capture = createCapture(VIDEO);
capture.hide();
updateCellSize();
}
function updateCellSize() {
cellHeight = height / grid;
cellWidth = cellHeight * ASPECT_RATIO;
}
function draw() {
background(0);
flashOffset += 0.2;
if (capture.loadedmetadata) {
capture.loadPixels();
loadPixels();
// Calculate flash intensity (0~255) and convert to 0~1 ratio (for mixing)
let flashAlpha = sin(flashOffset) * 127.5;
let alphaRatio = flashAlpha / 255; // Ratio between 0~1
const gridStartX = (width - grid * cellWidth) / 2;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const col = floor((x - gridStartX) / cellWidth);
const row = floor(y / cellHeight);
const inGrid =
col >= 0 &&
col < grid &&
row >= 0 &&
row < grid &&
x >= gridStartX &&
x < gridStartX + grid * cellWidth;
if (inGrid) {
// Calculate corresponding pixel position in the video (horizontal flip)
const videoX =
capture.width -
1 -
floor(
(x - gridStartX - col * cellWidth) * (capture.width / cellWidth)
);
const videoY = floor(
(y - row * cellHeight) * (capture.height / cellHeight)
);
const videoIndex = (videoY * capture.width + videoX) * 4;
if (videoIndex >= 0 && videoIndex < capture.pixels.length - 3) {
let r = capture.pixels[videoIndex];
let g = capture.pixels[videoIndex + 1];
let b = capture.pixels[videoIndex + 2];
// Flash effect: calculate mixed value manually without lerp()
const isWhiteFlash = (row + col) % 2 === 0;
if (isWhiteFlash) {
// White flash: original color + (white - original color) × ratio
r = r + (255 - r) * alphaRatio;
g = g + (255 - g) * alphaRatio;
b = b + (255 - b) * alphaRatio;
} else {
// Black flash: original color + (black - original color) × ratio
r = r + (0 - r) * alphaRatio;
g = g + (0 - g) * alphaRatio;
b = b + (0 - b) * alphaRatio;
}
// Ensure color values are within 0~255 range (prevent overflow)
r = constrain(r, 0, 255);
g = constrain(g, 0, 255);
b = constrain(b, 0, 255);
const canvasIndex = (y * width + x) * 4;
pixels[canvasIndex] = 255 - r;
pixels[canvasIndex + 1] = 169 - g;
pixels[canvasIndex + 2] = b;
pixels[canvasIndex + 3] = 255;
} else {
// Keep black outside the grid
const canvasIndex = (y * width + x) * 4;
pixels[canvasIndex] = 0;
pixels[canvasIndex + 1] = 0;
pixels[canvasIndex + 2] = 0;
pixels[canvasIndex + 3] = 255;
}
}
}
updatePixels();
}
}
function windowResized() {
resizeCanvas(900, 900);
updateCellSize();
}
}
Our final version is getting a capture video, placing/copying across a canvas that keeps adding and diminishing the size of the grid as well as getting the colors to rotate according the hue color wheel.
let capture;
let grid = 1; // Current grid size (with smooth transition)
let targetGrid = 1; // Target grid size
let gridStep = 0.3; // Speed of grid size change
let direction = 1; // 1 = increasing, -1 = decreasing
let cellWidth, cellHeight;
let hueOffset = 0; // Hue offset for color wheel rotation
const ASPECT_RATIO = 4 / 3;
const MAX_GRID = 10; // Maximum grid size
const MIN_GRID = 1; // Minimum grid size
function setup() {
createCanvas(800, 600);
pixelDensity(1);
colorMode(HSB, 360, 100, 100);
capture = createCapture(VIDEO);
capture.hide();
updateCellSize();
}
function updateCellSize() {
const currentGrid = floor(grid);
cellHeight = height / currentGrid;
cellWidth = cellHeight * ASPECT_RATIO;
}
function draw() {
background(0);
hueOffset = (hueOffset + 5) % 360;
// Update grid size with smooth transition
if (abs(grid - targetGrid) > 0.1) {
grid += gridStep * direction;
} else {
// Change direction when reaching boundaries
if (targetGrid === MAX_GRID) {
direction = -1; // Start decreasing
targetGrid = MIN_GRID;
} else if (targetGrid === MIN_GRID) {
direction = 1; // Start increasing
targetGrid = MAX_GRID;
}
}
updateCellSize();
if (capture.loadedmetadata) {
capture.loadPixels();
loadPixels();
const currentGrid = floor(grid);
const gridStartX = (width - currentGrid * cellWidth) / 2;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const col = floor((x - gridStartX) / cellWidth);
const row = floor(y / cellHeight);
const inGrid = col >= 0 && col < currentGrid && row >= 0 && row < currentGrid &&
x >= gridStartX && x < gridStartX + currentGrid * cellWidth;
const canvasIndex = (y * width + x) * 4;
if (inGrid) {
const videoX = capture.width - 1 - floor(
(x - gridStartX - col * cellWidth) * (capture.width / cellWidth)
);
const videoY = floor(
(y - row * cellHeight) * (capture.height / cellHeight)
);
const videoIndex = (videoY * capture.width + videoX) * 4;
if (videoIndex >= 0 && videoIndex < capture.pixels.length - 3) {
const r = capture.pixels[videoIndex];
const g = capture.pixels[videoIndex + 1];
const b = capture.pixels[videoIndex + 2];
const brightness = (r + g + b) / 3 / 2.55;
const hue = (hueOffset + col * 36 + row * 36) % 360;
const saturation = 80;
const c = color(hue, saturation, brightness);
pixels[canvasIndex] = red(c);
pixels[canvasIndex + 1] = green(c);
pixels[canvasIndex + 2] = blue(c);
}
} else {
pixels[canvasIndex] = pixels[canvasIndex + 1] = pixels[canvasIndex + 2] = 0;
}
pixels[canvasIndex + 3] = 255;
}
}
updatePixels();
}
}
function windowResized() {
resizeCanvas(900, 900);
updateCellSize();
}
Fullscreen Version: https://editor.p5js.org/JuliaQi/full/YzQIEs1Nl