summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dimension/common.terminals2
-rw-r--r--dimension/grammar.epilogue1
-rw-r--r--dimension/grammar.rules5
-rw-r--r--dimension/lexer.l1
-rw-r--r--dimension/parse.h1
-rw-r--r--dimension/realize.c5
-rw-r--r--libdimension/dimension/scene.h3
-rw-r--r--libdimension/raytrace.c26
-rw-r--r--libdimension/scene.c1
-rw-r--r--tests/dimension/demo.pov5
-rwxr-xr-xtests/dimension/demo.sh5
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)))