As with all
Layout scripts, the processing point of your LS/PT script is the process()
function. The process() function is called on a perpixel 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
(READONLY)
sx is a number representing the spot X location in the final image in pixel
coordinates where (0,0) is at the upperleft corner.
sy
(READONLY)
sy is a number representing the spot Y location in the final image in pixel
coordinates where (0,0) is at the upperleft corner.
oPos[3]
(READONLY)
oPos[3]are numbers that represent the coordinates of the spot position
in object coordinates.
wPos[3]
(READONLY)
wPos[3]are numbers that represent the coordinates of the spot position
in world coordinates.
gNorm[3]
(READONLY)
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
(READONLY)
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 antialiasing.
raySource[3]
(READONLY)
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
(READONLY)
rayLength is a number representing the distance the viewing ray travelled
in free space to reach this spot.
cosine
(READONLY)
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]
(READONLY)
oXfrm[9] refers to objecttoworld 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]
(READONLY)
wXfrm[9] refers to worldtoobject 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
(READONLY)
objID is a pointer to an Object Agent that represents the object being
shaded.
polNum
(READONLY)
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 subobject information in nonmesh 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[13] and direction[46]) 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 [24]. 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 plugin 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();
}
}
