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(¶ms->fade_start);
miScalar fade_end = *mi_eval_scalar(¶ms->fade_end);
miVector world_point, march_point;
if (state->dist == 0.0)
return miTRUE;
else if (*mi_eval_boolean(¶ms->show_layers)) {
miColor* full_fog_marker =
mi_eval_color(¶ms->full_fog_marker);
miColor* partial_fog_marker =
mi_eval_color(¶ms->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(¶ms->fog_density);
miScalar march_increment = *mi_eval_scalar(¶ms->march_increment);
miScalar unit_density = *mi_eval_scalar(¶ms->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(¶ms->fog_color);
return miTRUE;
}
}
if (accumulated_density > 0.0) {
miaux_blend_colors(result, result, mi_eval_color(¶ms->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