Cycles: Add OpenCL support for shadow catcher feature

The title says it all actually.
This commit is contained in:
Hristo Gueorguiev 2017-03-21 12:27:12 +01:00 committed by Sergey Sharybin
parent 8ada7f7397
commit e07ffcbd1c
8 changed files with 99 additions and 30 deletions

@ -16,11 +16,18 @@
CCL_NAMESPACE_BEGIN
#if (defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__) || defined(__SHADOW_TRICKS__)) && !defined(__SPLIT_KERNEL__)
#if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__) || defined(__SHADOW_TRICKS__)
/* branched path tracing: connect path directly to position on one or more lights and add it to L */
ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RNG *rng,
ShaderData *sd, ShaderData *emission_sd, PathState *state, float3 throughput,
float num_samples_adjust, PathRadiance *L, int sample_all_lights)
ccl_device_noinline void kernel_branched_path_surface_connect_light(
KernelGlobals *kg,
RNG *rng,
ShaderData *sd,
ShaderData *emission_sd,
ccl_addr_space PathState *state,
float3 throughput,
float num_samples_adjust,
PathRadiance *L,
int sample_all_lights)
{
#ifdef __EMISSION__
/* sample illumination from lights to find path contribution */
@ -138,9 +145,17 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
}
/* branched path tracing: bounce off or through surface to with new direction stored in ray */
ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg, RNG *rng,
ShaderData *sd, const ShaderClosure *sc, int sample, int num_samples,
float3 *throughput, PathState *state, PathRadiance *L, Ray *ray)
ccl_device bool kernel_branched_path_surface_bounce(
KernelGlobals *kg,
RNG *rng,
ShaderData *sd,
const ShaderClosure *sc,
int sample,
int num_samples,
ccl_addr_space float3 *throughput,
ccl_addr_space PathState *state,
PathRadiance *L,
Ray *ray)
{
/* sample BSDF */
float bsdf_pdf;

@ -117,10 +117,18 @@ bool kernel_path_volume_bounce(
return true;
}
#ifdef __BRANCHED_PATH__
ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG *rng,
ShaderData *sd, ShaderData *emission_sd, float3 throughput, PathState *state, PathRadiance *L,
bool sample_all_lights, Ray *ray, const VolumeSegment *segment)
#ifndef __SPLIT_KERNEL__
ccl_device void kernel_branched_path_volume_connect_light(
KernelGlobals *kg,
RNG *rng,
ShaderData *sd,
ShaderData *emission_sd,
float3 throughput,
ccl_addr_space PathState *state,
PathRadiance *L,
bool sample_all_lights,
Ray *ray,
const VolumeSegment *segment)
{
#ifdef __EMISSION__
if(!kernel_data.integrator.use_direct_light)
@ -270,7 +278,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
}
#endif /* __EMISSION__ */
}
#endif /* __BRANCHED_PATH__ */
#endif /* __SPLIT_KERNEL__ */
#endif /* __VOLUME_SCATTER__ */

