diff options
-rw-r--r-- | dimension/common.terminals | 2 | ||||
-rw-r--r-- | dimension/grammar.epilogue | 1 | ||||
-rw-r--r-- | dimension/grammar.rules | 5 | ||||
-rw-r--r-- | dimension/lexer.l | 1 | ||||
-rw-r--r-- | dimension/parse.h | 1 | ||||
-rw-r--r-- | dimension/realize.c | 5 | ||||
-rw-r--r-- | libdimension/dimension/scene.h | 3 | ||||
-rw-r--r-- | libdimension/raytrace.c | 26 | ||||
-rw-r--r-- | libdimension/scene.c | 1 | ||||
-rw-r--r-- | tests/dimension/demo.pov | 5 | ||||
-rwxr-xr-x | tests/dimension/demo.sh | 5 |
11 files changed, 48 insertions, 7 deletions
diff --git a/dimension/common.terminals b/dimension/common.terminals index f96a1f6..567267b 100644 --- a/dimension/common.terminals +++ b/dimension/common.terminals @@ -71,7 +71,7 @@ %token DMNSN_T_ACOS "acos" %token DMNSN_T_ACOSH "acosh" %token DMNSN_T_ADAPTIVE -%token DMNSN_T_ADC_BAILOUT +%token DMNSN_T_ADC_BAILOUT "adc_bailout" %token DMNSN_T_AGATE %token DMNSN_T_AGATE_TURB %token DMNSN_T_ALL diff --git a/dimension/grammar.epilogue b/dimension/grammar.epilogue index ffa93bf..9b2fa29 100644 --- a/dimension/grammar.epilogue +++ b/dimension/grammar.epilogue @@ -117,6 +117,7 @@ dmnsn_astnode_string(dmnsn_astnode_type astnode_type) dmnsn_astnode_map(DMNSN_AST_NONE, "none"); dmnsn_astnode_map(DMNSN_AST_GLOBAL_SETTINGS, "global_settings"); + dmnsn_astnode_map(DMNSN_AST_ADC_BAILOUT, "adc_bailout"); dmnsn_astnode_map(DMNSN_AST_ASSUMED_GAMMA, "assumed_gamma"); dmnsn_astnode_map(DMNSN_AST_CHARSET, "charset"); dmnsn_astnode_map(DMNSN_AST_ASCII, "ascii"); diff --git a/dimension/grammar.rules b/dimension/grammar.rules index 5f08e20..148e082 100644 --- a/dimension/grammar.rules +++ b/dimension/grammar.rules @@ -55,7 +55,10 @@ GLOBAL_SETTINGS_ITEMS: /* empty */ { } ; -GLOBAL_SETTINGS_ITEM: "ambient_light" COLOR { +GLOBAL_SETTINGS_ITEM: "adc_bailout" FLOAT { + $$ = dmnsn_new_astnode1(DMNSN_AST_ADC_BAILOUT, @$, $2); + } + | "ambient_light" COLOR { $$ = dmnsn_new_astnode1(DMNSN_AST_AMBIENT, @$, $2); } | "assumed_gamma" FLOAT { diff --git a/dimension/lexer.l b/dimension/lexer.l index dbafec2..89cc0a7 100644 --- a/dimension/lexer.l +++ b/dimension/lexer.l @@ -168,6 +168,7 @@ unsigned int wchar; "abs" RETURN_TOKEN(DMNSN_T_ABS); "acos" RETURN_TOKEN(DMNSN_T_ACOS); "acosh" RETURN_TOKEN(DMNSN_T_ACOSH); +"adc_bailout" RETURN_TOKEN(DMNSN_T_ADC_BAILOUT); "ambient" RETURN_TOKEN(DMNSN_T_AMBIENT); "ambient_light" RETURN_TOKEN(DMNSN_T_AMBIENT_LIGHT); "angle" RETURN_TOKEN(DMNSN_T_ANGLE); diff --git a/dimension/parse.h b/dimension/parse.h index 4471edf..a357324 100644 --- a/dimension/parse.h +++ b/dimension/parse.h @@ -31,6 +31,7 @@ typedef enum { DMNSN_AST_NONE, DMNSN_AST_GLOBAL_SETTINGS, + DMNSN_AST_ADC_BAILOUT, DMNSN_AST_ASSUMED_GAMMA, DMNSN_AST_CHARSET, DMNSN_AST_ASCII, diff --git a/dimension/realize.c b/dimension/realize.c index 2603ba1..c9a507d 100644 --- a/dimension/realize.c +++ b/dimension/realize.c @@ -232,6 +232,11 @@ dmnsn_realize_global_settings(dmnsn_astnode astnode, dmnsn_scene *scene) dmnsn_astnode child; switch (item->type) { + case DMNSN_AST_ADC_BAILOUT: + dmnsn_array_get(item->children, 0, &child); + scene->adc_bailout = dmnsn_realize_float(child); + break; + case DMNSN_AST_AMBIENT: dmnsn_array_get(item->children, 0, &child); scene->ambient = dmnsn_realize_color(child); diff --git a/libdimension/dimension/scene.h b/libdimension/dimension/scene.h index 747c764..7b44231 100644 --- a/libdimension/dimension/scene.h +++ b/libdimension/dimension/scene.h @@ -66,6 +66,9 @@ typedef struct dmnsn_scene { /** Recursion limit. */ unsigned int reclimit; + /** Adaptive depth control bailout. */ + double adc_bailout; + /** Number of parallel threads. */ unsigned int nthreads; diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c index a35b1e6..f5c68e6 100644 --- a/libdimension/raytrace.c +++ b/libdimension/raytrace.c @@ -109,7 +109,7 @@ typedef struct dmnsn_raytrace_state { const dmnsn_scene *scene; const dmnsn_intersection *intersection; - dmnsn_prtree *prtree; + const dmnsn_prtree *prtree; unsigned int reclevel; dmnsn_vector r; @@ -121,6 +121,8 @@ typedef struct dmnsn_raytrace_state { dmnsn_color additional; double ior; + + dmnsn_color adc_value; } dmnsn_raytrace_state; /** Main helper for dmnsn_raytrace_scene_impl - shoot a ray. */ @@ -156,6 +158,7 @@ dmnsn_raytrace_scene_concurrent(void *ptr, unsigned int thread, /* Shoot a ray */ state.reclevel = scene->reclimit; state.ior = 1.0; + state.adc_value = dmnsn_white; dmnsn_color color = dmnsn_raytrace_shoot(&state, ray); dmnsn_set_pixel(scene->canvas, x, y, color); @@ -253,7 +256,9 @@ dmnsn_raytrace_light_ray(const dmnsn_raytrace_state *state, dmnsn_color color = light->light_fn(light, state->r); unsigned int reclevel = state->reclevel; - while (reclevel > 0) { + while (reclevel > 0 + && dmnsn_color_intensity(color) >= state->scene->adc_bailout) + { dmnsn_intersection shadow_caster; bool shadow_casted = dmnsn_prtree_intersection(state->prtree, shadow_ray, &shadow_caster, false); @@ -268,7 +273,8 @@ 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)) { + && (shadow_state.pigment.filter || shadow_state.pigment.trans)) + { 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); @@ -339,6 +345,11 @@ dmnsn_raytrace_reflection(const dmnsn_raytrace_state *state) refl_ray = dmnsn_line_add_epsilon(refl_ray); dmnsn_raytrace_state recursive_state = *state; + recursive_state.adc_value = TEXTURE_CALLBACK( + state, finish, reflection_fn, dmnsn_black, + state->adc_value, state->pigment, state->reflected, + state->intersection->normal + ); dmnsn_color rec = dmnsn_raytrace_shoot(&recursive_state, refl_ray); reflected = TEXTURE_CALLBACK( state, finish, reflection_fn, dmnsn_black, @@ -396,6 +407,9 @@ dmnsn_raytrace_translucency(dmnsn_raytrace_state *state) ); } + recursive_state.adc_value + = dmnsn_filter_light(state->adc_value, state->pigment); + dmnsn_color rec = dmnsn_raytrace_shoot(&recursive_state, trans_ray); dmnsn_color filtered = dmnsn_filter_light(rec, state->pigment); state->diffuse.filter = state->pigment.filter; @@ -408,8 +422,12 @@ 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 + || dmnsn_color_intensity(state->adc_value) < state->scene->adc_bailout) + { return dmnsn_black; + } + --state->reclevel; /* Calculate the background color */ diff --git a/libdimension/scene.c b/libdimension/scene.c index 95c8f32..fadd077 100644 --- a/libdimension/scene.c +++ b/libdimension/scene.c @@ -42,6 +42,7 @@ dmnsn_new_scene(void) scene->lights = dmnsn_new_array(sizeof(dmnsn_light *)); scene->quality = DMNSN_RENDER_FULL; scene->reclimit = 5; + scene->adc_bailout = 1.0/255.0; scene->nthreads = dmnsn_ncpus(); scene->bounding_timer = NULL; scene->render_timer = NULL; diff --git a/tests/dimension/demo.pov b/tests/dimension/demo.pov index 390c4c6..91be9d2 100644 --- a/tests/dimension/demo.pov +++ b/tests/dimension/demo.pov @@ -19,6 +19,11 @@ // Render demo scene +global_settings { + max_trace_level 5 + adc_bailout 1/255 +} + camera { perspective location <0, 0.25, -4> diff --git a/tests/dimension/demo.sh b/tests/dimension/demo.sh index 10cf13b..233b880 100755 --- a/tests/dimension/demo.sh +++ b/tests/dimension/demo.sh @@ -21,7 +21,10 @@ demo=$(${top_builddir}/dimension/dimension ${dimension_flags} -w768 -h480 --parse ${srcdir}/demo.pov) demo_exp=$(echo -n \ -'((camera +'((global_settings + (max_trace_level (integer 5)) + (adc_bailout (float 0.00392157))) + (camera perspective (location (vector (integer 0) (float 0.25) (integer -4) (integer 0) (integer 0))) |