diff options
author | Brecht Van Lommel <brecht> | 2020-03-07 16:38:52 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2020-03-18 13:23:05 +0300 |
commit | 1162ba206dd7792414d3ae716877ba1383de8dab (patch) | |
tree | 3b243a7c33dfbbc6414e96a4df6b37ddc47531cd /intern/cycles/kernel | |
parent | 9d20f170c7c07ac38e86130de591ae98e9c0cf80 (diff) |
Cycles: change volume step size controls, auto adjust based on voxel size
By default it will now set the step size to the voxel size for smoke and
volume objects, and 1/10th the bounding box for procedural volume shaders.
New settings are:
* Scene render/preview step rate: to globally adjust detail and performance
* Material step rate: multiplied with auto detected per-object step size
* World step size: distance to steo for world shader
Differential Revision: https://developer.blender.org/D1777
Diffstat (limited to 'intern/cycles/kernel')
-rw-r--r-- | intern/cycles/kernel/geom/geom_object.h | 11 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path.h | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path_branched.h | 6 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_textures.h | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 10 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_volume.h | 51 | ||||
-rw-r--r-- | intern/cycles/kernel/split/kernel_do_volume.h | 8 |
7 files changed, 61 insertions, 34 deletions
diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index ac2ddf575ca..c6d02ed9702 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -320,6 +320,17 @@ ccl_device_inline uint object_patch_map_offset(KernelGlobals *kg, int object) return kernel_tex_fetch(__objects, object).patch_map_offset; } +/* Volume step size */ + +ccl_device_inline float object_volume_step_size(KernelGlobals *kg, int object) +{ + if (object == OBJECT_NONE) { + return kernel_data.background.volume_step_size; + } + + return kernel_tex_fetch(__object_volume_step, object); +} + /* Pass ID for shader */ ccl_device int shader_pass_id(KernelGlobals *kg, const ShaderData *sd) diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 74377f2c069..db35303e3f1 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -171,19 +171,19 @@ ccl_device_forceinline VolumeIntegrateResult kernel_path_volume(KernelGlobals *k Ray volume_ray = *ray; volume_ray.t = (hit) ? isect->t : FLT_MAX; - bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack); + float step_size = volume_stack_step_size(kg, state->volume_stack); # ifdef __VOLUME_DECOUPLED__ int sampling_method = volume_stack_sampling_method(kg, state->volume_stack); bool direct = (state->flag & PATH_RAY_CAMERA) != 0; - bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, direct, sampling_method); + bool decoupled = kernel_volume_use_decoupled(kg, step_size, direct, sampling_method); if (decoupled) { /* cache steps along volume for repeated sampling */ VolumeSegment volume_segment; shader_setup_from_volume(kg, sd, &volume_ray); - kernel_volume_decoupled_record(kg, state, &volume_ray, sd, &volume_segment, heterogeneous); + kernel_volume_decoupled_record(kg, state, &volume_ray, sd, &volume_segment, step_size); volume_segment.sampling_method = sampling_method; @@ -229,7 +229,7 @@ ccl_device_forceinline VolumeIntegrateResult kernel_path_volume(KernelGlobals *k { /* integrate along volume segment with distance sampling */ VolumeIntegrateResult result = kernel_volume_integrate( - kg, state, sd, &volume_ray, L, throughput, heterogeneous); + kg, state, sd, &volume_ray, L, throughput, step_size); # ifdef __VOLUME_SCATTER__ if (result == VOLUME_PATH_SCATTERED) { diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h index 0d5781fe3d1..337c4fb1d10 100644 --- a/intern/cycles/kernel/kernel_path_branched.h +++ b/intern/cycles/kernel/kernel_path_branched.h @@ -91,7 +91,7 @@ ccl_device_forceinline void kernel_branched_path_volume(KernelGlobals *kg, Ray volume_ray = *ray; volume_ray.t = (hit) ? isect->t : FLT_MAX; - bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack); + float step_size = volume_stack_step_size(kg, state->volume_stack); # ifdef __VOLUME_DECOUPLED__ /* decoupled ray marching only supported on CPU */ @@ -100,7 +100,7 @@ ccl_device_forceinline void kernel_branched_path_volume(KernelGlobals *kg, VolumeSegment volume_segment; shader_setup_from_volume(kg, sd, &volume_ray); - kernel_volume_decoupled_record(kg, state, &volume_ray, sd, &volume_segment, heterogeneous); + kernel_volume_decoupled_record(kg, state, &volume_ray, sd, &volume_segment, step_size); /* direct light sampling */ if (volume_segment.closure_flag & SD_SCATTER) { @@ -171,7 +171,7 @@ ccl_device_forceinline void kernel_branched_path_volume(KernelGlobals *kg, path_state_branch(&ps, j, num_samples); VolumeIntegrateResult result = kernel_volume_integrate( - kg, &ps, sd, &volume_ray, L, &tp, heterogeneous); + kg, &ps, sd, &volume_ray, L, &tp, step_size); # ifdef __VOLUME_SCATTER__ if (result == VOLUME_PATH_SCATTERED) { diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 1cae34348c9..c8e01677d09 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -35,6 +35,7 @@ KERNEL_TEX(KernelObject, __objects) KERNEL_TEX(Transform, __object_motion_pass) KERNEL_TEX(DecomposedTransform, __object_motion) KERNEL_TEX(uint, __object_flag) +KERNEL_TEX(float, __object_volume_step) /* cameras */ KERNEL_TEX(DecomposedTransform, __camera_motion) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index c5be93e2cda..6a0e74efc91 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -887,13 +887,13 @@ enum ShaderDataFlag { SD_HAS_DISPLACEMENT = (1 << 26), /* Has constant emission (value stored in __shaders) */ SD_HAS_CONSTANT_EMISSION = (1 << 27), - /* Needs to access attributes */ - SD_NEED_ATTRIBUTES = (1 << 28), + /* Needs to access attributes for volume rendering */ + SD_NEED_VOLUME_ATTRIBUTES = (1 << 28), SD_SHADER_FLAGS = (SD_USE_MIS | SD_HAS_TRANSPARENT_SHADOW | SD_HAS_VOLUME | SD_HAS_ONLY_VOLUME | SD_HETEROGENEOUS_VOLUME | SD_HAS_BSSRDF_BUMP | SD_VOLUME_EQUIANGULAR | SD_VOLUME_MIS | SD_VOLUME_CUBIC | SD_HAS_BUMP | SD_HAS_DISPLACEMENT | - SD_HAS_CONSTANT_EMISSION | SD_NEED_ATTRIBUTES) + SD_HAS_CONSTANT_EMISSION | SD_NEED_VOLUME_ATTRIBUTES) }; /* Object flags. */ @@ -1275,6 +1275,7 @@ typedef struct KernelBackground { /* only shader index */ int surface_shader; int volume_shader; + float volume_step_size; int transparent; float transparent_roughness_squared_threshold; @@ -1282,7 +1283,6 @@ typedef struct KernelBackground { float ao_factor; float ao_distance; float ao_bounces_factor; - float ao_pad; } KernelBackground; static_assert_align(KernelBackground, 16); @@ -1355,7 +1355,7 @@ typedef struct KernelIntegrator { /* volume render */ int use_volumes; int volume_max_steps; - float volume_step_size; + float volume_step_rate; int volume_samples; int start_sample; diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index f443bb88463..035fcdbc8e1 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -101,15 +101,19 @@ ccl_device float kernel_volume_channel_get(float3 value, int channel) #ifdef __VOLUME__ -ccl_device bool volume_stack_is_heterogeneous(KernelGlobals *kg, ccl_addr_space VolumeStack *stack) +ccl_device float volume_stack_step_size(KernelGlobals *kg, ccl_addr_space VolumeStack *stack) { + float step_size = FLT_MAX; + for (int i = 0; stack[i].shader != SHADER_NONE; i++) { int shader_flag = kernel_tex_fetch(__shaders, (stack[i].shader & SHADER_MASK)).flags; + bool heterogeneous = false; + if (shader_flag & SD_HETEROGENEOUS_VOLUME) { - return true; + heterogeneous = true; } - else if (shader_flag & SD_NEED_ATTRIBUTES) { + else if (shader_flag & SD_NEED_VOLUME_ATTRIBUTES) { /* We want to render world or objects without any volume grids * as homogeneous, but can only verify this at run-time since other * heterogeneous volume objects may be using the same shader. */ @@ -117,13 +121,19 @@ ccl_device bool volume_stack_is_heterogeneous(KernelGlobals *kg, ccl_addr_space if (object != OBJECT_NONE) { int object_flag = kernel_tex_fetch(__object_flag, object); if (object_flag & SD_OBJECT_HAS_VOLUME_ATTRIBUTES) { - return true; + heterogeneous = true; } } } + + if (heterogeneous) { + float object_step_size = object_volume_step_size(kg, stack[i].object); + object_step_size *= kernel_data.integrator.volume_step_rate; + step_size = fminf(object_step_size, step_size); + } } - return false; + return step_size; } ccl_device int volume_stack_sampling_method(KernelGlobals *kg, VolumeStack *stack) @@ -158,12 +168,13 @@ ccl_device int volume_stack_sampling_method(KernelGlobals *kg, VolumeStack *stac ccl_device_inline void kernel_volume_step_init(KernelGlobals *kg, ccl_addr_space PathState *state, + const float object_step_size, float t, float *step_size, float *step_offset) { const int max_steps = kernel_data.integrator.volume_max_steps; - float step = min(kernel_data.integrator.volume_step_size, t); + float step = min(object_step_size, t); /* compute exact steps in advance for malloc */ if (t > max_steps * step) { @@ -199,7 +210,8 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, ccl_addr_space PathState *state, Ray *ray, ShaderData *sd, - float3 *throughput) + float3 *throughput, + const float object_step_size) { float3 tp = *throughput; const float tp_eps = 1e-6f; /* todo: this is likely not the right value */ @@ -207,7 +219,7 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, /* prepare for stepping */ int max_steps = kernel_data.integrator.volume_max_steps; float step_offset, step_size; - kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset); + kernel_volume_step_init(kg, state, object_step_size, ray->t, &step_size, &step_offset); /* compute extinction at the start */ float t = 0.0f; @@ -264,8 +276,9 @@ ccl_device_noinline void kernel_volume_shadow(KernelGlobals *kg, { shader_setup_from_volume(kg, shadow_sd, ray); - if (volume_stack_is_heterogeneous(kg, state->volume_stack)) - kernel_volume_shadow_heterogeneous(kg, state, ray, shadow_sd, throughput); + float step_size = volume_stack_step_size(kg, state->volume_stack); + if (step_size != FLT_MAX) + kernel_volume_shadow_heterogeneous(kg, state, ray, shadow_sd, throughput, step_size); else kernel_volume_shadow_homogeneous(kg, state, ray, shadow_sd, throughput); } @@ -533,7 +546,8 @@ kernel_volume_integrate_heterogeneous_distance(KernelGlobals *kg, Ray *ray, ShaderData *sd, PathRadiance *L, - ccl_addr_space float3 *throughput) + ccl_addr_space float3 *throughput, + const float object_step_size) { float3 tp = *throughput; const float tp_eps = 1e-6f; /* todo: this is likely not the right value */ @@ -541,7 +555,7 @@ kernel_volume_integrate_heterogeneous_distance(KernelGlobals *kg, /* prepare for stepping */ int max_steps = kernel_data.integrator.volume_max_steps; float step_offset, step_size; - kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset); + kernel_volume_step_init(kg, state, object_step_size, ray->t, &step_size, &step_offset); /* compute coefficients at the start */ float t = 0.0f; @@ -679,12 +693,13 @@ kernel_volume_integrate(KernelGlobals *kg, Ray *ray, PathRadiance *L, ccl_addr_space float3 *throughput, - bool heterogeneous) + float step_size) { shader_setup_from_volume(kg, sd, ray); - if (heterogeneous) - return kernel_volume_integrate_heterogeneous_distance(kg, state, ray, sd, L, throughput); + if (step_size != FLT_MAX) + return kernel_volume_integrate_heterogeneous_distance( + kg, state, ray, sd, L, throughput, step_size); else return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, true); } @@ -735,7 +750,7 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, Ray *ray, ShaderData *sd, VolumeSegment *segment, - bool heterogeneous) + const float object_step_size) { const float tp_eps = 1e-6f; /* todo: this is likely not the right value */ @@ -743,9 +758,9 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, int max_steps; float step_size, step_offset; - if (heterogeneous) { + if (object_step_size != FLT_MAX) { max_steps = kernel_data.integrator.volume_max_steps; - kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset); + kernel_volume_step_init(kg, state, object_step_size, ray->t, &step_size, &step_offset); # ifdef __KERNEL_CPU__ /* NOTE: For the branched path tracing it's possible to have direct diff --git a/intern/cycles/kernel/split/kernel_do_volume.h b/intern/cycles/kernel/split/kernel_do_volume.h index 45b839db05f..b24699ec39c 100644 --- a/intern/cycles/kernel/split/kernel_do_volume.h +++ b/intern/cycles/kernel/split/kernel_do_volume.h @@ -44,7 +44,7 @@ ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(K branched_state->isect.t : FLT_MAX; - bool heterogeneous = volume_stack_is_heterogeneous(kg, branched_state->path_state.volume_stack); + float step_size = volume_stack_step_size(kg, branched_state->path_state.volume_stack); for (int j = branched_state->next_sample; j < num_samples; j++) { ccl_global PathState *ps = &kernel_split_state.path_state[ray_index]; @@ -61,7 +61,7 @@ ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(K /* integrate along volume segment with distance sampling */ VolumeIntegrateResult result = kernel_volume_integrate( - kg, ps, sd, &volume_ray, L, tp, heterogeneous); + kg, ps, sd, &volume_ray, L, tp, step_size); # ifdef __VOLUME_SCATTER__ if (result == VOLUME_PATH_SCATTERED) { @@ -164,12 +164,12 @@ ccl_device void kernel_do_volume(KernelGlobals *kg) if (!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) { # endif /* __BRANCHED_PATH__ */ - bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack); + float step_size = volume_stack_step_size(kg, state->volume_stack); { /* integrate along volume segment with distance sampling */ VolumeIntegrateResult result = kernel_volume_integrate( - kg, state, sd, &volume_ray, L, throughput, heterogeneous); + kg, state, sd, &volume_ray, L, throughput, step_size); # ifdef __VOLUME_SCATTER__ if (result == VOLUME_PATH_SCATTERED) { |