Shader ground_fog

Click on the filename to display or download the file.

ground_fog.mi
declare shader  
    color "ground_fog" ( 
	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, ) 
    version 1 
    apply volume 
end declare 

ground_fog.c
#include "shader.h" 
#include "miaux.h" 
 
struct ground_fog { 
    miColor fog_color; 
    miColor fog_density; 
    miScalar fade_start; 
    miScalar fade_end; 
    miScalar unit_density; 
    miScalar march_increment; 
}; 
 
DLLEXPORT 
int ground_fog_version(void) { return 1; } 
 
DLLEXPORT 
miBoolean ground_fog ( 
    miColor *result, miState *state, struct ground_fog *params  ) 
{ 
    miScalar fade_start, fade_end, fog_density, distance, density_factor, 
        march_increment, unit_density, accumulated_density; 
    miVector march_point; 
     
    if (state->dist == 0) 
        return miTRUE; 
 
    fade_start = *mi_eval_scalar(&params->fade_start); 
    fade_end = *mi_eval_scalar(&params->fade_end); 
    fog_density = *mi_eval_scalar(&params->fog_density);  
    march_increment = *mi_eval_scalar(&params->march_increment); 
    unit_density = *mi_eval_scalar(&params->unit_density); 
    accumulated_density = 0.0; 
 
    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_util.c
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:50