diff options
Diffstat (limited to 'intern/cycles/kernel')
-rw-r--r-- | intern/cycles/kernel/kernel_bake.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path_state.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_volume.h | 93 |
5 files changed, 93 insertions, 12 deletions
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index 822ad14039b..a1ec080e3d3 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -33,7 +33,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian path_radiance_init(&L_sample, kernel_data.film.use_light_pass); /* init path state */ - path_state_init(kg, &state, &rng, sample); + path_state_init(kg, &state, &rng, sample, NULL); /* evaluate surface shader */ float rbsdf = path_state_rng_1D(kg, &rng, &state, PRNG_BSDF); diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 0515489f77f..94440fc31a7 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -469,7 +469,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, path_radiance_init(&L, kernel_data.film.use_light_pass); PathState state; - path_state_init(kg, &state, rng, sample); + path_state_init(kg, &state, rng, sample, &ray); /* path iteration */ for(;;) { @@ -858,7 +858,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in path_radiance_init(&L, kernel_data.film.use_light_pass); PathState state; - path_state_init(kg, &state, rng, sample); + path_state_init(kg, &state, rng, sample, &ray); for(;;) { /* intersect scene */ diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index 43e75885849..f29168642a4 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -16,7 +16,7 @@ CCL_NAMESPACE_BEGIN -ccl_device_inline void path_state_init(KernelGlobals *kg, PathState *state, RNG *rng, int sample) +ccl_device_inline void path_state_init(KernelGlobals *kg, PathState *state, RNG *rng, int sample, Ray *ray) { state->flag = PATH_RAY_CAMERA|PATH_RAY_MIS_SKIP; @@ -41,7 +41,7 @@ ccl_device_inline void path_state_init(KernelGlobals *kg, PathState *state, RNG if(kernel_data.integrator.use_volumes) { /* initialize volume stack with volume we are inside of */ - kernel_volume_stack_init(kg, state->volume_stack); + kernel_volume_stack_init(kg, ray, state->volume_stack); /* seed RNG for cases where we can't use stratified samples */ state->rng_congruential = lcg_init(*rng + sample*0x51633e2d); } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 1f61d80b947..3e9e260794d 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -784,7 +784,7 @@ typedef struct KernelCamera { /* anamorphic lens bokeh */ float inv_aperture_ratio; - int pad1; + int is_inside_volume; int pad2; /* more matrices */ diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index ea02ede10cd..1273869ca28 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -954,17 +954,99 @@ ccl_device bool kernel_volume_use_decoupled(KernelGlobals *kg, bool heterogeneou * This is an array of object/shared ID's that the current segment of the path * is inside of. */ -ccl_device void kernel_volume_stack_init(KernelGlobals *kg, VolumeStack *stack) +ccl_device void kernel_volume_stack_init(KernelGlobals *kg, + Ray *ray, + VolumeStack *stack) { - /* todo: this assumes camera is always in air, need to detect when it isn't */ - if(kernel_data.background.volume_shader == SHADER_NONE) { - stack[0].shader = SHADER_NONE; + /* NULL ray happens in the baker, does it need proper initializetion of + * camera in volume? + */ + if(!kernel_data.cam.is_inside_volume || ray == NULL) { + /* Camera is guaranteed to be in the air, only take background volume + * into account in this case. + */ + if(kernel_data.background.volume_shader != SHADER_NONE) { + stack[0].shader = kernel_data.background.volume_shader; + stack[0].object = PRIM_NONE; + stack[1].shader = SHADER_NONE; + } + else { + stack[0].shader = SHADER_NONE; + } + return; } - else { + + const float3 Pend = ray->P + ray->D*ray->t; + Ray volume_ray = *ray; + int stack_index = 0, enclosed_index = 0; + int enclosed_volumes[VOLUME_STACK_SIZE]; + + while(stack_index < VOLUME_STACK_SIZE - 1 && + enclosed_index < VOLUME_STACK_SIZE - 1) + { + Intersection isect; + bool hit = scene_intersect(kg, &volume_ray, PATH_RAY_ALL_VISIBILITY, + &isect, + NULL, 0.0f, 0.0f); + if(!hit) { + break; + } + + ShaderData sd; + shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0); + if(sd.flag & SD_HAS_VOLUME) { + if(sd.flag & SD_BACKFACING) { + /* If ray exited the volume and never entered to that volume + * it means that camera is inside such a volume. + */ + bool is_enclosed = false; + for(int i = 0; i < enclosed_index; ++i) { + if(enclosed_volumes[i] == sd.object) { + is_enclosed = true; + break; + } + } + if(is_enclosed == false) { + stack[stack_index].object = sd.object; + stack[stack_index].shader = sd.shader; + ++stack_index; + } + } + else { + /* If ray from camera enters the volume, this volume shouldn't + * be added to the stak on exit. + */ + enclosed_volumes[enclosed_index++] = sd.object; + } + } + + /* Move ray forward. */ + volume_ray.P = ray_offset(sd.P, -sd.Ng); + if(volume_ray.t != FLT_MAX) { + volume_ray.D = normalize_len(Pend - volume_ray.P, &volume_ray.t); + /* TODO(sergey): Find a faster way detecting that ray_offset moved + * us pass through the end point. + */ + if(dot(ray->D, volume_ray.D) < 0.0f) { + break; + } + } + } + /* stack_index of 0 means quick checks outside of the kernel gave false + * positive, nothing to worry about, just we've wasted quite a few of + * ticks just to come into conclusion that camera is in the air. + * + * In this case we're doing the same above -- check whether background has + * volume. + */ + if(stack_index == 0 && kernel_data.background.volume_shader == SHADER_NONE) { stack[0].shader = kernel_data.background.volume_shader; stack[0].object = PRIM_NONE; stack[1].shader = SHADER_NONE; } + else { + stack[stack_index].shader = SHADER_NONE; + } } ccl_device void kernel_volume_stack_enter_exit(KernelGlobals *kg, ShaderData *sd, VolumeStack *stack) @@ -1013,4 +1095,3 @@ ccl_device void kernel_volume_stack_enter_exit(KernelGlobals *kg, ShaderData *sd } CCL_NAMESPACE_END - |