[Bf-committers] [Bf-blender-cvs] [2b39214] master: Cycles Volume Render: add support for overlapping volume objects.

Daniel Salazar - patazstudio.com zanqdo at gmail.com
Sat Dec 28 22:31:06 CET 2013


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
<noreply at 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-cvs at blender.org
> http://lists.blender.org/mailman/listinfo/bf-blender-cvs
>


More information about the Bf-committers mailing list