Shader depth_of_field

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(&params->focus_plane_distance); 
    miScalar blur_radius  =  
        *mi_eval_scalar(&params->blur_radius); 
    miUint number_of_samples =  
        *mi_eval_integer(&params->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