Shader Object Agents

 

As with all Layout scripts, the processing point of your LS/PT script is the process() function. The process() function is called on a per-pixel basis. LS/PT provides a single argument to your script's process() function. This argument is an instance of a Object Agent, known as a Shader Object. This object contains data members and methods that can be accessed (and in some cases, modified).

Data Members

sx (READ-ONLY)
sx is a number representing the spot X location in the final image in pixel coordinates where (0,0) is at the upper-left corner.

sy (READ-ONLY)
sy is a number representing the spot Y location in the final image in pixel coordinates where (0,0) is at the upper-left corner.

oPos[3] (READ-ONLY)
oPos[3]are numbers that represent the coordinates of the spot position in object coordinates.

wPos[3] (READ-ONLY)
wPos[3]are numbers that represent the coordinates of the spot position in world coordinates.

gNorm[3] (READ-ONLY)
gNorm[3]are numbers representing the geometric normal of the spot in world coordinates. This is the raw polygonal normal at the spot, unperturbed by smoothing or bump mapping.

spotSize (READ-ONLY)
spotSize is number representing the approximate spot diameter. This is a very approximate value because spots on a surface viewed on edge are long and thin. This can be used to compute texture anti-aliasing.

raySource[3] (READ-ONLY)
raySource[3]are numbers representing the origin of the incoming viewing ray in world coordinates. Often this will be the camera, but it does not have to be the camera.

rayLength (READ-ONLY)
rayLength is a number representing the distance the viewing ray travelled in free space to reach this spot.

cosine (READ-ONLY)
cosine is a number representing the cosine of the angle between the viewing ray and the surface normal at this spot. It indicates the glancing the view and measures the approximate size of the spot.

oXfrm[9] (READ-ONLY)
oXfrm[9] refers to object-to-world transformation matrix. This can be computed other ways, but it is included here for speed and is intended to be used primarily for directional vectors.

wXfrm[9] (READ-ONLY)
wXfrm[9] refers to world-to-object transformation matrix. This can be computed other ways, but is included here for speed and is intended to be used primarily for directional vectors.

objID (READ-ONLY)
objID is a pointer to an Object Agent that represents the object being shaded.

polNum (READ-ONLY)
polNum is an integer that represents the polygon number of the object being shaded. While this will be the polygon number for normal mesh objects, it may represent other sub-object information in non-mesh objects.

wNorm[3]
wNorm[3]is a new geometric normal of the spot in world coordinates. Modifying this makes the surface look bumpy without altering the geometry (bump mapping). The shader needs to renormalize the vector after perturbation.

color[3]
color[3]are numbers representing the percentage of the Red [1], Green [2], and Blue [3] values of the surface color, where 1.0 equals 100%.

luminous
luminous is a number representing the percentage of luminousity of the surface (1.0 == 100%).

diffuse
diffuse is a number representing the percentage of diffusion of the surface (1.0 == 100%).

specular
specular is a number representing the percentage of specularity of the surface (1.0 == 100%).

mirror
mirror is a number representing the percentage of mirroring of the surface (1.0 == 100%)

transparency
transparency is a number representing the percentage of transparency of the surface (1.0 == 100%).

eta
eta is a number representing the percentage of the index of refraction of the surface (1.0 == 100%).

roughness
roughness is a number representing the percentage of roughness of the surface (1.0 == 100%).

Methods

illuminate(light,position)
The illuminate(light,position) function returns an array of six numbers that represent the light ray (color[1-3] and direction[4-6]) hitting the given position from the given light at the current instance. The return value is zero if the light does not illuminate the given world coordinate position at all. The color includes effects from shadows (if any), falloff, spotlight cones, and transparent objects between the light and the point

raytrace(position,direction)
The raytrace(position,direction) function may be called to trace a ray from the a given location in a given direction (in world coordinates). The function returns an array of four elements that represent the length of the ray [1] and the color coming from that direction [2-4]. The ray length will be -1.0 if it is infinite. The direction used is the outgoing direction and must be normalized to be a unit vector.

raycast()
raycast()is essentially a faster version of raytrace(), accepting the same parameters, but returning only the ray length. No shading is evaluated, and no recursive raytracing takes place.

Examples:

This example demonstrates how to use a Shader Object. Much of this code involves calculations made for the shader to work properly. Take particular notice of the sa Shader Object in the process() function.

// LS/PT: Blotch                                
//
// Stick a colored spot on a surface(based on the
// sample Shader plug-in shipped with the LightWave 4.0 SDK)
//
//

@version 2.0

color;
center;
radius;
softness;

r2, piOverR;

create
{
  color[1] = 0.9;
  color[2] = 0.0;
  color[3] = 0.2;

  center[1] = 0.0;
  center[2] = 0.0;
  center[3] = 0.0;

     radius = 1.5;
   softness = 0.5;
}

init
{

     r2 = radius * radius;
   piOverR = 3.1416 / radius;
}

flags
{
  return(COLOR); // we will modify the color of the texture
}

process: sa
// 'sa' is an instance of a Shader Object.
{
  localr2 = 0.0;
  for(i = 1; i <= 3; i++)
  {
       d = sa.oPos[i] - center[i];
       d = d * d;
       if(d > r2)
            return;

          localr2 += d;
   }

     if(localr2 > r2)
        return;

     d = sqrt(localr2);
   d = cos(d * piOverR) * softness;

     if(d > 1.0)
        d = 1.0;
  a = 1.0 - d;
  for(i = 1; i <= 3; i++)
       sa.color[i] = sa.color[i] * a + color[i] * d;
}

options //This is the interface code.
{
  reqbegin("Blotch");
       clr = <integer(color[1] * 255),
       integer(color[2] * 255),
       integer(color[3] * 255)>;
       cntr = <center[1],center[2],center[3]>;

          c1 = ctlrgb("Blotch color",clr);
        c2 = ctlvector("Blotch center",cntr);
       c3 = ctlnumber("Radius",radius);
       c4 = ctlnumber("Softness",softness);
       if(reqpost())
       {
            clr = getvalue(c1);
            color[1] = clr.x / 255;
            color[2] = clr.y / 255;
            color[3] = clr.z / 255;
            cntr = getvalue(c2);
            center[1] = cntr.x;
            center[2] = cntr.y;
            center[3] = cntr.z;
            radius = getvalue(c3);
            softness = getvalue(c4);
            r2 = radius * radius;
            piOverR = 3.1416 / radius;
       }
  reqend();
}

save: what, io
{
  if(what == OBJECTMODE)
  {
       io.writeNumber(color[1]);
       io.writeNumber(color[2]);
       io.writeNumber(color[3]);
       io.writeNumber(center[1]);
       io.writeNumber(center[2]);
       io.writeNumber(center[3]);
       io.writeNumber(radius);
       io.writeNumber(softness);
  }
}

load: what,io
{
  if(what == OBJECTMODE) // processing an Object file
  {
       color[1] = io.readNumber();
       color[2] = io.readNumber();
       color[3] = io.readNumber();
       center[1] = io.readNumber();
       center[2] = io.readNumber();
       center[3] = io.readNumber();
       radius = io.readNumber();
       softness = io.readNumber();
  }
}