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). 

Sunday, February 9, 2014

Writing mental ray shaders: Simpler Diffuse!!

Intro

The previous simplest diffuse shader doesn't really take lights in the scene into account. To get that information, a shader parameter declaration of type "light" will be needed. 

Mi Source
declare shader
	color "jc_simpler_diffuse" (
		color "diffuse" default 0 0 0,
		light "onelight")
	version 1
	apply material
end declare

Notes:

The shader parameter declaration of type light is a string, so in the C sturct portion we'll use miTag

C Source

#include "shader.h"

DLLEXPORT

struct jc_simpler_diffuse {
	miColor diffuse;
	miTag light;
	};

DLLEXPORT
int jc_simpler_diffuse_version(void) {return(1);}

DLLEXPORT

miBoolean jc_simpler_diffuse(
	miColor *result,
	miState *state,
	struct jc_simpler_diffuse *params) {
	
	miColor light_color;
	miVector dir;
	miScalar dot_nl;
	int samples;
	miColor *diffuse = mi_eval_color(&params->diffuse);
	miTag *light = mi_eval_tag(&params->light);
	if(mi_sample_light(&light_color, &dir, &dot_nl, state, *light, &samples)) {

	result->r = diffuse->r * dot_nl * light_color.r;
	result->g = diffuse->g * dot_nl * light_color.g;
	result->b = diffuse->b * dot_nl * light_color.b;
	result->a = 1.0;
	}
	
	
	return(miTRUE);
}

Notes

the function mi_sample_light returns light_color, direction, and the dot_nl.
Inside maya, the shader node has a text box that can create a light, or type in the light name. It only accepts a single light, thus, simpler diffuse shader. Regardless, its the first light based shader.