Shader density_volume

Click on the filename to display or download the file.

density_volume.mi
declare shader 
    color "density_volume" ( 
	color  "color" default 1 1 1 1, 
	vector "center" default 0 0 0, 
	scalar "radius" default 1, 
	scalar "unit_density" default 1, 
	scalar "march_increment" default 0.1 ) 
    version 1 
    apply volume 
end declare 

density_volume.c
#include "shader.h" 
#include "miaux.h" 
 
struct density_volume { 
    miColor color; 
    miVector center; 
    miScalar radius; 
    miScalar unit_density; 
    miScalar march_increment; 
}; 
 
DLLEXPORT 
int density_volume_version(void) { return 1; } 
 
DLLEXPORT 
miBoolean density_volume (  
    miColor *result, miState *state, struct density_volume *params  ) 
{ 
    miScalar march_increment = *mi_eval_scalar(&params->march_increment); 
    miColor *color = mi_eval_color(&params->color); 
    miVector *center = mi_eval_vector(&params->center); 
    miScalar radius = *mi_eval_scalar(&params->radius); 
    miScalar unit_density = *mi_eval_scalar(&params->unit_density); 
    miScalar distance, accumulated_density = 0.0; 
    miVector march_point, internal_center; 
    mi_point_from_object(state, &internal_center, center); 
 
    for (distance = 0; distance <= state->dist; distance += march_increment) { 
        miaux_march_point(&march_point, state, distance); 
        accumulated_density +=  
            miaux_density_falloff(&march_point, &internal_center, radius,  
                                  unit_density, march_increment); 
        if (accumulated_density > 1.0) { 
            accumulated_density = 1.0; 
            break; 
        } 
    } 
    if (accumulated_density > 0.0) 
        miaux_blend_colors(result, result, color, 1.0 - accumulated_density); 
 
    return miTRUE; 
} 

density_volume_util.c
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; 
} 
 
miScalar miaux_density_falloff( 
    miVector *point, miVector *center, miScalar radius,  
    miScalar unit_density, miScalar march_increment) 
{ 
    return march_increment * unit_density *  
	miaux_fit_clamp(mi_vector_dist(center, point), 0.0, radius, 1.0, 0.0); 
} 
 
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:53