Fun with Renderman Procedural Shading - Stained Glass Mosaicing!

First, some eye-candy: (JPEG thumbnails, click for hi-res TIFF originals) :


Single Stained-Glass Pane


Church of the Ellipsoid and Latter-Day Stains


Turtle Model with Mosaiced Shell


Image Details:

The first image shows the shader on a flat rectangular glass sheet. The second is a more elaborate scene. Somewhere in a church, there is a marble center table with stained glass top surface and a stained glass ellipsoid that is partly below and partly above this surface. Some good effects like transparency and illumination are visible in this scene, along with some imperfections like the aliasing in some parts of the windows (note: the final output file, available here, is antialiased and shadows are computed for the point light source). The third image is a turtle shell closeup from a large DXF model that I downloaded from 3dcafe.com. The model does not have coherent texture coordinates for parts next to each other. Thus, the model does not look as good as one might think. Still, transparency effects are visible.

I used the Blue Moon Rendering Tools version 2.5 on my PC. Rhino 3D Modeling package was used to create and manipulate the model and export it to Renderman Interface Bytecode (RIB) format, after which the RIB file was directly edited.

Shader Details:

  1. How to Shade Colored Glass:

    I present a generalizable stained-glass mosaicing shader. It uses a funky variant of turbulence that I wrote to simulate the stained glass look. I tried various noise functions (particularly fractal noise and the brownian motion noises that come with BMRT) before settling on turbulence (refer to function turbulence in file noises.h).

    I use this noise function to composite the opaque pigment with a translucent white (plain glass). Both color and opacity are composited. However this function gives a large concentration of extreme values near 1.0 and 0.0 (signifying glass and pigment, respectively). To compensate for this, I add a blurring layer that blurs the computed color with a custom noise function that either weights towards the blurring color (for extreme values) or towards the existing color (for non-extreme values). The effect is clouding of the surface & distribution of the color in patches throughout the material, with most areas having an even mix of the two and some having more pigment or plain glass.

    In the final layer of the shader, a plastic-like illumination model is applied to the surface.

  2. How to do Mosaicing

    Now that shading is taken care of, I add one further effect - procedural multicolor mosaic shading of the glass using Voronoi regions. Functions for which Voronoi region of the points in a jittered grid the current point (ss, tt) lies in are provided with BMRT (Worley noise), and I hack the 2D version of this function which returns two closest points. If the two distances are nearly equal (to within a threshold equal to half the width of the border between regions), I mark the pixel as a border pixel and color it in the border color (black by default). For antialiasing these border lines, I blend the border color with the surrounding glass color using a smooth step.

    If we are squarely in a Voronoi region, we assign a color code to the pixel based on the region, using uniformly distributed noise, a function derived from Perlin noise given by Stephen May in his RManNotes. The color selected is then fed into the stained glass part of the shader to use as the base color to blend with white. The key to using UDN and not random numbers is that we want all pixels which pick a particular region to have the same base color, so the random number generator has to be seeded by something derived from the region coordinates. I use an exponential function of the s and t coordinates of the region's center vertex, as this gives both adequate continuity between neighboring regions as well as adequate color variation over a large group of regions.

    Several parameters govern the look of the stained glass. The border width varies from zero (no border, smooth blend between regions as on the table top) to a thick border (too thin a border can create problems for the antialiasing). The border falloff specifies the antialiasing blend distance. Finally, the cell size along s and t dimensions determines the size of the jittered grid and thus the pattern. I did try rendering two stained glass windows with the same cell size using an offset to the UDN noise generation, random_param , to create a difference in the pattern. This didn't work regardless of the offset value. This is probably due to some property of the UDN defined in the code. So I gave all three windows different cell sizes.

Code

A copy of the code for the shader and rib file can be found in this directory.


Page created by Deepak Bandyopadhyay 11/2/2000 07:50AM EST, last updated 11/2/2000 8:33AM EST.