Wednesday, February 12, 2014

Writing mental ray shaders: Simple Diffuse

Intro 

the previous simpler diffuse doesn't have a light loop to automatically go through all the lights in the scene and apply it to the shader. This simple diffuse shader will use a light array type to gather the lights in the scene and apply it tothe shader.



MI Source

declare shader
 color "jc_simple_diffuse" (
  color "diffuse" default 1 1 1,
  array light "lights")
 version 1
 apply material
end declare

C Source

#include "shader.h"

DLLEXPORT

struct jc_simple_diffuse {
 miColor diffuse;
 int i_light; //index to first light, the i_ prefix can be attached to arrays to get the index
 int n_light; //number of lights, the n_ prefix can be attached to arrays to get the size of the array
 miTag light[1];
 };

DLLEXPORT

int jc_simple_diffuse_version(void) {return(1);}

DLLEXPORT

miBoolean jc_simple_diffuse(
 miColor *result,
 miState *state,
 struct jc_simple_diffuse *params) {

 miColor *diffuse = mi_eval_color(&params->diffuse); 
 int n_l = *mi_eval_integer(&params->n_light); //number of lights
 int i_l = *mi_eval_integer(&params->i_light); //offset to first light
 miTag *light = mi_eval_tag(&params->light) + i_l; //name of light + offset, ie light1, or light23
 miColor light_color; 
 miVector dir;
 miScalar dot_nl;
 int i, samples;

 for(i = 0; i < n_l; i++, light++) {//go through all the lights
  samples = 0;
  if(mi_sample_light(&light_color,  &dir, &dot_nl, state, *light, &samples)) {
   result->r += diffuse->r * light_color.r * dot_nl;
   result->g += diffuse->g * light_color.g * dot_nl;
   result->b += diffuse->b * light_color.b * dot_nl;
  }
 }
 return(miTRUE);
}

Notes

the light array type comes with the use i_ and n_ prefix in the struct portion of the C source. i_ gives the index to the first light, and n_ gives the number of lights. The miTag string is the same as a light type except its in array form now, light[1], note, not light[0], because 0 is the base address of the array(i think). 

0 comments:

Post a Comment