#2 (Due 9/14)

This set of Deliverables has 4 parts, due at the beginning of class on September 14.

  1. Reading #02
  2. Looking Outwards #02 [Due 9/21]
  3. Warmup: Praxinoscope/Zoetrope
  4. Generated GIF Loop


1. Reading[s] #02: Generative Art Theory

"Generative art refers to any art practice where the artist uses a system, such as a set of natural language rules, a computer program, a machine, or other procedural invention, which is set into motion with some degree of autonomy contributing to or resulting in a completed work of art." -- Philip Galanter

For this deliverable, you will read two texts. In a blog post, you will then write brief (50-word) responses to two questions, which are below. The two texts are:

  • a 2-page fragment of an article by Kate Compton, "So you want to build a generator..." (2016)
  • and a 30-page article, Generative Art Theory (2003) by Philip Galanter.

Kate Compton's article appears in its [complete] original here, but I only ask that you read the section near the bottom which begins, "Aesthetics: the toughest challenge", where she discusses oatmeal. That's right. I have uploaded a PDF of this excerpt for you here: 

Philip Galanter's article appears as Chapter 5 (pages 146-175) in A Companion to Digital Art, Edited by Christiane Paul, 2016 by John Wiley & Sons, Inc. This PDF/eBook is available at:

Question 1A. Be sure to have read the first 20 pages of "Generative Art Theory" by Philip Galanter (p.146-166). In your own words, and in just a few sentences, discuss an example of something you like which exhibits effective complexity. (It doesn't have to be something made by people.) Where does your selection sit between total order (e.g. crystal lattice) and total randomness (e.g. gas molecules, white noise, static)? Include an image which illustrates your selected thing.

Question 1B. Quickly skim the remaining 10 pages of Galanter's article, in which he outlines nine different problems with generative art (The Problem of Authorship; The Problem of Intent; The Problem of Uniqueness; The Problem of Authenticity; The Problem of Dynamics; The Problem of Postmodernity; The Problem of Locality, Code, and Malleability; The Problem of Creativity; The Problem of Meaning). Select one of these problems for which you yourself feel some sort of internal conflict or personal stake. Discuss your internal conflict. Which side of the argument do you come down on?

Please be sure to:

  • Categorize your blog post with the WordPress category, 02-Reading.
  • Title your blog post, nickname-Reading02 (where "nickname" is your login name for this course WordPress!)


2. Looking Outwards 02: Generative Art

Please note that this LO component is due 9/21, not 9/14. 

This deliverable will be your second Looking Outwards report. Our topic is Generative Art: art whose forms (images, sculptures, etc.) have been generated by algorithms -- algorithms created by artists, designers, architects, musicians, and poets.

You are to identify a generative project you like, and write about it.
Some places to get started include:

Here are some lists of generative artists:

Identify a generative project or work which you find inspirational. In a blog post of about 150 words,

  • Discuss the project. Respond to the questions:
    • What is the project?
    • What do you admire about the work, and why do you admire these aspects of it?
    • What do you know (or what do you suppose) about the algorithm that generated the work?
    • It what ways are the creator's artistic sensibilities manifest in their algorithm?
    • What is the artwork's effective complexity? Discuss the way that the artist has balanced order and disorder.
  • Link (if possible) to the work. To the best of your abilities, be sure to provide the creator's name, title of the work, and year of creation.
  • Embed an image of the project.
  • Embed a YouTube/Vimeo video of the project (if available).
  • Label your blog post with the Category, LookingOutwards02.
  • Title your blog post, nickname-LookingOutwards02.


3. Warmup: A Praxinoscope / Zoetrope Animation

You have been provided with some inexpensive versions of classic early-cinema devices: Praxinoscopes and Zoetropes. As a warmup for Part 4 of this week's deliverables, you are to write code to produce an animation for one of these devices. Keep it simple -- this is meant as a fun, creative warmup. It is not a graded assignment.

You have been provided with code templates (for both Processing and p5.js) that produce print designs for these devices. I recommend Processing because it has a particularly handy library for generating PDFs computationally; you could use p5.js if you prefer, but it can only generate raster (pixel-based) images. Click on the green "Clone or Download" button on the following Github repository pages in order to download a zip file containing the Processing projects:

Code templates:

These templates do the following:

  • The templates provide a function called drawArtFrame(). Your job is to put your own drawing code into this function. Currently there is a "sample" drawing there, and some guidelines that indicate the location of the origin.
  • If you run the code and press 'f', the code will export a series of frame images into your sketch (or Downloads) folder.
  • If you run the code and press 'p', the code will export a PDF (or single PNG) containing the design to be printed and placed in the device.

The Praxinoscope / Zoetrope project is meant to be a lightweight introduction to the problem of creating a looping animation. We won't have an in-depth critique of this project, but we'll definitely have a chat in which we discuss our favorites. There are some important constraints that will affect your design:

  • Zoetropes in general are dim, because they must be viewed through a tiny slit.
  • Our Praxinoscopes and Zoetropes are quite small. The printed designs will be quite tiny!
  • You don't need to make a design for both devices; just pick one.
  • Feel free to use color. But: that said, because the graphics will be tiny and dim, and it will probably work best to create simple, high-contrast (black-and-white?) designs.
  • Our Praxinoscope supports animations with exactly 10 frames. Our Zoetrope toys appear to support 11-12 frames. (It's possible that they might support up to 20; feel free to experiment.)

Now:

  • Create a blog post. In this blog post, you should:
  • Upload your Praxinoscope / Zoetrope design to this WordPress. (I need to be able to download the PNG/PDF, in order to print it for our exhibition.)
  • Include an animated GIF of your design. You can generate the frames by pressing 'f' when running your project from my template.
  • Don't forget to upload the PDF or PNG, and not just the animated GIF. It won't embed in the web page visually, but embedding it will create a link just like this: nickname-praxinoscope-output
  • Write a paragraph about your design.
  • Include any preparatory hand-drawn sketches of your design, if any.
  • Embed your code in the post. As a reminder, instructions for doing so are here.
  • Label your blog post with the Category, 02-Scope.
  • Title your blog post, nickname-Scope.


4. A Looping, Animated, Computationally Generated GIF

This is the "main" part of Deliverables #2, and will be the only part of this week's assignment which is critiqued in class. In this project, you will create a looping, animated GIF using computationally generated graphics. Your GIF must be uploaded to this site no later than 8:00am on Friday, 9/14. So:

  1. SKETCH FIRST! Before doing anything, make some (real) sketches in your notebook. Try to develop a graphic concept.
  2. Your design must be square, with dimensions: 640x640 pixels. (Why? Ask about my EV2730Q)
  3. Write code which generates a (seamlessly) looping animation. You may use the code templates below to get started. I've provided templates in Processing (Java), p5.js (JavaScript), and Python, using Processing's Python mode. I recommend that you restrict yourself to just a few, well-chosen colors; and that you limit your GIF to approximately 30-120 frames in duration. (It's permissible for your design to be derived from your Zoetrope/Praxinoscope design.)
  4. Export your frames from your code computationally (i.e. from code), and then use a tool (such as one of these) to assemble the animated GIF from the frames. Don't use a screencapture program to make your GIF! Also, be sure to create your GIF so that it loops infinitely, and be sure to create it so that it plays back at least 20 frames per second (preferably 30 FPS). These are options you can set with proper GIF creation tools. You may need to specify the frame rate using milliseconds per frame (e.g. 30 FPS = 33 ms/f).
  5. Remember, an animated GIF must represent all of its frames with a single a palette of just 256 colors. You may find this resource helpful: tips for making animated GIFs.
  6. OH HEY. You are required to use an easing function to create a nuanced articulation of animated form. (Why? because you'll learn a ton.) Select an easing function from Pattern_Master (Processing/Java) or p5-func (p5.js/JavaScript). [The p5-func is an external library, which you can put into your addons folder for p5.js when developing on your laptop. By contrast, note that the Pattern_Master is just a grab-bag of functions; although it is a working Processing project, it is not formatted as a proper Processing library. You'll need to hunt through the code to find the function you want, and then copy-paste it into your project.] These easing functions take a number from 0...1, and return an altered number from 0...1, which has a different character or quality.
  7. Want more challenge? Motion blur can make GIF loops look amaaazing. David Whyte from BeesAndBombs has posted some Processing template code for achieving motion blur, and Étienne Jacob has written a detailed tutorial about using this code, available here.
  8. Export a series of frames, and compile these into an animated GIF. You can do this with an online tool like http://gifmaker.me/. Alternatively, here is a helpful tutorial for creating animated GIFs from folders of images, using Photoshop. Remember to set the duration of your GIF to "forever". Your GIF can be any length, but keeping it under 5MB is strongly preferred. There are some tools for optimizing your GIF linked from here.
  9. In a blog post, upload and embed your animated GIF. Important: Embed the GIF at original resolution. Be sure not to embed any version that has been automatically resized by WordPress; it will not be animated! Also important: please upload your GIF to this WordPress site -- embeds from Giphy or elsewhere in the cloud are not acceptable.
  10. Write a paragraph about the experience of creating the piece. Which easing function did you select, and why? Critique your work: where you feel you succeeded, where you feel you fell short of what you'd hoped to achieve.
  11. Include a scan or photo of your pen-and-paper sketches.
  12. Embed your code into the blog. Instructions for doing so are here. Note that you may need to switch to the WordPress Text-mode (not Visual mode) editing mode at this point. (Otherwise, code with < and > characters can get messed up.)
  13. Label your blog post with the Category, 02-AnimatedLoop.
  14. Title your blog post, nickname-AnimatedLoop.

Code Templates for Generating Looping GIFs

Below are Processing, p5.js, and Processing.py templates for exporting frames to make an animated GIF loop. If you decide to use the template code, you'll need to rewrite the renderMyDesign() method, which takes a percentage from 0..1 (NOTE: not a frame number!) as its argument.

If you're using the JavaScript version, in order to export the frames, you'll need to set bEnableExport to true, and you'll need to be running a local server; for help, see this explanation/instruction Wiki and this Shiffman video.

Here is an animated GIF, and the Processing code template that produced it. Observe how the small pink square is moving nonlinearly, using one of the Pattern_Master functions. It has some character!

// This is a template for creating a looping animation in Processing/Java. 
// When you press the 'F' key, this program will export a series of images
// into a "frames" directory located in its sketch folder. 
// These can then be combined into an animated gif. 
// Known to work with Processing 3.4
// Prof. Golan Levin, January 2018
 
//===================================================
// Global variables. 
String  myNickname = "nickname"; 
int     nFramesInLoop = 120;
int     nElapsedFrames;
boolean bRecording; 
 
//===================================================
void setup() {
  size (500, 200); 
  bRecording = false;
  nElapsedFrames = 0;
}
//===================================================
void keyPressed() {
  if ((key == 'f') || (key == 'F')) {
    bRecording = true;
    nElapsedFrames = 0;
  }
}
 
//===================================================
void draw() {
 
  // Compute a percentage (0...1) representing where we are in the loop.
  float percentCompleteFraction = 0; 
  if (bRecording) {
    percentCompleteFraction = (float) nElapsedFrames / (float)nFramesInLoop;
  } else {
    percentCompleteFraction = (float) (frameCount % nFramesInLoop) / (float)nFramesInLoop;
  }
 
  // Render the design, based on that percentage. 
  renderMyDesign (percentCompleteFraction);
 
  // If we're recording the output, save the frame to a file. 
  if (bRecording) {
    saveFrame("frames/" + myNickname + "_frame_" + nf(nElapsedFrames, 4) + ".png");
    nElapsedFrames++; 
    if (nElapsedFrames >= nFramesInLoop) {
      bRecording = false;
    }
  }
}
 
//===================================================
void renderMyDesign (float percent) {
  //
  // YOUR ART GOES HERE.
  // This is an example of a function that renders a temporally looping design. 
  // It takes a "percent", between 0 and 1, indicating where we are in the loop. 
  // This example uses two different graphical techniques. 
  // Use or delete whatever you prefer from this example. 
  // Remember to SKETCH FIRST!
 
  //----------------------
  // here, I set the background and some other graphical properties
  background (180);
  smooth(); 
  stroke (0, 0, 0); 
  strokeWeight (2); 
 
  //----------------------
  // Here, I assign some handy variables. 
  float cx = 100;
  float cy = 100;
 
  //----------------------
  // Here, I use trigonometry to render a rotating element.
  float radius = 80; 
  float rotatingArmAngle = percent * TWO_PI; 
  float px = cx + radius*cos(rotatingArmAngle); 
  float py = cy + radius*sin(rotatingArmAngle); 
  fill    (255); 
  line    (cx, cy, px, py); 
  ellipse (px, py, 20, 20);
 
  //----------------------
  // Here, I use graphical transformations to render a rotated square. 
  pushMatrix(); 
  translate (cx, cy);
  float rotatingSquareAngle =  percent * TWO_PI * -0.25;
  rotate (rotatingSquareAngle); 
  fill (255, 128); 
  rect (-40, -40, 80, 80);
  popMatrix(); 
 
  //----------------------
  // Here's a linearly-moving white square
  float squareSize = 20;
  float topY = 0 - squareSize - 2;
  float botY = height + 2;
  float sPercent = (percent + 0.5)%1.0; // shifted by a half-loop
  float yPosition1 = map(sPercent, 0, 1, topY, botY); 
  fill (255, 255, 255); 
  rect (230, yPosition1, 20, 20); 
 
  //----------------------
  // Here's a sigmoidally-moving pink square!
  // This uses the "Double-Exponential Sigmoid" easing function 
  // from https://github.com/golanlevin/Pattern_Master
  float eased = function_DoubleExponentialSigmoid (percent, 0.7); 
  eased = (eased + 0.5)%1.0; // again, shifted by a half-loop, for fun
  float yPosition2 = map(eased, 0, 1, topY, botY); 
  fill (255, 200, 200); 
  rect (260, yPosition2, 20, 20); 
 
  //----------------------
  // Here's a pulsating ellipse
  float ellipsePulse = sin ( 3.0 * percent * TWO_PI); 
  float ellipseW = map(ellipsePulse, -1, 1, 20, 50); 
  float ellipseH = map(ellipsePulse, -1, 1, 50, 30); 
  float ellipseColor = map(ellipsePulse, -1, 1, 128, 255); 
  fill (255, ellipseColor, ellipseColor); 
  ellipse (350, cy, ellipseW, ellipseH); 
 
  //----------------------
  // Here's a traveling sine wave, 
  // of which one-quarter is visible
  for (int sy=0; sy <= height; sy+=4) {
    float t = map (sy, 0, height, 0.0, 0.25); 
    float sx = 450 + 25.0 * sin ((t + percent)*TWO_PI); 
    point (sx, sy);
  }
 
  //----------------------
  // If we're recording, I include some visual feedback. 
  fill (255, 0, 0);
  textAlign (CENTER); 
  String percentDisplayString = nf(percent, 1, 3);
  text (percentDisplayString, cx, cy-15);
}
 
 
 
//===================================================
// Taken from https://github.com/golanlevin/Pattern_Master
float function_DoubleExponentialSigmoid (float x, float a) {
  // functionName = "Double-Exponential Sigmoid";
 
  float min_param_a = 0.0 + EPSILON;
  float max_param_a = 1.0 - EPSILON;
  a = constrain(a, min_param_a, max_param_a); 
  a = 1-a;
 
  float y = 0;
  if (x<=0.5) {
    y = (pow(2.0*x, 1.0/a))/2.0;
  } else {
    y = 1.0 - (pow(2.0*(1.0-x), 1.0/a))/2.0;
  }
  return y;
}

For more ideas, here's Dan Shiffman from Coding Train, in which he re-codes a classic GIF loop by Bees and Bombs: