Shader mock_specular

Click on the filename to display or download the file.

mock_specular.mi
declare shader 
    color "mock_specular" ( 
        color "ambient"  default 0 0 0, 
        color "diffuse"  default 1 1 1, 
	color "specular" default 1 1 1, 
	color "cutoff"   default .95 .95 .95, 
        array light "lights" ) 
    version 1 
    apply material 
end declare 

mock_specular.c
#include "shader.h" 
#include "miaux.h" 
 
struct mock_specular { 
    miColor ambient;  
    miColor diffuse;  
    miColor specular; 
    miColor cutoff;  
    int     i_light;  
    int     n_light;  
    miTag   light[1]; 
}; 
 
DLLEXPORT 
int mock_specular_version(void) { return 1; } 
 
DLLEXPORT 
miBoolean mock_specular ( 
    miColor *result, miState *state, struct mock_specular *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 *specular = mi_eval_color(&params->specular); 
    miColor *cutoff   = mi_eval_color(&params->cutoff); 
    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_mock_specular_component( 
                &sum, state, &direction_toward_light,  
                specular, cutoff, &light_color); 
        } 
        if (light_sample_count) 
            miaux_add_scaled_color(result, &sum, 1/light_sample_count); 
    }         
    return miTRUE; 
} 

mock_specular_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_mock_specular_component( 
    miColor *result, miState *state, 
    miVector *direction_toward_light, 
    miColor *specular_color, 
    miColor *cutoff, 
    miColor *light_color) 
{ 
    miScalar lightdir_offset, r_scale, g_scale, b_scale; 
    miColor attenuated_specular = {0,0,0,0}; 
 
    lightdir_offset = mi_vector_dot(&state->normal, direction_toward_light); 
    r_scale = miaux_sinusoid_fit_clamp(lightdir_offset, cutoff->r, 1.0, 0, 1); 
    g_scale = miaux_sinusoid_fit_clamp(lightdir_offset, cutoff->g, 1.0, 0, 1); 
    b_scale = miaux_sinusoid_fit_clamp(lightdir_offset, cutoff->b, 1.0, 0, 1); 
 
    miaux_scale_channels(&attenuated_specular, specular_color, 
			 r_scale, g_scale, b_scale); 
    miaux_multiply_colors(light_color, light_color, &attenuated_specular); 
    miaux_add_color(result, light_color); 
} 
 
double miaux_sinusoid_fit_clamp( 
    double v, double oldmin, double oldmax, double newmin, double newmax) 
{ 
    return miaux_fit(sin(miaux_fit_clamp(v, oldmin, oldmax, -M_PI_2, M_PI_2)),  
		     -1, 1, newmin, newmax); 
} 
 
double miaux_fit( 
    double v, double oldmin, double oldmax, double newmin, double newmax)     
{ 
    return newmin + ((v - oldmin) / (oldmax - oldmin)) * (newmax - newmin); 
} 
 
double miaux_fit_clamp( 
    double v, double oldmin, double oldmax, double newmin, double newmax) 
{ 
    if (oldmin > oldmax) { 
	double temp = oldmin; 
        oldmin = oldmax; 
	oldmax = oldmin; 
	temp = newmin; 
        newmin = newmax; 
	newmax = newmin; 
    } 
    if (v < oldmin) 
	return newmin; 
    else if (v > oldmax) 
	return newmax; 
    else  
	return miaux_fit(v, oldmin, oldmax, newmin, newmax); 
} 
 
void miaux_scale_channels(miColor *result, miColor* color,  
			  miScalar r_scale, miScalar g_scale, miScalar b_scale) 
{ 
    result->r = color->r * r_scale; 
    result->g = color->g * g_scale; 
    result->b = color->b * b_scale; 
} 
 
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; 
} 
 
void miaux_add_color(miColor *result, miColor *c) 
{ 
    result->r += c->r; 
    result->g += c->g; 
    result->b += c->b; 
    result->a += c->a; 
} 
 
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:12