Maybe this can be seen as a boolean operation (boolean volume node?) in which we can decide if two volumes add, subtract or merge densities
Daniel Salazar patazstudio.com On Sat, Dec 28, 2013 at 1:13 PM, Brecht Van Lommel <nore...@git.blender.org>wrote: > Commit: 2b39214c4d8811b06545b83c4e42a7578266e2b1 > Author: Brecht Van Lommel > Date: Sat Dec 28 20:02:40 2013 +0100 > https://developer.blender.org/rB2b39214c4d8811b06545b83c4e42a7578266e2b1 > > Cycles Volume Render: add support for overlapping volume objects. > > This works pretty much as you would expect, overlapping volume objects > gives > a more dense volume. What did change is that world volume shaders are now > active everywhere, they are no longer excluded inside objects. > > This may not be desirable and we need to think of better control over this. > In some cases you clearly want it to happen, for example if you are > rendering > a fire in a foggy environment. In other cases like the inside of a house > you > may not want any fog, but it doesn't seem possible in general for the > renderer > to automatically determine what is inside or outside of the house. > > This is implemented using a simple fixed size array of shader/object ID > pairs, > limited to max 15 overlapping objects. The closures from all shaders are > put > into a single closure array, exactly the same as if an add shader was used > to > combine them. > > =================================================================== > > M intern/cycles/kernel/kernel_path.h > M intern/cycles/kernel/kernel_path_state.h > M intern/cycles/kernel/kernel_shader.h > M intern/cycles/kernel/kernel_shadow.h > M intern/cycles/kernel/kernel_types.h > M intern/cycles/kernel/kernel_volume.h > M intern/cycles/kernel/osl/osl_shader.cpp > M intern/cycles/kernel/osl/osl_shader.h > M intern/cycles/kernel/svm/svm.h > > =================================================================== > > diff --git a/intern/cycles/kernel/kernel_path.h > b/intern/cycles/kernel/kernel_path.h > index d318a85..b703970 100644 > --- a/intern/cycles/kernel/kernel_path.h > +++ b/intern/cycles/kernel/kernel_path.h > @@ -34,7 +34,6 @@ > #include "kernel_light.h" > #include "kernel_emission.h" > #include "kernel_passes.h" > -#include "kernel_path_state.h" > > #ifdef __SUBSURFACE__ > #include "kernel_subsurface.h" > @@ -44,6 +43,7 @@ > #include "kernel_volume.h" > #endif > > +#include "kernel_path_state.h" > #include "kernel_shadow.h" > > CCL_NAMESPACE_BEGIN > @@ -93,10 +93,10 @@ ccl_device void kernel_path_indirect(KernelGlobals > *kg, RNG *rng, int sample, Ra > > #ifdef __VOLUME__ > /* volume attenuation */ > - if(state.volume_shader != SHADER_NO_ID) { > + if(state.volume_stack[0].shader != SHADER_NO_ID) { > Ray segment_ray = ray; > segment_ray.t = (hit)? isect.t: FLT_MAX; > - throughput *= > kernel_volume_get_shadow_attenuation(kg, &state, &segment_ray, > state.volume_shader); > + throughput *= > kernel_volume_get_shadow_attenuation(kg, &state, &segment_ray); > } > #endif > > @@ -116,7 +116,7 @@ ccl_device void kernel_path_indirect(KernelGlobals > *kg, RNG *rng, int sample, Ra > float rbsdf = path_rng_1D(kg, rng, sample, > num_total_samples, rng_offset + PRNG_BSDF); > shader_eval_surface(kg, &sd, rbsdf, state.flag, > SHADER_CONTEXT_INDIRECT); > #ifdef __BRANCHED_PATH__ > - shader_merge_closures(kg, &sd); > + shader_merge_closures(&sd); > #endif > > /* blurring of bsdf after bounces, for rays that have a > small likelihood > @@ -291,7 +291,7 @@ ccl_device void kernel_path_indirect(KernelGlobals > *kg, RNG *rng, int sample, Ra > #ifdef __VOLUME__ > /* enter/exit volume */ > if(label & LABEL_TRANSMIT) > - kernel_volume_enter_exit(kg, &sd, > &state.volume_shader); > + kernel_volume_stack_enter_exit(kg, &sd, > state.volume_stack); > #endif > } > #ifdef __VOLUME__ > @@ -308,7 +308,7 @@ ccl_device void kernel_path_indirect(KernelGlobals > *kg, RNG *rng, int sample, Ra > #endif > > /* enter/exit volume */ > - kernel_volume_enter_exit(kg, &sd, > &state.volume_shader); > + kernel_volume_stack_enter_exit(kg, &sd, > state.volume_stack); > } > #endif > else { > @@ -411,7 +411,7 @@ ccl_device_inline bool > kernel_path_integrate_lighting(KernelGlobals *kg, RNG *rn > #ifdef __VOLUME__ > /* enter/exit volume */ > if(label & LABEL_TRANSMIT) > - kernel_volume_enter_exit(kg, sd, > &state->volume_shader); > + kernel_volume_stack_enter_exit(kg, sd, > state->volume_stack); > #endif > return true; > } > @@ -429,7 +429,7 @@ ccl_device_inline bool > kernel_path_integrate_lighting(KernelGlobals *kg, RNG *rn > #endif > > /* enter/exit volume */ > - kernel_volume_enter_exit(kg, sd, &state->volume_shader); > + kernel_volume_stack_enter_exit(kg, sd, > state->volume_stack); > return true; > } > #endif > @@ -515,10 +515,10 @@ ccl_device float4 > kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, > > #ifdef __VOLUME__ > /* volume attenuation */ > - if(state.volume_shader != SHADER_NO_ID) { > + if(state.volume_stack[0].shader != SHADER_NO_ID) { > Ray segment_ray = ray; > segment_ray.t = (hit)? isect.t: FLT_MAX; > - throughput *= > kernel_volume_get_shadow_attenuation(kg, &state, &segment_ray, > state.volume_shader); > + throughput *= > kernel_volume_get_shadow_attenuation(kg, &state, &segment_ray); > } > #endif > > @@ -769,7 +769,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals > *kg, RNG *rng, int sample, > #ifdef __VOLUME__ > /* enter/exit volume */ > if(label & LABEL_TRANSMIT) > - kernel_volume_enter_exit(kg, &sd, > &state.volume_shader); > + kernel_volume_stack_enter_exit(kg, &sd, > state.volume_stack); > #endif > > } > @@ -787,7 +787,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals > *kg, RNG *rng, int sample, > #endif > > /* enter/exit volume */ > - kernel_volume_enter_exit(kg, &sd, > &state.volume_shader); > + kernel_volume_stack_enter_exit(kg, &sd, > state.volume_stack); > } > #endif > else { > @@ -957,7 +957,7 @@ ccl_device_noinline void > kernel_branched_path_integrate_lighting(KernelGlobals * > #ifdef __VOLUME__ > /* enter/exit volume */ > if(label & LABEL_TRANSMIT) > - kernel_volume_enter_exit(kg, sd, > &ps.volume_shader); > + kernel_volume_stack_enter_exit(kg, sd, > ps.volume_stack); > #endif > > kernel_path_indirect(kg, rng, sample*num_samples + > j, bsdf_ray, buffer, > @@ -1019,10 +1019,10 @@ ccl_device float4 > kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in > > #ifdef __VOLUME__ > /* volume attenuation */ > - if(state.volume_shader != SHADER_NO_ID) { > + if(state.volume_stack[0].shader != SHADER_NO_ID) { > Ray segment_ray = ray; > segment_ray.t = (hit)? isect.t: FLT_MAX; > - throughput *= > kernel_volume_get_shadow_attenuation(kg, &state, &segment_ray, > state.volume_shader); > + throughput *= > kernel_volume_get_shadow_attenuation(kg, &state, &segment_ray); > } > #endif > > @@ -1050,7 +1050,7 @@ ccl_device float4 > kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in > ShaderData sd; > shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce); > shader_eval_surface(kg, &sd, 0.0f, state.flag, > SHADER_CONTEXT_MAIN); > - shader_merge_closures(kg, &sd); > + shader_merge_closures(&sd); > > /* holdout */ > #ifdef __HOLDOUT__ > @@ -1198,7 +1198,7 @@ ccl_device float4 > kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in > > #ifdef __VOLUME__ > /* enter/exit volume */ > - kernel_volume_enter_exit(kg, &sd, &state.volume_shader); > + kernel_volume_stack_enter_exit(kg, &sd, > state.volume_stack); > #endif > } > > diff --git a/intern/cycles/kernel/kernel_path_state.h > b/intern/cycles/kernel/kernel_path_state.h > index 2df8f56..afca28f 100644 > --- a/intern/cycles/kernel/kernel_path_state.h > +++ b/intern/cycles/kernel/kernel_path_state.h > @@ -16,20 +16,6 @@ > > CCL_NAMESPACE_BEGIN > > -typedef struct PathState { > - int flag; > - int bounce; > - > - int diffuse_bounce; > - int glossy_bounce; > - int transmission_bounce; > - int transparent_bounce; > - > -#ifdef __VOLUME__ > - int volume_shader; > -#endif > -} PathState; > - > ccl_device_inline void path_state_init(KernelGlobals *kg, PathState > *state) > { > state->flag = PATH_RAY_CAMERA|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP; > @@ -40,8 +26,7 @@ ccl_device_inline void path_state_init(KernelGlobals > *kg, PathState *state) > state->transparent_bounce = 0; > > #ifdef __VOLUME__ > - /* todo: this assumes camera is always in air, need to detect when > it isn't */ > - state->volume_shader = kernel_data.background.volume_shader; > + kernel_volume_stack_init(kg, state->volume_stack); > #endif > } > > diff --git a/intern/cycles/kernel/kernel_shader.h > b/intern/cycles/kernel/kernel_shader.h > index a2f4e0a..685143b 100644 > --- a/intern/cycles/kernel/kernel_shader.h > +++ b/intern/cycles/kernel/kernel_shader.h > @@ -459,6 +459,41 @@ ccl_device_inline void > shader_setup_from_volume(KernelGlobals *kg, ShaderData *s > sd->ray_dP = ray->dP; > } > > +/* Merging */ > + > +#if defined(__BRANCHED_PATH__) || defined(__VOLUME__) > +ccl_device void shader_merge_closures(ShaderData *sd) > +{ > + /* merge identical closures, better when we sample a single > closure at a time */ > + for(int i = 0; i < sd->num_closure; i++) { > + ShaderClosure *sci = &sd->closure[i]; > + > + for(int j = i + 1; j < sd->num_closure; j++) { > + ShaderClosure *scj = &sd->closure[j]; > + > +#ifdef __OSL__ > + if(!sci->prim && !scj->prim && sci->type == > scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1) { > +#else > + if(sci->type == scj->type && sci->data0 == > scj->data0 && sci->data1 == scj->data1) { > +#endif > + sci->weight += scj->weight; > + sci->sample_weight += scj->sample_weight; > + > + int size = sd->num_closure - (j+1); > + if(size > 0) { > + for(int k = 0; k < size; k++) { > + scj[k] = scj[k+1]; > + } > + } > + > + sd->num_closure--; > + j--; > + } > + } > + } > +} > +#endif > + > /* BSDF */ > > #ifdef __MULTI_CLOSURE__ > @@ -851,9 +886,16 @@ ccl_device float3 shader_holdout_eval(KernelGlobals > *kg, ShaderData *sd) > ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, > float randb, int path_flag, ShaderContext ctx) > { > +#ifdef __MULTI_CLOSURE__ > + sd->num_closure = 0; > + sd->randb_closure = randb; > +#else > + sd->closure.type = NBUILTIN_CLOSURES; > +#endif > + > #ifdef __OSL__ > - if (kg->osl) > - OSLShader::eval_surface(kg, sd, randb, path_flag, ctx); > + if(kg->osl) > + OSLShader::eval_surface(kg, sd, path_flag, ctx); > else > #endif > { > @@ -871,9 +913,17 @@ ccl_device void shader_eval_surface(KernelGlobals > *kg, ShaderData *sd, > > ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData > *sd, int path_flag, ShaderContext ctx) > { > +#ifdef __MULTI_CLOSURE__ > + sd->num_closure = 0; > + sd->randb_closure = 0.0f; > +#else > + sd->closure.type = NBUILTIN_CLOSURES; > +#endif > + > #ifdef __OSL__ > - if (kg->osl) > + if(kg->osl) { > return OSLShader::eval_background(kg, sd, path_flag, ctx); > + } > else > #endif > > @@ -907,6 +957,7 @@ ccl_device float3 shader_eval_background(KernelGlobals > *kg, ShaderData *sd, int > > /* Volume */ > > +#ifdef __VOLUME__ > ccl_device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData > *sd, > float3 omega_in, float3 omega_out) > { > @@ -931,30 +982,77 @@ ccl_device float3 > shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd, > /* Volume Evaluation */ > > ccl_device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd, > - float randb, int path_flag, ShaderContext ctx) > + VolumeStack *stack, float randb, int path_flag, ShaderContext ctx) > { > + /* reset closures once at the start, we will be accumulating the > closures > + * for all volumes in the stack into a single array of closures */ > +#ifdef __MULTI_CLOSURE__ > + sd->num_closure = 0; > + sd->randb_closure = randb; > +#else > + sd->closure.type = NBUILTIN_CLOSURES; > +#endif > + > + for(int i = 0; stack[i].shader != SHADER_NO_ID; i++) { > + /* setup shaderdata from stack. it's mostly setup already > in > + * shader_setup_from_volume, this switching should be > quick */ > + sd->object = stack[i].object; > + sd->shader = stack[i].shader; > + > + sd->flag &= ~(SD_SHADER_FLAGS|SD_OBJECT_FLAGS); > + sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & > SHADER_MASK)*2); > + > + if(sd->object != ~0) { > + sd->flag |= kernel_tex_fetch(__object_flag, > sd->object); > + > +#ifdef __OBJECT_MOTION__ > + /* todo: this is inefficient for motion blur, we > should be > + * caching matrices instead of recomputing them > each step */ > + shader_setup_object_transforms(k > > @@ Diff output truncated at 10240 characters. @@ > > _______________________________________________ > Bf-blender-cvs mailing list > bf-blender-...@blender.org > http://lists.blender.org/mailman/listinfo/bf-blender-cvs > _______________________________________________ Bf-committers mailing list Bf-committers@blender.org http://lists.blender.org/mailman/listinfo/bf-committers