@ -282,18 +282,18 @@ ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, RNG *rng, const ccl_
path_rng_2D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension, fx, fy);
}
ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, RNG *rng, const PathState *state, int branch, int num_branches, int dimension)
ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension)
{
return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension);
}
ccl_device_inline float path_branched_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, const PathState *state, int branch, int num_branches, int dimension)
ccl_device_inline float path_branched_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension)
{
int rng_offset = state->rng_offset + state->transparent_bounce*PRNG_BOUNCE_NUM;
return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, rng_offset + dimension);
}
ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, RNG *rng, const PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy)
ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy)
{
path_rng_2D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension, fx, fy);
}
@ -307,7 +307,7 @@ ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, RNG
return 0.0f;
}
ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, RNG *rng, const PathState *state, int branch, int num_branches)
ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches)
{
if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
return path_branched_rng_1D_for_decision(kg, rng, state, branch, num_branches, PRNG_LIGHT_TERMINATE);
@ -315,7 +315,7 @@ ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, R
return 0.0f;
}
ccl_device_inline void path_state_branch(PathState *state, int branch, int num_branches)
ccl_device_inline void path_state_branch(ccl_addr_space PathState *state, int branch, int num_branches)
{
/* path is splitting into a branch, adjust so that each branch
* still gets a unique sample from the same sequence */

@ -157,10 +157,7 @@ CCL_NAMESPACE_BEGIN
#define __INTERSECTION_REFINE__
#define __CLAMP_SAMPLE__
#define __PATCH_EVAL__
#ifndef __SPLIT_KERNEL__
# define __SHADOW_TRICKS__
#endif
#define __SHADOW_TRICKS__
#ifdef __KERNEL_SHADING__
# define __SVM__

@ -111,7 +111,16 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride;
if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
float3 L_sum = path_radiance_clamp_and_sum(kg, L);
float3 L_sum;
#ifdef __SHADOW_TRICKS__
if(state->flag & PATH_RAY_SHADOW_CATCHER) {
L_sum = path_radiance_sum_shadowcatcher(kg, L, L_transparent);
}
else
#endif /* __SHADOW_TRICKS__ */
{
L_sum = path_radiance_clamp_and_sum(kg, L);
}
kernel_write_light_passes(kg, buffer, L, sample);
#ifdef __KERNEL_DEBUG__
kernel_write_debug_passes(kg, buffer, state, debug_data, sample);

@ -79,16 +79,32 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
/* direct lighting */
#ifdef __EMISSION__
if((kernel_data.integrator.use_direct_light &&
(sd->flag & SD_BSDF_HAS_EVAL)))
{
RNG rng = kernel_split_state.rng[ray_index];
bool flag = (kernel_data.integrator.use_direct_light &&
(sd->flag & SD_BSDF_HAS_EVAL));
# ifdef __SHADOW_TRICKS__
if(flag && state->flag & PATH_RAY_SHADOW_CATCHER) {
flag = false;
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
float3 throughput = kernel_split_state.throughput[ray_index];
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
kernel_branched_path_surface_connect_light(kg,
&rng,
sd,
emission_sd,
state,
throughput,
1.0f,
L,
1);
}
# endif /* __SHADOW_TRICKS__ */
if(flag) {
/* Sample illumination from lights to find path contribution. */
RNG rng = kernel_split_state.rng[ray_index];
float light_t = path_state_rng_1D(kg, &rng, state, PRNG_LIGHT);
float light_u, light_v;
path_state_rng_2D(kg, &rng, state, PRNG_LIGHT_U, &light_u, &light_v);
float terminate = path_state_rng_light_termination(kg, &rng, state);
kernel_split_state.rng[ray_index] = rng;
LightSample ls;
if(light_sample(kg,
@ -99,9 +115,9 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
&ls)) {
Ray light_ray;
#ifdef __OBJECT_MOTION__
# ifdef __OBJECT_MOTION__
light_ray.time = sd->time;
#endif
# endif
BsdfEval L_light;
bool is_lamp;
@ -118,6 +134,7 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
}
}
}
kernel_split_state.rng[ray_index] = rng;
#endif /* __EMISSION__ */
}

@ -120,6 +120,23 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
buffer += (kernel_split_params.offset + pixel_x + pixel_y * stride) * kernel_data.film.pass_stride;
#ifdef __SHADOW_TRICKS__
if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
if (state->flag & PATH_RAY_CAMERA) {
state->flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY);
state->catcher_object = sd->object;
if(!kernel_data.background.transparent) {
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
L->shadow_color = indirect_background(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, ray);
}
}
}
else {
state->flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
}
#endif /* __SHADOW_TRICKS__ */
/* holdout */
#ifdef __HOLDOUT__
if(((sd->flag & SD_HOLDOUT) ||

@ -117,6 +117,9 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
shadow,
state->bounce);
}
else {
path_radiance_accum_total_ao(L, _throughput, kernel_split_state.ao_bsdf[ray_index]);
}
REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO);
}
@ -124,8 +127,8 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
float3 shadow = kernel_split_state.light_ray[ray_index].P;
// TODO(mai): investigate correctness here
char update_path_radiance = (char)kernel_split_state.light_ray[ray_index].t;
BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index];
if(update_path_radiance) {
BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index];
path_radiance_accum_light(L,
_throughput,
&L_light,
@ -134,6 +137,9 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
state->bounce,
kernel_split_state.is_lamp[ray_index]);
}
else {
path_radiance_accum_total_light(L, _throughput, &L_light);
}
REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL);
}
}