Forking a Sketch: How the OpenProcessing Community Uses Remixing to Collect, Annotate, Tune, and Extend Creative Code

Blair Subbaraman, Shenna Shim, Nadya Peek

Machine Agency, University of Washington

Slides: https://rb.gy/3jdyb

What remixing strategies do creative coders employ to reuse code?

Remixing Creative Code

Antecedent by SamuelYAN
Antecedent by SamuelYAN
Remix by naha

Antecedent by SamuelYAN
Remix by naha

Understanding High-Level Remixing Practices

  • Dataset
    • 1.2 million sketches available
    • 336,069 sketches in remixing graph
      • 30% of all sketches
  • Dataset
    • 1.2 million sketches available
    • 336,069 sketches in remixing graph
      • 30% of all sketches

  • Network Analysis
    • 79,453 subgraphs
    • 2749 nodes in largest subgraph
    • 49% of all remixes are self-remixes

Antecedent-Remix Pairs: A Worked Example

Antecedent by Taiki Saito

								function myCircle (x, y, rad) {
									let numLayers = 200
									for (let i = 0; i < numLayers; i++) {
									  let vertices = []


									  for (let theta = 0; theta < TAU; theta += TAU / 20) {
										  ...
							
Remix by Owaun Scantlebury

								function myCircle (x, y, rad) {
								  let numLayers = random(100, 300)
								  for (let i = 0; i < numLayers; i++) {
								    let vertices = []
								    let flick = random(10,11)
									  // for (let theta = 0; theta < TAU; theta += TAU / random(10,30)) {
									  for (let theta = 0; theta < TAU; theta += TAU / flick) {
										  ...
							
Antecedent by Taiki Saito

									function myCircle (x, y, rad) {
										let numLayers = 200
										for (let i = 0; i < numLayers; i++) {
										  let vertices = []
	
	
										  for (let theta = 0; theta < TAU; theta += TAU / 20) {
											  ...
								
Remix by Owaun Scantlebury

									function myCircle (x, y, rad) {
									  let numLayers = random(100, 300)
									  for (let i = 0; i < numLayers; i++) {
									    let vertices = []
									    let flick = random(10,11)
										  // for (let theta = 0; theta < TAU; theta += TAU / random(10,30)) {
										  for (let theta = 0; theta < TAU; theta += TAU / flick) {
										    ...
								
Antecedent by Taiki Saito

								function myCircle (x, y, rad) {
									let numLayers = 200
									for (let i = 0; i < numLayers; i++) {
									  let vertices = []


									  for (let theta = 0; theta < TAU; theta += TAU / 20) {
										  ...
							
Remix by Owaun Scantlebury

								function myCircle (x, y, rad) {
								  let numLayers = random(100, 300)
								  for (let i = 0; i < numLayers; i++) {
									let vertices = []
									let flick = random(10,11)
									  // for (let theta = 0; theta < TAU; theta += TAU / random(10,30)) {
									  for (let theta = 0; theta < TAU; theta += TAU / flick) {
										...
							

tuning

Antecedent by Taiki Saito

								function myCircle (x, y, rad) {
									let numLayers = 200
									for (let i = 0; i < numLayers; i++) {
									  let vertices = []


									  for (let theta = 0; theta < TAU; theta += TAU / 20) {
										  ...
							
Remix by Owaun Scantlebury

								function myCircle (x, y, rad) {
								  let numLayers = random(100, 300)
								  for (let i = 0; i < numLayers; i++) {
									let vertices = []
									let flick = random(10,11)
									  // for (let theta = 0; theta < TAU; theta += TAU / random(10,30)) {
									  for (let theta = 0; theta < TAU; theta += TAU / flick) {
										...
							

tuning, extending

Antecedent by Taiki Saito

								function myCircle (x, y, rad) {
								  let numLayers = 200
								  for (let i = 0; i < numLayers; i++) {
								    let vertices = []
									
									
									  for (let theta = 0; theta < TAU; theta += TAU / 20) {
										  ...
							
Remix by Owaun Scantlebury

								function myCircle (x, y, rad) {
									let numLayers = random(100, 300)
									for (let i = 0; i < numLayers; i++) {
										let vertices = []
										let flick = random(10,11)
										// for (let theta = 0; theta < TAU; theta += TAU / random(10,30)) {
										for (let theta = 0; theta < TAU; theta += TAU / flick) {
											...
							

tuning, extending, annotating

tuning, extension, annotation

collecting, tuning, extending, annotating

Collecting

Annotating

Sketches by Aaron Reuland (a_soluble_fish)

						/* 
						ok, this texture algorithm I definitely stole. 98% sure it was from
						**Che-Yu Wu (openprocessing.org/user/139364)** an amazingly talented 
						artist, who also adds lots of in-progress stuff to openProcessing-
						nice to learn from (not that I learned from this at the time I made this,
						so much as I copied and pasted it) creates a nice papery texture by applying
						noise to the pixel array, that is blended with the rest of the ’art’ later on.
						*/
					
Sketches by Aaron Reuland (a_soluble_fish)

						/* 
						ok, this texture algorithm I definitely stole. 98% sure it was from
						**Che-Yu Wu (openprocessing.org/user/139364)** an amazingly talented 
						artist, who also adds lots of in-progress stuff to openProcessing-
						nice to learn from (not that I learned from this at the time I made this,
						so much as I copied and pasted it) creates a nice papery texture by applying
						noise to the pixel array, that is blended with the rest of the ’art’ later on.
						*/
					

						var length = 150;          var length = 100; // 150
					

Tuning


Antecedent by SamuelYAN

								margin = mySize / 100;
								for (let i=0; i < int(random(50, 100) ); i++) { ... }
								theShader.setUniform('u_time ', millis () / 1000);
								let version = random ([1 ,2 ,4 ,6 ,8]) * 100;
								let c = random (2000 , 5000) ;
								colorMode(HSB, 360, 100, 100, 100);
							
Remix by naha

								margin = mySize / 10;
								for (let i=0; i < int(random(500, 100) ); i++) { ... }
								theShader.setUniform('u_time', millis () / 1);
								let version = random ([200,150,77,50,140] * 100;
								let c = random (1000, 2000);
								colorMode(HSB, 21, 10, 10, 10);
							

Antecedent by SamuelYAN

								margin = mySize / 100;
								for (let i=0; i < int(random(50, 100) ); i++) { ... }
								theShader.setUniform('u_time ', millis () / 1000);
								let version = random ([1 ,2 ,4 ,6 ,8]) * 100;
								let c = random (2000 , 5000) ;
								colorMode(HSB, 360, 100, 100, 100);
							

								stroke (244 , 37 , 37 , 60); // red
							
Remix by naha

								margin = mySize / 10;
								for (let i=0; i < int(random(500, 100) ); i++) { ... }
								theShader.setUniform('u_time', millis () / 1);
								let version = random ([200,150,77,50,140] * 100;
								let c = random (1000, 2000);
								colorMode(HSB, 21, 10, 10, 10);
							

								stroke (0, 0, 0); // red
							

Extending

Antecedent by Sasha T.

								vertex(xPosition , yPosition);
							
Remix by JFrench

								curveVertex(xPosition,yPosition);
							
Antecedent by Okazz

								function randomShape(x_, y_, w_, h_, col) {
									let grfx = createGraphics(w_, h_);
									let rnd = int(random(6));
									let num = int(random(1, 4));
									...
									for (let i = 0; i < num; i++) {
									  let w = random(5, w_ * 0.35);
									  let h = random(5, h_ * 0.35);
									  let x = (random(1.4)-0.2)*grfx.width;
									  let y = (random(1.4)-0.2)*grfx.height;
									  ...
								  }
							
Antecedent by JFrench

								function drawTrees(x_, y_, w_, h_, col) {
									let grfx = createGraphics (w_, h_);
									count = int(random(30));

									...
									for (let i = 0; i < count; i++) {
									let w = random(2, 10);
									let h = w * random (2, 5);
									let x = (random(1.4) - 0.2) * grfx.width;
									let y = (random(1.4) - 0.2) * grfx.height;
									...
									};
							
Family of remixes by Roni Kaufman

Key Takeaways

  • Understanding Existing Creative Communities
  • Design Provocations
  • Applicability to Other Contexts
  • Understanding Existing Creative Communities
  • Design Provocations
  • Applicability to Other Contexts
  • Understanding Existing Creative Communities
  • Design Provocations
  • Applicability to Other Contexts

Special thanks to the OpenProcessing, Processing, and p5.js communities, and especially the authors who agreed to share their work for this paper:

Roni Kaufman, caaatisgood, Taiki Saito, Owaun Scantlebury, Richard Bourne, Neill Bogie, Naoki Tsutae, Aaron Reuland (a_soluble_fish), Naha, SamuelYAN, Trrrrrr, Sasha T. (@tequibo), shrike, Raven Kwok, Jason Labbe, Okazz, JFrench, garabotospr, Hans Peter, and Sayama
Forking a Sketch: How the OpenProcessing Community Uses Remixing to Collect, Annotate, Tune, and Extend Creative Code

Blair Subbaraman, Shenna Shim, Nadya Peek

Machine Agency, University of Washington

Slides: https://rb.gy/3jdyb