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(¶ms->base_color);
miaux_light_array(&light, &light_count, state,
¶ms->i_light, ¶ms->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