Created
September 17, 2024 20:00
-
-
Save Bleuje/04348a2b692737d69120d9858e8d8f4a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Processing code by Etienne Jacob | |
// motion blur template by beesandbombs, explanation/article: https://bleuje.com/tutorial6/ | |
// See the license information at the end of this file. | |
////////////////////////////////////////////////////////////////////////////// | |
// Start of template | |
int[][] result; // pixel colors buffer for motion blur | |
float t; // time global variable in [0,1[ | |
float c; // other global variable for testing things, controlled by mouse | |
//----------------------------------- | |
// ease in and out, [0,1] -> [0,1], with a parameter g: | |
// https://patakk.tumblr.com/post/88602945835/heres-a-simple-function-you-can-use-for-easing | |
float ease(float p, float g) { | |
if (p < 0.5) | |
return 0.5 * pow(2*p, g); | |
else | |
return 1 - 0.5 * pow(2*(1 - p), g); | |
} | |
//----------------------------------- | |
void draw() | |
{ | |
if (!recording) // test mode... | |
{ | |
t = (mouseX*1.3/width)%1; | |
c = mouseY*1.0/height; | |
if (mousePressed) | |
println(c); | |
draw_(); | |
} | |
else // render mode... | |
{ | |
for (int i=0; i<width*height; i++) | |
for (int a=0; a<3; a++) | |
result[i][a] = 0; | |
c = 0; | |
for (int sa=0; sa<samplesPerFrame; sa++) { | |
t = map(frameCount-1 + sa*shutterAngle/samplesPerFrame, 0, numFrames, 0, 1); | |
t %= 1; | |
draw_(); | |
loadPixels(); | |
for (int i=0; i<pixels.length; i++) { | |
result[i][0] += red(pixels[i]); | |
result[i][1] += green(pixels[i]); | |
result[i][2] += blue(pixels[i]); | |
} | |
} | |
loadPixels(); | |
for (int i=0; i<pixels.length; i++) | |
pixels[i] = 0xff << 24 | | |
int(result[i][0]*1.0/samplesPerFrame) << 16 | | |
int(result[i][1]*1.0/samplesPerFrame) << 8 | | |
int(result[i][2]*1.0/samplesPerFrame); | |
updatePixels(); | |
if (frameCount<=numFrames) { | |
saveFrame("data/fr###.gif"); | |
println(frameCount,"/",numFrames); | |
} | |
if (frameCount==numFrames) | |
stop(); | |
} | |
} | |
// End of template | |
////////////////////////////////////////////////////////////////////////////// | |
int samplesPerFrame = 1; | |
int numFrames = 150; | |
float shutterAngle = 1.0; | |
boolean recording = false; | |
float L = 500; // size parameter for the entire thing | |
int MAX_DEPTH = 5; | |
// Function for drawing a white square, | |
// controlling how far the lines go into the inside of the square (lines are actually drawn rectangles) | |
// instead of using strokeWeight and line functions. | |
// Different drawing depending on depth index | |
void drawWhiteSquare(int depthIndex) | |
{ | |
float l = map(pow(depthIndex,0.8), 0, pow(MAX_DEPTH,0.8), 0.02*L, L/2); // replaces the strokeWeight | |
// going towards full white square at max depth | |
// basically just starts small and ends at L/2 to fill the square, the rest is experimentation for aesthetic | |
fill(255); | |
noStroke(); | |
for(int i=0;i<4;i++) | |
{ | |
// draw side i... | |
push(); | |
rotate(HALF_PI*i); | |
// just drawing a white rectangle: | |
beginShape(); | |
vertex(-L/2,-L/2); | |
vertex(L/2,-L/2); | |
vertex(L/2,-L/2+l); | |
vertex(-L/2,-L/2+l); | |
endShape(); | |
pop(); | |
} | |
} | |
void drawFractal(int depthIndex, float currentDepthTime) | |
{ | |
currentDepthTime = (1234 + currentDepthTime)%1; // loop time, keep it in [0,1[ | |
// adding 1234 is a habit to make sure we take the modulo 1 of a positive thing | |
if(depthIndex==MAX_DEPTH) | |
{ | |
drawWhiteSquare(depthIndex); | |
} | |
else | |
{ | |
scale(1.0/3.0); | |
drawWhiteSquare(depthIndex); // draw a square at this depth, then we recursively draw the stuff around the square | |
// then we recursively draw the stuff around the square | |
int K = 5; // replacement technique number (https://bleuje.com/tutorial4/) | |
for(int i=0;i<K;i++) | |
{ | |
float replacementTechniqueProgress = (i + currentDepthTime)/K; | |
float drawingProgress = replacementTechniqueProgress; // this is kind of the progress that will be used for choosing drawing position of the i-th square | |
if((depthIndex%2)==1) drawingProgress = 1 - drawingProgress; // alternating progress direction every other depth index | |
drawingProgress = (1234 + drawingProgress - 0.25*depthIndex)%1; // progress offset with depth for extra layer of complexity | |
float floatCorner = 4 * drawingProgress; | |
int cornerIndex = floor(floatCorner); | |
float straightMovementProgress = floatCorner - cornerIndex; | |
straightMovementProgress = ease(straightMovementProgress,2.0); | |
push(); | |
float r = 2/sqrt(2)*L; | |
// start corner position | |
float theta1 = QUARTER_PI + TAU*cornerIndex/4; | |
PVector pos1 = new PVector(r*cos(theta1),r*sin(theta1)); | |
// end corner position | |
float theta2 = QUARTER_PI + TAU*(cornerIndex+1)/4; | |
PVector pos2 = new PVector(r*cos(theta2),r*sin(theta2)); | |
// real position with interpolation of weight straightMovementProgress | |
PVector pos = pos1.copy().lerp(pos2, straightMovementProgress); | |
translate(pos.x,pos.y); | |
scale(1.0 - 0.4*sin(straightMovementProgress*PI)); // smaller scale in the middle of movement | |
// because of replacement technique, the motion at next depth level should be done a lot of times for a full current depth replacement technique cycle | |
// or it's going to be very slow | |
// Normal (same speed at all depths): | |
//float nextTime = K * replacementTechniqueProgress; | |
// Faster at next depth: | |
float nextTime = 8 * (depthIndex + 1) * replacementTechniqueProgress; | |
// as long as nextTime starts at 0 for progress=0 and ends at any integer n for progress=1, it will loop perfectly so it's possible to experiment easily | |
drawFractal(depthIndex + 1, nextTime); | |
pop(); | |
} | |
} | |
} | |
void setup() | |
{ | |
size(600,600,P3D); | |
result = new int[width*height][3]; | |
smooth(8); | |
} | |
void draw_() | |
{ | |
background(0); | |
push(); | |
translate(width/2,height/2); | |
drawFractal(0,t); | |
pop(); | |
} | |
/* License: | |
* | |
* Copyright (c) 2024 Etienne Jacob | |
* | |
* All rights reserved. | |
* | |
* This code after the template and the related animations are the property of the | |
* copyright holder. Any reproduction, distribution, or use of this material, | |
* in whole or in part, without the express written permission of the copyright | |
* holder is strictly prohibited. | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment