Shader ground_fog_layers

Click on the filename to display or download the file.

ground_fog_layers.mi
declare shader  
    color "ground_fog_layers" ( 
	color   "fog_color"          default 1 1 1, 
	color   "fog_density"        default 1 1 1, 
	scalar  "fade_start"         default 0, 
	scalar  "fade_end"           default 1, 
	scalar  "unit_density"       default 1, 
	scalar  "march_increment"    default 0.1, 
	boolean "show_layers"        default off, 
	color   "full_fog_marker"    default 1.1 .9 .9, 
	color   "partial_fog_marker" default .9 1.1 .9 ) 
    version 1 
    apply volume 
end declare 

ground_fog_layers.c
#include "shader.h" 
#include "miaux.h" 
 
struct ground_fog_layers { 
    miColor fog_color; 
    miColor fog_density; 
    miScalar fade_start; 
    miScalar fade_end; 
    miScalar unit_density; 
    miScalar march_increment; 
    miBoolean show_layers; 
    miColor full_fog_marker; 
    miColor partial_fog_marker; 
}; 
 
DLLEXPORT 
int ground_fog_layers_version(void) { return 1; } 
 
DLLEXPORT 
miBoolean ground_fog_layers ( 
     miColor *result, miState *state, struct ground_fog_layers *params  ) 
{ 
    miScalar fade_start = *mi_eval_scalar(&params->fade_start); 
    miScalar fade_end = *mi_eval_scalar(&params->fade_end); 
    miVector world_point, march_point; 
 
    if (state->dist == 0.0)  
        return miTRUE; 
    else if (*mi_eval_boolean(&params->show_layers)) { 
        miColor* full_fog_marker =  
            mi_eval_color(&params->full_fog_marker); 
        miColor* partial_fog_marker =  
            mi_eval_color(&params->partial_fog_marker); 
 
        mi_point_to_world(state, &world_point, &state->point); 
        if (world_point.y < fade_start) 
            miaux_multiply_colors(result, result, full_fog_marker); 
        else if (world_point.y < fade_end) 
            miaux_multiply_colors(result, result, partial_fog_marker); 
    } else { 
        miScalar fog_density = *mi_eval_scalar(&params->fog_density);  
        miScalar march_increment = *mi_eval_scalar(&params->march_increment); 
        miScalar unit_density = *mi_eval_scalar(&params->unit_density); 
        miScalar accumulated_density = 0.0, distance, density_factor; 
         
        for (distance = 0; distance < state->dist; distance += march_increment) { 
            miaux_world_space_march_point(&march_point, state, distance); 
            density_factor = miaux_fit_clamp( 
                march_point.y, fade_start, fade_end, fog_density, 0.0); 
            accumulated_density +=  
                density_factor * march_increment * unit_density; 
            if (accumulated_density > 1.0) { 
                *result = *mi_eval_color(&params->fog_color); 
                return miTRUE; 
            } 
        } 
        if (accumulated_density > 0.0) { 
            miaux_blend_colors(result, result, mi_eval_color(&params->fog_color), 
                               1.0 - accumulated_density); 
        } 
    } 
    return miTRUE; 
} 

ground_fog_layers_util.c
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_world_space_march_point( 
    miVector *result, miState *state, miScalar distance) 
{ 
    miaux_march_point(result, state, distance); 
    mi_vector_to_world(state, result, result); 
} 
 
void miaux_march_point( 
    miVector *result, miState *state, miScalar distance) 
{ 
    miaux_point_along_vector(result, &state->org, &state->dir, distance); 
} 
 
void miaux_point_along_vector( 
    miVector *result, miVector *point, miVector *direction, miScalar distance) 
{ 
    result->x = point->x + distance * direction->x; 
    result->y = point->y + distance * direction->y; 
    result->z = point->z + distance * direction->z; 
} 
 
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); 
} 
 
double miaux_fit( 
    double v, double oldmin, double oldmax, double newmin, double newmax)     
{ 
    return newmin + ((v - oldmin) / (oldmax - oldmin)) * (newmax - newmin); 
} 
 
void miaux_blend_colors(miColor *result,  
			miColor *color1, miColor *color2, miScalar factor) 
{ 
    result->r = miaux_blend(color1->r, color2->r, factor); 
    result->g = miaux_blend(color1->g, color2->g, factor); 
    result->b = miaux_blend(color1->b, color2->b, factor); 
} 
 
double miaux_blend(miScalar a, miScalar b, miScalar factor) 
{ 
    return a * factor + b * (1.0 - factor); 
} 

22 April 2008 23:40:51