Shader ward

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(&params->diffuse); 
    miColor *glossy        = mi_eval_color(&params->glossy); 
    miScalar shiny_u_coeff = *mi_eval_scalar(&params->shiny_u_coeff); 
    miScalar shiny_v_coeff = *mi_eval_scalar(&params->shiny_v_coeff); 
    miaux_light_array(&light, &light_count, state, 
                      &params->i_light, &params->n_light, params->light); 
    *result = *mi_eval_color(&params->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