#02 (Due 2/2)
This set of Deliverables has 4 parts, due at the beginning of class on February 2.
1. Reading #02: Generative Art Theory
For this deliverable, you will read a 30-page article, Generative Art Theory (2003) by Philip Galanter. In a blog post, you will write brief (50-word) responses to two questions below.
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 from the CMU Library at:
- here
- http://vufind.library.cmu.edu/vufind/Record/1760329 or
- http://onlinelibrary.wiley.com/book/10.1002/9781118475249 (off-campus link)
Question 1A. 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. 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 selection.
Question 1B. Quickly skim the remaining 10 pages of the article, in which Galanter 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, Reading02.
- Title your blog post, nickname-Reading02.
2. Looking Outwards 02: Generative Art
This deliverable is to be your second Looking Outwards report. Our topic for this week is Generative Art: art whose forms (images, sculptures, etcetera) have been generated by algorithms — algorithms created by artists, designers, architects, musicians, and poets.
“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, What is Generative Art? (2003)
You are to identify a project you like, and write about it.
Some places to get started include:
- The list of blogs and feeds here.
- The CreativeApplications.net blog, which has a generative tag — https://www.creativeapplications.net/tag/generative/. (We have a class account which will allow you to see posts older than one year; an account login was emailed to you.)
- The creators linked from the ScriptedbyPurpose exhibition.
- The link archive at RadicalInfo for Algorithmic Art by Remko Scha.
- A fantastic web site of Generative Art Links by Mikael Hvidtfeldt Christensen.
- The Wikipedia article on Generative Art (could be helpful to skim).
- Vimeo videos tagged with ‘generative‘
Here are some lists of generative artists:
- Generative Artists – 1st Generation (active since late 1960s): Charles Csuri (*1922), Herbert W. Franke (*1927), Jean-Pierre Hébert (*1939), Manfred Mohr (*1938), Vera Molnar (*1924), Frieder Nake (*1938), Georg Nees (1926-2016), A. Michael Noll (*1939), Lillian Schwartz (*1927), Roman Verostko (*1929), Edward Zajec (*1938);
- Generative Artists – 2nd Generation (active since early ’80s): Karl Sims (*1962), William Latham (*1961), Mark Wilson (*1943);
- Generative Artists – 3nd Generation and younger (active since late ’90s): Marius Watz, Lia, Casey Reas, Michael Hansmeyer, Quayola, Jonathan McCabe, Allison Parrish, Mitchell Whitelaw, Tina Frank, Iñigo Quílez, Joshua Davis, David Wicks, Robert Hodgin, Dr. Woohoo, Erik Natzke, Dave Bollinger, Moka, Matt Pearson, Alex Dragulescu, Paul Prudence, Jared Tarbell, Memo Akten, Glen Marshall, Holger Lippmann, Markos Kay, Jessica Rosenkrantz & Nervous System, Marcin Ignac, Leonardo Solaas, Philip Rideout, Mario Klingemann, Altered Qualia, Frederik Vanhoutte, Karsten Schmidt, Leander Herzog, Madeline Gannon, Caitlin Morris, Neri Oxman.
Identify a project or work which you find inspirational. In a blog post of about 150 words,
- Discuss the project. Respond to the questions:
- 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. Finish your Praxinoscope / Zoetrope Design
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. (We’ll be staging a hallway exhibition of your designs on February 7th.)
You have been provided with code templates (for Processing/Java) that produce print designs for these devices. We’re using Processing because it has a particularly handy library for generating PDFs computationally. 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:
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 origin.
- If you run the code and press ‘f‘, the code will export a series of frame images into your sketch folder.
- If you run the code and press ‘p‘, the code will export a PDF 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 will not have an in-depth critique of the 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 designs will be quite tiny!
- Because the graphics are tiny and dim, it will probably work best to create simple, high-contrast, black-and-white designs.
- Our Praxinoscope supports animations with exactly 10 frames. Our Zoetrope appears to support 11-12 frames. (It’s possible that it might support up to 20; feel free to experiment.)
Now:
- Create a blog post. In this blog post, you should:
- Upload your Praxinoscope / Zoetrope PDF to this WordPress. (I need to be able to download the PDF, in order to print it for our exhibition.)
- Don’t forget to upload the PDF, and not just the 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 an animated GIF of your design. You can generate the frames by pressing ‘f’ when running your project.
- Include any preparatory hand-drawn sketches of your design, if any.
- Embed your code in the post. 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 reviewed by our external reviewers. In this project, you will create a looping, animated GIF using computationally generated graphics. So:
- SKETCH FIRST! Before doing anything, make some (real) sketches in your notebook. Try to develop a graphic concept.
- Write code which creates 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 your image be no larger than 600 pixels wide; that you restrict yourself to just a few, well-chosen colors; and that you limit your GIF to approximately 30-120 frames in duration. Although it is not a strict requirement, you are especially encouraged to make a square GIF.
- 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).
- 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.
- You are required to use an easing function to create a nuanced articulation of animated form. 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 Processing 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.
- 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.
- 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!
- 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.
- Include a scan or photo of your pen-and-paper sketches.
- 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.)
- Label your blog post with the Category, 02-AnimatedLoop.
- 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.
- Code template for GIF loop generation, in Processing (Java)
- Code template for GIF loop generation, in p5.js (JavaScript)
- Code template for GIF loop generation, in Processing.py (Python)
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.
// 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.3.6 // 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 a 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; } |