Shader soft_spotlight

Click on the filename to display or download the file.

soft_spotlight.mi
declare shader 
    color "soft_spotlight" ( 
        color "light_color" default 1 1 1, 
        scalar "inner_spread" default 1 ) 
    version 1 
    apply light 
end declare 

soft_spotlight.c
#include "shader.h" 
#include "miaux.h" 
 
struct soft_spotlight { 
    miColor light_color; 
    miScalar inner_spread; 
}; 
 
DLLEXPORT 
int soft_spotlight_version(void) { return 1; } 
 
DLLEXPORT 
miBoolean soft_spotlight ( 
    miColor *result, miState *state, struct soft_spotlight *params ) 
{ 
    miScalar inner_spread, attenuation; 
    miTag light_tag = miaux_current_light_tag(state); 
    miScalar offset_spread = miaux_offset_spread_from_light(state, light_tag); 
    miScalar light_spread = miaux_light_spread(state, light_tag); 
 
    if (offset_spread < light_spread) 
        return miFALSE; 
 
    *result = *mi_eval_color(&params->light_color); 
    inner_spread = *mi_eval_scalar(&params->inner_spread); 
 
    if (offset_spread < inner_spread) { 
        attenuation = miaux_fit(offset_spread, inner_spread, light_spread, 1, 0); 
        miaux_scale_color(result, attenuation); 
    } 
    return mi_trace_shadow(result, state); 
} 

soft_spotlight_util.c
miTag miaux_current_light_tag(miState *state) 
{ 
    miTag light_tag; 
    mi_query(miQ_INST_ITEM, state, state->light_instance, &light_tag); 
    return light_tag; 
} 
 
miScalar miaux_offset_spread_from_light(miState *state, miTag light_tag) 
{ 
    miVector light_direction, light_to_sample_point; 
 
    mi_query(miQ_LIGHT_DIRECTION, state, light_tag, &light_direction); 
    mi_vector_normalize(&light_direction); 
 
    mi_vector_to_light(state, &light_to_sample_point, &state->dir); 
    mi_vector_normalize(&light_to_sample_point);  
 
    return mi_vector_dot(&light_to_sample_point, &light_direction); 
} 
 
miScalar miaux_light_spread(miState *state, miTag light_tag) 
{ 
    miScalar light_spread; 
    mi_query(miQ_LIGHT_SPREAD, state, light_tag, &light_spread); 
    return light_spread; 
} 
 
double miaux_fit( 
    double v, double oldmin, double oldmax, double newmin, double newmax)     
{ 
    return newmin + ((v - oldmin) / (oldmax - oldmin)) * (newmax - newmin); 
} 
 
void miaux_scale_color(miColor *result, miScalar scale) 
{ 
    result->r *= scale; 
    result->g *= scale; 
    result->b *= scale; 
} 

22 April 2008 23:40:05