Contoured Watercolor Rendering
The goal of this project was to take a 3D mesh, generate the contours, and then apply a watercolor shader to turn the mesh into a 2D watercolor image. My group based our project off two papers- Computing Smooth Surface Contours with Accurate Topology by Pierre Benard, Aaron Hertzmann, and Michael Kass and Interactive Watercolor Rendering with Temporal Coherence and Abstraction by Adrien Bousseau, Matt Kaplan, Joelle Thollot, and Francois X. Sillion. I focused on building a watercolor shader with temporal coherence to make for realistic 2D animations.
Calculating Contours
My team members focused on generating the contours of a mesh. They used FreeStyle and Blender to generate the contours. Freestyle works by making a viewmap of all the contours, boundaries and surface intersections in the scene. Then it checks for visibility of all the segment chains, and renders only the correct ones. The viewmap is then used to construct triangles that form the lines for OpenGL to render. What lines to render and how they are rendered (width and texture) was implemented with python scripts.
Watercolor Rendering
Abstraction
Implement toon shading and average normals to reduce definition and create more abstract areas.
Watercolor Physical Effects
Use various noise textures to mimic 2 physical effects of watercolor- pigment and dispersion - as well as mimic paper textures.
Temporal Coherence
Make sure that the textures don’t swim and slide as the model animates.
Abstraction
Toon Shading
The first step in making a realistic watercolor shader was to modify the original Phong lighting model. As seen in the first image, using the Phong lighting model results in a smooth interpolation between the shaded regions and the well-lit regions. Watercolor does not allow for such smooth shading- color is built up in chunks as the pigment collects on paper.
Toon shading is a simple modification to the Phong lighting model. The smooth lighting value is put through a step function, resulting in these discrete color blocks.
Averaging Normals
While toon shading is a good start, further abstraction can be done by averaging the normals. A single vertex normal was averaged with its neighbors and then updated to the new value. The more this is repeated, the smoother the appearance will be.
This creates broader, more abstract areas. This is particularly apparent in Beethoven’s hair, where the original model had a lot of variation and definition.
Watercolor Physical Effects
Pigment Density Variation
One of the defining characteristics of watercolor is the pigment density variation. Naturally, the most realistic watercolor shader might simulate the interaction between pigment and water. However, this can also be mimicked with noise textures. Here are a few Perlin Noise textures that were used to mimic pigmentation dispersion and turbulent flow.
The pigmentation noise texture is used to represent how the pigment dries in flecks once the water has evaporated. The turbulent flow texture is used to represent how the uneven dilution of the pigment.
Wobbling
The edges have been distorted to mimic wobbling edges due to paper texture. The x and y offsets were calculated with the horizontal and vertical paper gradients. These gradients were calculated by manipulating the resolution of a paper texture.
This makes the outline of the object look much more like a pencil on watercolor paper, rather than a straight line.
Paper Texture
I sampled an image of a paper texture and mixed that with the rendered image. This helps mimic effects like “dry brush” which is when a nearly-dry paint brush is dragged across the paper. The paper texture intensity was calculated and used a height map.
Temporal Coherence
At this point, the watercolor shader looks realistic on still images. However, when tested with a simple turntable animation, the “shower door” effect becomes apparent. The gif to the side shows that the turbulence texture remains fixed, despite the fact that the teapot is moving. This is similar to someone moving behind a textured glass shower door.
This is where the transition from photorealistic to non-photorealistic begins to break down. 3D animation does not happen naturally within a realistic watercolor animation. Should the noise texture follow the moving object? Or should it remain fixed, as it is now? My team and I felt that it would be more natural for the texture to move with the teapot, so I implemented a simple form of temporal coherence.
Textures in Object Space
Ultimately, the texture needs to be tied to the object. When the object rotates, so should the texture. I implemented this by using particles to attach the noise textures to the object. The particles were calculated by making a simple bounding box around the object, and distributing the particles on each of the 6 sides of the box. Since we were using relatively simple models, only one particle was needed per side. However, if more complicated models were to be used or if more detailed textures were used, the bounding box and single particle workflow would break down. The textures were blended together so no jarring popping effect would occur as the object moved.