Friday, April 1, 2011

Writing mental ray shaders: Facing Forward

A shader that provides the visual representation of facing forward, where the surface normal is 90 degrees to the camera is black, and 0 degrees to the camera is white.

1. create a color parameter called tint
2. create a scalar variable called scale
3. assign scale the dot value product of the surface normal and camera normal
4. assign result the value of tint multiplied by scale

Mi File
declare shader
 color "facing_ratio" (
  color "tint"  default 1 1 1
 apply material
end declare

C File
#include "shader.h"

struct facing_ratio {
 miColor tint;

miBoolean facing_ratio (
 miColor *result, miState *state, struct facing_ratio *params ) {
 miColor *tint = mi_eval_color(&params->tint);
 miScalar scale = -state->dot_nd;
 result->r = tint->r * scale;
 result->g = tint->g * scale;
 result->b = tint->b * scale;
 result->a = 1.0;
 return miTRUE;


On line 10 of the C source code, 

Q. Why can't I directly assign the color of mi_eval_color() to tint?
A. mi_eval_color() or mi_eval in general, does not return color. It returns a pointer.

Q. What is it doing? 
A.  This is dereferencing, it is storing the location of mi_eval_color() at the location of tint. And hence the final value 

Q. When did tint become a pointer? Or can I convert any type to a pointer type with a "*"?
A. Any variable has an address associated with it. The * refers to the address.

  1. dot_nd is a state variable that is a dot product of the surface normal and camera vector. It is found in, in the MentalRay manual - Using and Writing Shaders - State Variables - Intersection
  2. mi_eval returns a pointer to the parameter value, no matter where it comes from. If the shader accessed its parameters directly, without using mi_eval, it would get garbage (such as 0 or NaN) if the parameter is assigned. More detail in the MentalRay manual - Using and Writing Shaders -  Parameter Assignment and mi_eval.
  3. A refresher for pointers in C. "Practical Programming in C"


Post a Comment