[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