From b6d6b32a6f02965e1d088adaa6a0e051d620b878 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 12 Apr 2011 14:09:46 -0400 Subject: Fix up translucency semantics and API. --- libdimension/color.c | 39 ++++++++++++++++++++++++++++++--------- libdimension/dimension/color.h | 8 ++++++-- libdimension/raytrace.c | 17 +++++++---------- libdimension/sky_sphere.c | 5 ++--- 4 files changed, 45 insertions(+), 24 deletions(-) (limited to 'libdimension') diff --git a/libdimension/color.c b/libdimension/color.c index 2424e61..0b74adf 100644 --- a/libdimension/color.c +++ b/libdimension/color.c @@ -393,21 +393,42 @@ dmnsn_color_gradient(dmnsn_color c1, dmnsn_color c2, double n) return ret; } -/* Filters `color' through `filter' */ +/* Filters `light' through `filter' */ dmnsn_color -dmnsn_color_filter(dmnsn_color color, dmnsn_color filter) +dmnsn_filter_light(dmnsn_color light, dmnsn_color filter) { - dmnsn_color transmitted = dmnsn_color_mul(filter.trans, color); - dmnsn_color filtered = dmnsn_color_mul(filter.filter, - dmnsn_color_illuminate(filter, color)); - + dmnsn_color transmitted = dmnsn_color_mul(filter.trans, light); + dmnsn_color filtered = dmnsn_color_mul( + filter.filter, + dmnsn_color_illuminate(filter, light) + ); dmnsn_color ret = dmnsn_color_add(transmitted, filtered); - ret.filter = color.filter*dmnsn_color_intensity(filtered) - + filter.filter*color.trans + filter.trans*color.filter; - ret.trans = filter.trans*color.trans; + ret.filter = light.filter*dmnsn_color_intensity(filtered) + + filter.filter*light.trans + filter.trans*light.filter; + ret.trans = filter.trans*light.trans; + return ret; +} + +/* Adds the background contribution, `filtered', to `filter' */ +dmnsn_color +dmnsn_apply_translucency(dmnsn_color filtered, dmnsn_color filter) +{ + dmnsn_color ret = dmnsn_color_add( + dmnsn_color_mul(1.0 - (filter.filter + filter.trans), filter), + filtered + ); + ret.filter = filtered.filter; + ret.trans = filtered.trans; return ret; } +/* Adds the background contribution of `color' to `filter' */ +dmnsn_color +dmnsn_apply_filter(dmnsn_color color, dmnsn_color filter) +{ + return dmnsn_apply_translucency(dmnsn_filter_light(color, filter), filter); +} + /* Illuminates `color' with `light' */ dmnsn_color dmnsn_color_illuminate(dmnsn_color light, dmnsn_color color) diff --git a/libdimension/dimension/color.h b/libdimension/dimension/color.h index 363eb56..c9d777b 100644 --- a/libdimension/dimension/color.h +++ b/libdimension/dimension/color.h @@ -127,8 +127,12 @@ dmnsn_color dmnsn_color_add(dmnsn_color color1, dmnsn_color color2); dmnsn_color dmnsn_color_mul(double n, dmnsn_color color); /** Return the color at \p n on a gradient from \p c1 at 0 to \p c2 at 1. */ dmnsn_color dmnsn_color_gradient(dmnsn_color c1, dmnsn_color c2, double n); -/** Filter \p color through \p filter. */ -dmnsn_color dmnsn_color_filter(dmnsn_color color, dmnsn_color filter); +/** Filter \p light through \p filter. */ +dmnsn_color dmnsn_filter_light(dmnsn_color light, dmnsn_color filter); +/** Add the background contribution \p filtered to \p filter. */ +dmnsn_color dmnsn_apply_translucency(dmnsn_color filtered, dmnsn_color filter); +/** Add the background contribution of \p color to \p filter. */ +dmnsn_color dmnsn_apply_filter(dmnsn_color color, dmnsn_color filter); /** Illuminate \p color with \p light. */ dmnsn_color dmnsn_color_illuminate(dmnsn_color light, dmnsn_color color); diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c index 1379c29..7a797bf 100644 --- a/libdimension/raytrace.c +++ b/libdimension/raytrace.c @@ -216,7 +216,7 @@ dmnsn_raytrace_background(dmnsn_raytrace_state *state, dmnsn_line ray) { dmnsn_color sky = dmnsn_sky_sphere_color(state->scene->sky_sphere, dmnsn_vector_normalize(ray.n)); - color = dmnsn_color_add(dmnsn_color_filter(color, sky), sky); + color = dmnsn_apply_filter(color, sky); } return color; @@ -269,7 +269,7 @@ dmnsn_raytrace_light_ray(const dmnsn_raytrace_state *state, dmnsn_raytrace_pigment(&shadow_state); if ((state->scene->quality & DMNSN_RENDER_TRANSLUCENCY) && (shadow_state.pigment.filter || shadow_state.pigment.trans)) { - color = dmnsn_color_filter(color, shadow_state.pigment); + color = dmnsn_filter_light(color, shadow_state.pigment); shadow_ray.x0 = dmnsn_line_point(shadow_ray, shadow_caster.t); shadow_ray.n = dmnsn_vector_sub(light->x0, shadow_ray.x0); shadow_ray = dmnsn_line_add_epsilon(shadow_ray); @@ -396,14 +396,11 @@ dmnsn_raytrace_translucency(dmnsn_raytrace_state *state) ); } - state->diffuse = dmnsn_color_mul( - 1.0 - state->pigment.filter - state->pigment.trans, - state->diffuse - ); - dmnsn_color rec = dmnsn_raytrace_shoot(&recursive_state, trans_ray); - dmnsn_color filtered = dmnsn_color_filter(rec, state->pigment); - state->additional = dmnsn_color_add(filtered, state->additional); + dmnsn_color filtered = dmnsn_filter_light(rec, state->pigment); + state->diffuse.filter = state->pigment.filter; + state->diffuse.trans = state->pigment.trans; + state->diffuse = dmnsn_apply_translucency(filtered, state->diffuse); } } @@ -411,7 +408,7 @@ dmnsn_raytrace_translucency(dmnsn_raytrace_state *state) static dmnsn_color dmnsn_raytrace_shoot(dmnsn_raytrace_state *state, dmnsn_line ray) { - if (state->reclevel <= 0) + if (state->reclevel == 0) return dmnsn_black; --state->reclevel; diff --git a/libdimension/sky_sphere.c b/libdimension/sky_sphere.c index 9643feb..0ea5fa3 100644 --- a/libdimension/sky_sphere.c +++ b/libdimension/sky_sphere.c @@ -58,14 +58,13 @@ dmnsn_initialize_sky_sphere(dmnsn_sky_sphere *sky_sphere) dmnsn_color dmnsn_sky_sphere_color(const dmnsn_sky_sphere *sky_sphere, dmnsn_vector d) { - dmnsn_color color = dmnsn_black; - color.trans = 1.0; + dmnsn_color color = dmnsn_clear; DMNSN_ARRAY_FOREACH (const dmnsn_pigment **, pigment, sky_sphere->pigments) { dmnsn_pigment_fn *pigment_fn = (*pigment)->pigment_fn; if (pigment_fn) { dmnsn_color sky = pigment_fn(*pigment, d); - color = dmnsn_color_add(dmnsn_color_filter(color, sky), sky); + color = dmnsn_apply_filter(color, sky); } } -- cgit v1.2.3