frost shader

Our final project was an independant study into whatever holds our interest pertaining to the material. I decided to create a procedural frost shader in the Renderman Shading Language.

 

Inspired by a margarita at a mexican restaurant, I thought a procedural frost shader would pose an interesting challenge that would be suitable for a final project in the class. I wanted to have a thin layer of white frost grow up the side of an object, preferably a glass. The way I had planned the shader, I would start by creating the frost surface as a whole and leave the growing process up to animating the opacity. I think I was both successful and unsuccessful in my attempt.

My first instinct was to base the shader off of a stippled pattern, so I began by examining the source for Pixar's stone shader. Ultimately, however, I didn't follow that path and began by using a high frequency noise with a color spline determining surface color.

    tone = noise( transform("shader",P) / scaleo);
    tone = round(nshades * pow(tone, exponent)) / nshades;
    grain = mix(graincolor,basecolor,tone);

A lot of thought went into the real physical aspects of frost and how one would go about creating a realistic shader that achieves the look. The problem is that the details that really make a real world frost look like real world frost are so small that it would be barely noticable and insanely impractical to try to do it that way. This lesson came quickly, fortunately, and I started working towards the illusion of frost.

I used the same high-frequency noise that the surface shader calculates to power a subtle displacement to acquire the tactile aspect of the shader. I also piped my own noise function, caleld dfse_noise(), into the diffuse color of the shader, which succeeded in giving parts of the frost the milky look that a buildup of ice produces.

float dfse_noise()
{
    float sum = 0;
    float i, freq = 1.0;
    
    for (i = 0; i < 6; i = i + 1){
        sum = sum + abs(.5 - noise(transform("shader",P)*4*freq))/freq;
        freq *= 2;
    }
float result = sum;
return result;
}

I also added a reflectivity component, initially by using an environment map, without raytracing. Here is a turnaround of some test renders of the frost so far.

While a good start, if this ice were going "grow" on something, you would see an obvious distortion taking place through it. After really really not wanting to, I decided to bite the bullet and start raytracing. I started by throwing out all my environment mapping code and replacing it with a fresnel() function. This is a double-edged sword, as it takes care of both reflection and refractions. The difference is noticable and nice looking.

The original plan was to have the frost shader grow up the side of a modelled cup of some sort, but due to time constraints and excessive troubleshooting I was forced to cut my losses and just display the shader as a whole.

Full shader source here.