Pen and Ink Rendering

Jeff Ballard - ballard@cs.wisc.edu

About this project
I started this project out as an effort to do a broad swipe at pen and ink rendering. What I had found that others had done so far was interesting, but altogether it left a vast section out. What my renderer does that (to my knowledge) no other does is that it is purely a shading-based system.

How does this renderer work?
This renderer uses Nick Rasmussen's render as its front-end to all available 3-D information. I render the image and keep the following things: With these things, I can now create a pen and ink image. The agorithm that creates the images works like this:

For the first image its:

  1. Pick a point randomly from the screen to start a line.
  2. Check to see if this point intersects an object, if not goto 1.
  3. Check to see if this area needs to be darkened. If not, goto 1.
  4. Start drawing a line following the U vector. Start in one direction, then when no more points can be added, go in the other.
  5. Save this vector (the x,y location of the screen, the u,v location of the object, and the random noise offsets).
  6. Goto 1 until no more lines can be added.
  7. Draw the outline.
  8. Save the frame, increment the frame counter, and go to the #1 below.

So for the rest of the images its:

  1. Try adding all the last successful lines from the last frame, doing some searching to see if they moved.
  2. Store any lines that succeed.
  3. Pick a point randomly from the screen to start a line.
  4. Check to see if this point intersects an object, if not goto 3.
  5. Check to see if this area needs to be darkened. If not, goto 3.
  6. Start drawing a line following the U vector. Start in one direction, then when no more points can be added, go in the other.
  7. Save this line (the x,y location of the screen, the u,v location of the object, and the random noise offsets).
  8. Goto 3 until no more lines can be added.
  9. Draw the outlines.
  10. Save the frame, increment the frame counter, and goto 1.

So whats this about noise? Yes, I have also implemented a 3 dimensional Perlin noise field to give the lines a little inherant wiggle. The third dimension is time. This makes the images imperfect (and thats the point). For the examples I used, I am using 5 octaves and each successive octave is 1/1.4th as much as the one before it. I have a nifty C++ object that handles all of that for me now. For speed (and since it really isn't doing a lot), I only implemented linear interpretation.

When each line is drawn, it is given a random offest into the noise field on this frame's offset into the noise field. All the points that are drawn get their noise from that offset. However, because the noise causes many artifacts when the noisy lines are used in the shading calculations, I actually store 2 copies of the picture in memory, one thats noisy and one that is not.

Other wild things
In doing this project, I also did some rather interesting things. I started this project by doing a bunch of work supersampling pixels and then reducing to a smaller pixel (hence the "antialias" value in the code). Well, this was extremely RAM intensive and generally didn't work extremely well.

I got around this by doing everything as float offsets rather than integer. When I go to draw a frame, I have methods that will take floats and preform the necessary linear interpolation to get the right value. With all the samples you see, I have not done any supersampling, and everything has been done at the resolution you see.

Enough... lets see some pictures!
Alright, here we go...


wiggle.avi - 3.9 meg
This animation is one triangle that remains stationary to show off the Perlin Noise.

eggbeat.avi - 12 meg
This animation is two spheres that move in an eggbeater pattern.

cool-1.avi (lower resolution) - 2.1 meg
This was the final animation I created with my project. It contains a sphere and a pyramid that go around on a triangle (the triangle is to show shadows).

cool-1big.avi (higher resolution) - 15.5 meg
This is the same thing as the one above.
What about the code?
The code is right here. It is only the code to do my pen and ink stuff and requires Nick's renderer. You'll have to ask him for it, if you're interested.

Thats's all...