A dictionary function for the shading language

For the Air 11 release we’ve added new shaders that compute a physical sky environment and sun position based on geographical location and date/time.  We thought it would be nice to be able to enter a location using a simple city name instead of having to look up and remember a set of figures for latitude, longitude, and time zone every time.

We need a function that allows us to look up a set of values based on a name, like looking up a word’s definition in a dictionary.   We can add such a function to Air’s shading language by implementing a dynamic shadeop, or DSO for short, which will be loaded by Air automatically and used to evaluate our new function.

The dictionary DSO adds the following new functions to the shading language:

float dictionary(string dictname, string keyname, float fvalue);
float dictionary(string dictname, string keyname, color cvalue);
float dictionary(string dictname, string keyname, string svalue);

The dictionary function looks for a text file named dictname and tries to load a list of token value pairs, one per line.  The token values should look like

Seattle 47.45 -122.3 -8

The functions return 0 if they succeed.  If an error occurs, the functions return one of the following error codes:

-1:  unable to find or read dictionary file
-2:  key name not found
-3:  unable to convert value to the requested type

Since Air 11 has not yet been released, here are a couple other uses for the dictionary function that you can try with the current Air release.

The first example uses the dictionary function to allow the base surface color to be specified using a name instead of r,g,b values.  The Air distribution includes a list of named colors in $AIRHOME/vizools/colors.txt (used by the Air Space tool).  Here’s the source code for a simple NamedColor shader:

surface NamedColor(
 float Ambient = 1;
 float Diffuse = 1;
 string ColorName = "";
 string ColorList = "$AIRHOME/viztools/colors.txt"
)
{
  color Ct = Cs;
  if (ColorName!="") dictionary(ColorList,ColorName,Ct);
  normal Nf = faceforward (normalize(N),I);
  Oi = Os;
  Ci = Oi * Ct * (Ambient * ambient() + Diffuse * diffuse(Nf));
}

The dictionary function will expand the reference to the $AIRHOME environment variable in the ColorList value.

In a RIB file, we can then specify a named color as:

Surface "NamedColor"
 "string ColorName" "neon pink"

Another application for the dictionary function is to allow simple text files to be used to define “preset” values for a shader’s parameters.  Here’s an extended version of the standard paintedplastic surface shader with an option to use a file with preset values:

surface paintedplasticpreset(
 float Ka = 1;
 float Kd = .5;
 float Ks = .5;
 float roughness = .1;
 color specularcolor = 1;
 string texturename = "";
 string preset = "";
)
{
 float preKa=Ka;
 float preKd=Kd;
 float preKs=Ks;
 float preroughness = roughness;
 color prespecularcolor=specularcolor;
 string pretexturename=texturename;

 if (preset!="") {
  dictionary(preset,"Ka",preKa);
  dictionary(preset,"Kd",preKd);
  dictionary(preset,"Ks",preKs);
  dictionary(preset,"roughness",preroughness);
  dictionary(preset,"specularcolor",prespecularcolor);
  dictionary(preset,"texturename",pretexturename);
 }
 Ci = Cs;
 if (pretexturename != "")     Ci *= color texture(pretexturename);
 normal Nf = faceforward (normalize(N),I);
 Oi = Os;
 Ci = Oi * Ci * (preKa*ambient() + preKd*diffuse(Nf)) + prespecularcolor * preKs*specular(Nf,-normalize(I),preroughness);
}

A sample preset file might look like:

Kd 0.4
Ks 0.6
roughness 0.2
specularcolor = 1 1 0
texturename = grid.tx

The new dictionary shadeop can found in this archive.  Unzip the archive to the AIRHOME directory, and the new shadop will automatically be added to the shaders directory of your Air installation (where Air can find it).  Examples and source code for the shadeop can be found in $AIRHOME/examples/dictionary.

This entry was posted in Shaders and tagged , . Bookmark the permalink.