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(¶ms->diffuse);
miColor *specular = mi_eval_color(¶ms->specular);
miColor *cutoff = mi_eval_color(¶ms->cutoff);
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_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