Shader Writing Sub Surface Test

I’ve been sick the past two days so I decided to get visual studio and learn mental ray shader writing. Once I got visual studio working it was pretty easy, it seams to tell me on compile if I’ve made a mistake so I just kept compiling and fixing until the thing works, then boot maya up and see how the shader acts.

The biggest issues so far are dealing with all the *s and &s and knowing when to use an mi_eval. I’m going to probably try and get a basic C++ book to get me through that stuff. The other weird thing was dealing with shader state, this seams to be very object oriented and very much the opposite RSL. Anyway here’s my first render from my SS shader:

I realize there’s some odds and ends in here, unused variables and redundancy.  The next one will be nicer!


struct my_shader{
    miColor    diff;
    miScalar    exponent;
    miScalar    scatter_cone;
    miColor    front;
    miColor   back;
    miScalar    blend_len;
    miScalar    blend_exp;
    int    count;
    int    i_lights;
    int    n_lights;
    miTag    *light[1];
};
DLLEXPORT miBoolean my_shader(
 miColor *result,
 miState *state,
 struct my_shader *param)
{
 miColor color;
 miVector dir;
 miColor sum;
 miColor blended_color;
 miScalar dot_nl;
 miTag* light;
 int samples;
 miScalar blend_exp = *mi_eval_scalar(¶m->blend_exp);
 miScalar blend_len = *mi_eval_scalar(¶m->blend_len);
 miScalar scatter_cone = *mi_eval_scalar(¶m->scatter_cone);
 miColor diff = *mi_eval_color(¶m->diff);
 miColor front = *mi_eval_color(¶m->front);
 miColor back = *mi_eval_color(¶m->back);
 int i_lights = *mi_eval_integer(¶m->i_lights);
 int n_lights = *mi_eval_integer(¶m->n_lights);
  
 /*
  * sample array loops
  */
 
 if (state->type == miRAY_REFRACT)
 {
  int i;
  light = mi_eval_tag(param->light)+i_lights;
  mi_instance_lightlist(&n_lights, &light, state);
  mi_vector_neg(&state->normal);
  mi_vector_neg(&state->normal_geom);
  for (i=0; i < n_lights; i++,light++)
   {
   sum.r =sum.g = sum.b = 0;
   samples = 0;
   while (mi_sample_light(&color,&dir,&dot_nl,state,*light,&samples))
    {
    sum.r += (color.r*dot_nl);
    sum.g += (color.g*dot_nl);
    sum.b += (color.b*dot_nl);
    }
   }
 
 if (samples)
  {
  result->r += diff.r*sum.r/samples;
  result->g += diff.g*sum.g/samples;
  result->b += diff.b*sum.b/samples;
  }
 mi_compute_irradiance(&sum, state);
 result->r += .3*sum.r*diff.r;
 result->g += .3*sum.g*diff.g;
 result->b += .3*sum.b*diff.b;
 result->a += 1;
 return(miTRUE);
 }
 else
  {
  miTag env_save = state->environment;
        state->environment = 0;
  miVector *scatter_dir = &state->normal;
  miVector *orig_normal = &state->normal;
  miVector *point_vec = &state->point;
  state->dir = state->normal;
  miScalar path_len = mi_scattering_pathlength(state,param->exponent);
  double path_len_dub = path_len;
  mi_ray_falloff(state,&path_len_dub,&path_len_dub);
  mi_scattering_dir_directional(scatter_dir,state,param->scatter_cone);
  if (mi_trace_refraction(&sum,state,scatter_dir))
   {
   miScalar dist = state->dist;
   miScalar blend_amount = pow(dist/blend_len,blend_exp);
   if (blend_amount > 1)
    {
    blend_amount = 1.0;
    }
   blended_color.r = (front.r*(1-blend_amount))+(back.r*(blend_amount));
   blended_color.g = (front.g*(1-blend_amount))+(back.g*(blend_amount));
   blended_color.b = (front.b*(1-blend_amount))+(back.b*(blend_amount));
   result->r += sum.r*blended_color.r;
   result->g += sum.g*blended_color.g;
   result->b += sum.b*blended_color.b;
   }
  else
   {
   miVector *offset = scatter_dir;
   mi_vector_mul(offset,path_len);
   miVector *new_point = &state->point;
   mi_vector_add(new_point,offset,point_vec);
   state->point = *new_point;
   state->pri = 0;
   path_len_dub *= 2;
   mi_ray_falloff(state,&path_len_dub,&path_len_dub);
   mi_scattering_dir_directional(scatter_dir,state,-param->scatter_cone);
   state->environment = env_save;
   if (mi_trace_refraction(&sum,state,scatter_dir))
    {
    miScalar dist = state->dist;
    miScalar blend_amount = pow((path_len+dist)/blend_len,blend_exp);
    if (blend_amount > 1)
     {
     blend_amount = 1.0;
     }
    blended_color.r = (front.r*(1-blend_amount))+(back.r*(blend_amount));
    blended_color.g = (front.g*(1-blend_amount))+(back.g*(blend_amount));
    blended_color.b = (front.b*(1-blend_amount))+(back.b*(blend_amount));
    result->r += sum.r*blended_color.r;
    result->g += sum.g*blended_color.g;
    result->b += sum.b*blended_color.b;
    }
   }
  result->a = 1;
  return(miTRUE);
  }
 
}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: