Hi, I have only learned Mental Ray for one month, and now I find a big problem. I have spent one day to conquer it, but found it impossible for me.
My shader needs to ray trace several times in different positions to different directions to make Monte Carlo integration. But now I find trouble in the ray trace.
I cut some part of my shader below to do the debug. If it works, then so will my shader.
Tag is a flag which I defined. When tag is 0, I use ray trace, from the point below the current intersect point, to the direction same as the surface’s normal.
When tag is 2, the ray hit the back side of the surface, I calculate the light radiance, and send it back in result.
I create a sphere in Maya and add my shader and a point light(decay rate: linear) to it, and render it in 640*480. Set the sample number to 30 or bigger, then bugs will occur different times in different area, which drives me crazy.
I need help. Please, HELP ME!!!
Thanks to everyone who have spent time reading my question and sorry for my poor English.
//subscatter.c
#include <stdio.h>
#include <stdlib.h> /* for abs /
#include <float.h> / for FLT_MAX */
#include <math.h>
#include <string.h>
#include <assert.h>
#include “shader.h”
struct subscatter {
int sample_num;
int mode; /* light mode: 0…2 /
int i_light; / index of first light /
int n_light; / number of lights /
miTag light[1]; / list of lights */
};
DLLEXPORT int subscatter_version(void) {return(1);}
static int tag = 0;
static miTag light_tag; /* tag of light instance */
DLLEXPORT miBoolean subscatter(
miColor *result,
miState *state,
struct subscatter *paras)
{
miVector old_state_dir;
miVector old_state_point;
void * old_state_pri;
int m; /* light mode: 0=all, 1=incl, 2=excl */
miTag *light; /* tag of light instance */
int n_l; /* number of light sources */
int i_l; /* offset of light sources */
int sam_num;
int light_samples; /* # of samples taken */
miColor color; /* color from light source */
miColor light_sum; /* summed sample colors */
miVector dir; /* direction towards light */
miScalar dot_nl; /* dot prod of normal and dir */
int n; /* light counter */
miVector p_x0;
miVector normal;
miVector watch_dir;
int i;
miVector p_intersect;
miColor Li;
sam_num = *mi_eval_integer(¶s->sample_num);
if (tag == 2) //hit the back side of the material: tag = 2
//I still have a tag=1, but I don't leave it here
{
light_sum.r = light_sum.g = light_sum.b = 0;
light_samples = 0;
old_state_pri = state->pri;
state->pri = 0;
while (mi_sample_light(&color, &dir, &dot_nl, state,
light_tag, &light_samples)) {
light_sum.r += color.r;
light_sum.g += color.g;
light_sum.b += color.b;
}
if (light_samples) {
light_sum.r /= light_samples;
light_sum.g /= light_samples;
light_sum.b /= light_samples;
}
result->r = light_sum.r;
result->g = light_sum.g;
result->b = light_sum.b;
state->pri = old_state_pri;
return(miTRUE);
}
// hit the front side of the material: tag = 0
result->r = 0.0;
result->g = 0.0;
result->b = 0.0;
m = *mi_eval_integer(¶s->mode);
n_l = *mi_eval_integer(¶s->n_light);
i_l = *mi_eval_integer(¶s->i_light);
light = mi_eval_tag(paras->light) + i_l;
if (m == 1) /* modify light list (inclusive mode) */
mi_inclusive_lightlist(&n_l, &light, state);
else if (m == 2) /* modify light list (exclusive mode) */
mi_exclusive_lightlist(&n_l, &light, state);
normal = state->normal;
watch_dir = state->dir;
p_x0 = state->point;
//Loop over all light sources
for (n=0; n < n_l; n++, light++)
{
light_tag = *light;
for (i=0; i<sam_num; i++)
{// In my shader, there is a while loop use mi_sample()
// to make Monte Carlo integration.
//But in debug, this for loop is enough.
//My trouble is that the more times I trace (it means the bigger sam_num),
// the larger broken partition I'll have after rendering.
state->cache = 0 ;
old_state_dir = state->dir;
old_state_point = state->point;
state->dir = normal;
p_intersect.x = p_x0.x - normal.x * 0.01;
p_intersect.y = p_x0.y - normal.y * 0.01;
p_intersect.z = p_x0.z - normal.z * 0.01;
state->point = p_intersect;
tag = 2;
mi_trace_transparent(&Li, state);
state->dir = old_state_dir;
state->point = old_state_point;
}
*result = Li;
}
tag =0;
return miTRUE;
}
//subscatter.mi
declare shader
color “subscatter” (
integer “sample_num”,
integer “mode”, # light selection mode 0…2
array light “lights”
)
version 1
apply material
end declare