Click on the filename to display or download the file.
depth_of_field.mi
declare shader
color "depth_of_field" (
scalar "focus_plane_distance" default 1,
scalar "blur_radius" default .1,
integer "number_of_samples" default 1 )
version 1
apply lens
scanline off
trace on
end declare
depth_of_field.c
#include
#include
#include "shader.h"
#include "miaux.h"
struct depth_of_field {
miScalar focus_plane_distance;
miScalar blur_radius;
miInteger number_of_samples;
};
DLLEXPORT
int depth_of_field_version(void) { return 1; }
DLLEXPORT
miBoolean depth_of_field (
miColor *result, miState *state, struct depth_of_field *params )
{
miScalar focus_plane_distance =
*mi_eval_scalar(¶ms->focus_plane_distance);
miScalar blur_radius =
*mi_eval_scalar(¶ms->blur_radius);
miUint number_of_samples =
*mi_eval_integer(¶ms->number_of_samples);
miVector camera_origin, camera_direction, origin, direction, focus_point;
double samples[2], focus_plane_z;
int sample_number = 0;
miColor sum = {0,0,0,0}, single_trace;
miaux_to_camera_space(state, &camera_origin, &camera_direction);
focus_plane_z = state->org.z - focus_plane_distance;
miaux_z_plane_intersect(
&focus_point, &camera_origin, &camera_direction, focus_plane_z);
while (mi_sample(samples, &sample_number, state, 2, &number_of_samples)) {
miaux_sample_point_within_radius(
&origin, &camera_origin, samples[0], samples[1], blur_radius);
mi_vector_sub(&direction, &focus_point, &origin);
mi_vector_normalize(&direction);
miaux_from_camera_space(state, &origin, &direction);
mi_trace_eye(&single_trace, state, &origin, &direction);
miaux_add_color(&sum, &single_trace);
}
miaux_divide_color(result, &sum, number_of_samples);
return miTRUE;
}
depth_of_field_util.c
void miaux_to_camera_space(
miState *state, miVector *origin, miVector *direction)
{
mi_point_to_camera(state, origin, &state->org);
mi_vector_to_camera(state, direction, &state->dir);
}
void miaux_z_plane_intersect(
miVector *result, miVector *origin, miVector *direction, miScalar z_plane)
{
miScalar z_delta = (z_plane - origin->z) / direction->z;
result->x = origin->x + z_delta * direction->x;
result->y = origin->y + z_delta * direction->y;
result->z = z_plane;
}
void miaux_sample_point_within_radius(
miVector *result, miVector *center, float x, float y, float max_radius)
{
float x_offset, y_offset;
miaux_square_to_circle(&x_offset, &y_offset, x, y, max_radius);
result->x = center->x + x_offset;
result->y = center->y + y_offset;
result->z = center->z;
}
void miaux_square_to_circle(
float *result_x, float *result_y, float x, float y, float max_radius)
{
float angle = M_PI * 2 * x;
float radius = max_radius * sqrt(y);
*result_x = radius * cos(angle);
*result_y = radius * sin(angle);
}
void miaux_from_camera_space(
miState *state, miVector *origin, miVector *direction)
{
mi_point_from_camera(state, origin, origin);
mi_vector_from_camera(state, direction, direction);
}
void miaux_add_color(miColor *result, miColor *c)
{
result->r += c->r;
result->g += c->g;
result->b += c->b;
result->a += c->a;
}
void miaux_divide_colors(miColor *result, miColor *x, miColor *y)
{
result->r = y->r == 0.0 ? 1.0 : x->r / y->r;
result->g = y->g == 0.0 ? 0.0 : x->g / y->g;
result->b = y->b == 0.0 ? 1.0 : x->b / y->b;
}
22 April 2008 23:41:00