Shader shadowpass

Click on the filename to display or download the file.

shadowpass.mi
declare shader 
    color "shadowpass" ( 
        color "base_color", 
        array light "lights" ) 
    version 1 
    apply material 
end declare 

shadowpass.c
#include "shader.h" 
#include "miaux.h" 
 
struct shadowpass { 
    miColor base_color; 
    int     i_light; 
    int     n_light; 
    miTag   light[1]; 
}; 
 
DLLEXPORT 
int shadowpass_version(void) { return 1; } 
 
DLLEXPORT 
miBoolean shadowpass ( 
    miColor *result, miState *state, struct shadowpass *params  ) 
{ 
    int i, light_count; 
    miTag *light; 
    miColor without_shadow, with_shadow, shadow; 
    miColor *base_color = mi_eval_color(&params->base_color); 
    miaux_light_array(&light, &light_count, state, 
                      &params->i_light, &params->n_light, params->light); 
 
    miaux_set_channels(&without_shadow, 0.0); 
    miaux_set_channels(&with_shadow, 0.0); 
 
    for (i = 0; i < light_count; i++, light++) { 
        miaux_add_light_color(&without_shadow, state, *light, miFALSE); 
        miaux_add_light_color(&with_shadow, state, *light, miTRUE); 
    } 
    miaux_divide_colors(&shadow, &with_shadow, &without_shadow); 
 
    miaux_multiply_colors(result, base_color, &shadow); 
    mi_fb_put(state, 0, base_color); 
    mi_fb_put(state, 1, &shadow); 
 
    return miTRUE; 
} 

shadowpass_util.c
void miaux_light_array(miTag **lights, int *light_count, miState *state, 
		       int *offset_param, int *count_param, miTag *lights_param) 
{ 
    int array_offset = *mi_eval_integer(offset_param); 
    *light_count = *mi_eval_integer(count_param); 
    *lights = mi_eval_tag(lights_param) + array_offset; 
} 
 
void miaux_set_channels(miColor *c, miScalar new_value) 
{ 
    c->r = c->g = c->b = c->a = new_value; 
} 
 
void miaux_add_light_color( 
    miColor *result, miState *state, miTag light, char shadow_state) 
{ 
    int light_sample_count = 0; 
    miScalar dot_nl; 
    miVector direction_toward_light; 
    miColor sample_color, single_light_color; 
 
    const miOptions *original_options = state->options; 
    miOptions options_copy = *original_options; 
    options_copy.shadow = shadow_state; 
    state->options = &options_copy; 
 
    miaux_set_channels(&single_light_color, 0.0); 
    while (mi_sample_light(&sample_color, &direction_toward_light, 
			   &dot_nl, state, light, &light_sample_count)) 
	miaux_add_scaled_color(&single_light_color, &sample_color, dot_nl); 
    if (light_sample_count) 
	miaux_add_scaled_color(result, &single_light_color, 
			       1.0/light_sample_count); 
 
    state->options = (miOptions*)original_options; 
} 
 
void miaux_add_scaled_color(miColor *result, miColor *color, miScalar scale) 
{ 
    result->r += color->r * scale; 
    result->g += color->g * scale; 
    result->b += color->b * scale; 
} 
 
void miaux_divide_colors(miColor *result, miColor *x, miColor *y) 
{ 
    result->r = y->r == 0.0 ? 1.0 : x->r / y->r; 
    result->g = y->g == 0.0 ? 0.0 : x->g / y->g; 
    result->b = y->b == 0.0 ? 1.0 : x->b / y->b; 
} 
 
void miaux_multiply_colors(miColor *result, miColor *x, miColor *y) 
{ 
    result->r = x->r * y->r; 
    result->g = x->g * y->g; 
    result->b = x->b * y->b; 
} 

22 April 2008 23:41:02