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

View File

@@ -16,11 +16,18 @@
CCL_NAMESPACE_BEGIN 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 */ /* 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, ccl_device_noinline void kernel_branched_path_surface_connect_light(
ShaderData *sd, ShaderData *emission_sd, PathState *state, float3 throughput, KernelGlobals *kg,
float num_samples_adjust, PathRadiance *L, int sample_all_lights) 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__ #ifdef __EMISSION__
/* sample illumination from lights to find path contribution */ /* 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 */ /* 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, ccl_device bool kernel_branched_path_surface_bounce(
ShaderData *sd, const ShaderClosure *sc, int sample, int num_samples, KernelGlobals *kg,
float3 *throughput, PathState *state, PathRadiance *L, Ray *ray) 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 */ /* sample BSDF */
float bsdf_pdf; float bsdf_pdf;

View File

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

View File

@@ -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); 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); 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; 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); 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); 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; 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) { 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); 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; 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 /* path is splitting into a branch, adjust so that each branch
* still gets a unique sample from the same sequence */ * still gets a unique sample from the same sequence */

View File

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

View File

@@ -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; 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)) { 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); kernel_write_light_passes(kg, buffer, L, sample);
#ifdef __KERNEL_DEBUG__ #ifdef __KERNEL_DEBUG__
kernel_write_debug_passes(kg, buffer, state, debug_data, sample); kernel_write_debug_passes(kg, buffer, state, debug_data, sample);

View File

@@ -79,16 +79,32 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
/* direct lighting */ /* direct lighting */
#ifdef __EMISSION__ #ifdef __EMISSION__
if((kernel_data.integrator.use_direct_light && RNG rng = kernel_split_state.rng[ray_index];
(sd->flag & SD_BSDF_HAS_EVAL))) 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. */ /* 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_t = path_state_rng_1D(kg, &rng, state, PRNG_LIGHT);
float light_u, light_v; float light_u, light_v;
path_state_rng_2D(kg, &rng, state, PRNG_LIGHT_U, &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); float terminate = path_state_rng_light_termination(kg, &rng, state);
kernel_split_state.rng[ray_index] = rng;
LightSample ls; LightSample ls;
if(light_sample(kg, if(light_sample(kg,
@@ -99,9 +115,9 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
&ls)) { &ls)) {
Ray light_ray; Ray light_ray;
#ifdef __OBJECT_MOTION__ # ifdef __OBJECT_MOTION__
light_ray.time = sd->time; light_ray.time = sd->time;
#endif # endif
BsdfEval L_light; BsdfEval L_light;
bool is_lamp; bool is_lamp;
@@ -118,6 +134,7 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
} }
} }
} }
kernel_split_state.rng[ray_index] = rng;
#endif /* __EMISSION__ */ #endif /* __EMISSION__ */
} }

View File

@@ -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; 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 */ /* holdout */
#ifdef __HOLDOUT__ #ifdef __HOLDOUT__
if(((sd->flag & SD_HOLDOUT) || if(((sd->flag & SD_HOLDOUT) ||

View File

@@ -117,6 +117,9 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
shadow, shadow,
state->bounce); 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); 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; float3 shadow = kernel_split_state.light_ray[ray_index].P;
// TODO(mai): investigate correctness here // TODO(mai): investigate correctness here
char update_path_radiance = (char)kernel_split_state.light_ray[ray_index].t; 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) { if(update_path_radiance) {
BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index];
path_radiance_accum_light(L, path_radiance_accum_light(L,
_throughput, _throughput,
&L_light, &L_light,
@@ -134,6 +137,9 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
state->bounce, state->bounce,
kernel_split_state.is_lamp[ray_index]); 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); REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL);
} }
} }