Click on the filename to display or download the file.
ward.mi
declare shader
color "ward" (
color "ambient" default 0 0 0,
color "diffuse" default 1 1 1,
color "glossy" default 0 0 0,
scalar "shiny_u_coeff" default 10,
scalar "shiny_v_coeff" default 10,
array light "lights" )
version 1
apply material
end declare
ward.c
#include "shader.h"
#include "miaux.h"
struct ward {
miColor ambient;
miColor diffuse;
miColor glossy;
miScalar shiny_u_coeff;
miScalar shiny_v_coeff;
int i_light;
int n_light;
miTag light[1];
};
DLLEXPORT
int ward_version(void) { return 1; }
DLLEXPORT
miBoolean ward (
miColor *result, miState *state, struct ward *params )
{
int i, light_count, light_sample_count;
miColor sum, light_color;
miVector direction_toward_light;
miScalar dot_nl;
miTag* light;
miColor *diffuse = mi_eval_color(¶ms->diffuse);
miColor *glossy = mi_eval_color(¶ms->glossy);
miScalar shiny_u_coeff = *mi_eval_scalar(¶ms->shiny_u_coeff);
miScalar shiny_v_coeff = *mi_eval_scalar(¶ms->shiny_v_coeff);
miaux_light_array(&light, &light_count, state,
¶ms->i_light, ¶ms->n_light, params->light);
*result = *mi_eval_color(¶ms->ambient);
for (i = 0; i < light_count; i++, light++) {
miaux_set_channels(&sum, 0);
light_sample_count = 0;
while (mi_sample_light(&light_color, &direction_toward_light, &dot_nl,
state, *light, &light_sample_count)) {
miaux_add_diffuse_component(&sum, dot_nl, diffuse, &light_color);
miaux_add_ward_specular_component(
&sum, state, shiny_u_coeff, shiny_v_coeff, glossy, dot_nl,
direction_toward_light, &light_color);
}
if (light_sample_count)
miaux_add_scaled_color(result, &sum, 1.0/light_sample_count);
}
return miTRUE;
}
ward_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_diffuse_component(
miColor *result,
miScalar light_and_surface_cosine,
miColor *diffuse, miColor *light_color)
{
result->r += light_and_surface_cosine * diffuse->r * light_color->r;
result->g += light_and_surface_cosine * diffuse->g * light_color->g;
result->b += light_and_surface_cosine * diffuse->b * light_color->b;
}
void miaux_add_ward_specular_component(
miColor *result, miState *state,
miScalar shiny_u, miScalar shiny_v,
miColor *glossy, miScalar normal_dot_light,
miVector direction_toward_light,
miColor *light_color)
{
miScalar specular_reflection_amount;
if (shiny_u == shiny_v) /* Isotropic */
specular_reflection_amount = normal_dot_light *
mi_ward_glossy(
&state->dir, &direction_toward_light, &state->normal, shiny_u);
else { /* Anisotropic */
miVector u = state->derivs[0], v;
float d = mi_vector_dot(&u, &state->normal);
u.x -= d * state->normal.x;
u.y -= d * state->normal.y;
u.z -= d * state->normal.z;
mi_vector_normalize(&u);
/* Set v to be perpendicular to u (in the tangent plane) */
mi_vector_prod(&v, &state->normal, &u);
specular_reflection_amount = normal_dot_light *
mi_ward_anisglossy(&state->dir, &direction_toward_light,
&state->normal, &u, &v, shiny_u, shiny_v);
}
if (specular_reflection_amount > 0.0) {
result->r += specular_reflection_amount * glossy->r * light_color->r;
result->g += specular_reflection_amount * glossy->g * light_color->g;
result->b += specular_reflection_amount * glossy->b * light_color->b;
}
}
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;
}
22 April 2008 23:40:11