Cycles: add Transparent Depth output to Light Path node.

This can for example be useful if you want to manually terminate the path at
some point and use a color other than black.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D454
This commit is contained in:
Carlo Andreacchio 2014-04-21 14:20:29 +02:00 committed by Brecht Van Lommel
parent f8cd3d974d
commit 7765b73f6d
14 changed files with 66 additions and 37 deletions

@ -55,7 +55,7 @@ ccl_device void kernel_shader_evaluate(KernelGlobals *kg, ccl_global uint4 *inpu
#endif #endif
/* setup shader data */ /* setup shader data */
shader_setup_from_background(kg, &sd, &ray, 0); shader_setup_from_background(kg, &sd, &ray, 0, 0);
/* evaluate */ /* evaluate */
int flag = 0; /* we can't know which type of BSDF this is for */ int flag = 0; /* we can't know which type of BSDF this is for */

@ -19,7 +19,7 @@ CCL_NAMESPACE_BEGIN
/* Direction Emission */ /* Direction Emission */
ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando, ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando,
LightSample *ls, float3 I, differential3 dI, float t, float time, int bounce) LightSample *ls, float3 I, differential3 dI, float t, float time, int bounce, int transparent_bounce)
{ {
/* setup shading at emitter */ /* setup shading at emitter */
ShaderData sd; ShaderData sd;
@ -37,13 +37,13 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando,
ray.dP = differential3_zero(); ray.dP = differential3_zero();
ray.dD = dI; ray.dD = dI;
shader_setup_from_background(kg, &sd, &ray, bounce+1); shader_setup_from_background(kg, &sd, &ray, bounce+1, transparent_bounce);
eval = shader_eval_background(kg, &sd, 0, SHADER_CONTEXT_EMISSION); eval = shader_eval_background(kg, &sd, 0, SHADER_CONTEXT_EMISSION);
} }
else else
#endif #endif
{ {
shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time, bounce+1); shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time, bounce+1, transparent_bounce);
ls->Ng = sd.Ng; ls->Ng = sd.Ng;
@ -65,7 +65,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando,
ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex, ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
float randt, float rando, float randu, float randv, Ray *ray, BsdfEval *eval, float randt, float rando, float randu, float randv, Ray *ray, BsdfEval *eval,
bool *is_lamp, int bounce) bool *is_lamp, int bounce, int transparent_bounce)
{ {
LightSample ls; LightSample ls;
@ -88,7 +88,7 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, int
differential3 dD = differential3_zero(); differential3 dD = differential3_zero();
/* evaluate closure */ /* evaluate closure */
float3 light_eval = direct_emissive_eval(kg, rando, &ls, -ls.D, dD, ls.t, sd->time, bounce); float3 light_eval = direct_emissive_eval(kg, rando, &ls, -ls.D, dD, ls.t, sd->time, bounce, transparent_bounce);
if(is_zero(light_eval)) if(is_zero(light_eval))
return false; return false;
@ -183,7 +183,7 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, Shader
/* Indirect Lamp Emission */ /* Indirect Lamp Emission */
ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf, float randt, float3 *emission, int bounce) ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf, float randt, float3 *emission, int bounce, int transparent_bounce)
{ {
LightSample ls; LightSample ls;
int lamp = lamp_light_eval_sample(kg, randt); int lamp = lamp_light_eval_sample(kg, randt);
@ -204,7 +204,7 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int
} }
#endif #endif
float3 L = direct_emissive_eval(kg, 0.0f, &ls, -ray->D, ray->dD, ls.t, ray->time, bounce); float3 L = direct_emissive_eval(kg, 0.0f, &ls, -ray->D, ray->dD, ls.t, ray->time, bounce, transparent_bounce);
if(!(path_flag & PATH_RAY_MIS_SKIP)) { if(!(path_flag & PATH_RAY_MIS_SKIP)) {
/* multiple importance sampling, get regular light pdf, /* multiple importance sampling, get regular light pdf,
@ -219,7 +219,7 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int
/* Indirect Background */ /* Indirect Background */
ccl_device_noinline float3 indirect_background(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf, int bounce) ccl_device_noinline float3 indirect_background(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf, int bounce, int transparent_bounce)
{ {
#ifdef __BACKGROUND__ #ifdef __BACKGROUND__
int shader = kernel_data.background.surface_shader; int shader = kernel_data.background.surface_shader;
@ -235,7 +235,7 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg, Ray *ray, int
/* evaluate background closure */ /* evaluate background closure */
ShaderData sd; ShaderData sd;
shader_setup_from_background(kg, &sd, ray, bounce+1); shader_setup_from_background(kg, &sd, ray, bounce+1, transparent_bounce);
float3 L = shader_eval_background(kg, &sd, path_flag, SHADER_CONTEXT_EMISSION); float3 L = shader_eval_background(kg, &sd, path_flag, SHADER_CONTEXT_EMISSION);

@ -72,7 +72,7 @@ ccl_device_inline bool kernel_path_integrate_scatter_lighting(KernelGlobals *kg,
light_ray.time = sd->time; light_ray.time = sd->time;
#endif #endif
if(direct_emission(kg, sd, LAMP_NONE, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce)) { if(direct_emission(kg, sd, LAMP_NONE, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
/* trace shadow ray */ /* trace shadow ray */
float3 shadow; float3 shadow;
@ -157,7 +157,7 @@ ccl_device void kernel_branched_path_integrate_direct_lighting(KernelGlobals *kg
float light_u, light_v; float light_u, light_v;
path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v); path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
if(direct_emission(kg, sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce)) { if(direct_emission(kg, sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
/* trace shadow ray */ /* trace shadow ray */
float3 shadow; float3 shadow;
@ -186,7 +186,7 @@ ccl_device void kernel_branched_path_integrate_direct_lighting(KernelGlobals *kg
if(kernel_data.integrator.num_all_lights) if(kernel_data.integrator.num_all_lights)
light_t = 0.5f*light_t; light_t = 0.5f*light_t;
if(direct_emission(kg, sd, LAMP_NONE, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce)) { if(direct_emission(kg, sd, LAMP_NONE, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
/* trace shadow ray */ /* trace shadow ray */
float3 shadow; float3 shadow;
@ -204,7 +204,7 @@ ccl_device void kernel_branched_path_integrate_direct_lighting(KernelGlobals *kg
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);
/* sample random light */ /* sample random light */
if(direct_emission(kg, sd, LAMP_NONE, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce)) { if(direct_emission(kg, sd, LAMP_NONE, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
/* trace shadow ray */ /* trace shadow ray */
float3 shadow; float3 shadow;
@ -248,7 +248,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, ccl_g
float light_t = path_state_rng_1D(kg, rng, &state, PRNG_LIGHT); float light_t = path_state_rng_1D(kg, rng, &state, PRNG_LIGHT);
float3 emission; float3 emission;
if(indirect_lamp_emission(kg, &light_ray, state.flag, state.ray_pdf, light_t, &emission, state.bounce)) if(indirect_lamp_emission(kg, &light_ray, state.flag, state.ray_pdf, light_t, &emission, state.bounce, state.transparent_bounce))
path_radiance_accum_emission(L, throughput, emission, state.bounce); path_radiance_accum_emission(L, throughput, emission, state.bounce);
} }
#endif #endif
@ -275,7 +275,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, ccl_g
if(!hit) { if(!hit) {
#ifdef __BACKGROUND__ #ifdef __BACKGROUND__
/* sample background shader */ /* sample background shader */
float3 L_background = indirect_background(kg, &ray, state.flag, state.ray_pdf, state.bounce); float3 L_background = indirect_background(kg, &ray, state.flag, state.ray_pdf, state.bounce, state.transparent_bounce);
path_radiance_accum_background(L, throughput, L_background, state.bounce); path_radiance_accum_background(L, throughput, L_background, state.bounce);
#endif #endif
@ -284,7 +284,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, ccl_g
/* setup shading */ /* setup shading */
ShaderData sd; ShaderData sd;
shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce); shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce, state.transparent_bounce);
float rbsdf = path_state_rng_1D(kg, rng, &state, PRNG_BSDF); float rbsdf = path_state_rng_1D(kg, rng, &state, PRNG_BSDF);
shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_INDIRECT); shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_INDIRECT);
#ifdef __BRANCHED_PATH__ #ifdef __BRANCHED_PATH__
@ -490,7 +490,7 @@ ccl_device_inline bool kernel_path_integrate_lighting(KernelGlobals *kg, RNG *rn
light_ray.time = sd->time; light_ray.time = sd->time;
#endif #endif
if(direct_emission(kg, sd, LAMP_NONE, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce)) { if(direct_emission(kg, sd, LAMP_NONE, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
/* trace shadow ray */ /* trace shadow ray */
float3 shadow; float3 shadow;
@ -637,7 +637,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
float light_t = path_state_rng_1D(kg, rng, &state, PRNG_LIGHT); float light_t = path_state_rng_1D(kg, rng, &state, PRNG_LIGHT);
float3 emission; float3 emission;
if(indirect_lamp_emission(kg, &light_ray, state.flag, state.ray_pdf, light_t, &emission, state.bounce)) if(indirect_lamp_emission(kg, &light_ray, state.flag, state.ray_pdf, light_t, &emission, state.bounce, state.transparent_bounce))
path_radiance_accum_emission(&L, throughput, emission, state.bounce); path_radiance_accum_emission(&L, throughput, emission, state.bounce);
} }
#endif #endif
@ -674,7 +674,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
#ifdef __BACKGROUND__ #ifdef __BACKGROUND__
/* sample background shader */ /* sample background shader */
float3 L_background = indirect_background(kg, &ray, state.flag, state.ray_pdf, state.bounce); float3 L_background = indirect_background(kg, &ray, state.flag, state.ray_pdf, state.bounce, state.transparent_bounce);
path_radiance_accum_background(&L, throughput, L_background, state.bounce); path_radiance_accum_background(&L, throughput, L_background, state.bounce);
#endif #endif
@ -683,7 +683,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
/* setup shading */ /* setup shading */
ShaderData sd; ShaderData sd;
shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce); shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce, state.transparent_bounce);
float rbsdf = path_state_rng_1D(kg, rng, &state, PRNG_BSDF); float rbsdf = path_state_rng_1D(kg, rng, &state, PRNG_BSDF);
shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_MAIN); shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
@ -851,7 +851,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
light_ray.time = sd.time; light_ray.time = sd.time;
#endif #endif
if(direct_emission(kg, &sd, LAMP_NONE, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp, state.bounce)) { if(direct_emission(kg, &sd, LAMP_NONE, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp, state.bounce, state.transparent_bounce)) {
/* trace shadow ray */ /* trace shadow ray */
float3 shadow; float3 shadow;
@ -1100,7 +1100,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
VolumeSegment volume_segment; VolumeSegment volume_segment;
ShaderData volume_sd; ShaderData volume_sd;
shader_setup_from_volume(kg, &volume_sd, &volume_ray, state.bounce); shader_setup_from_volume(kg, &volume_sd, &volume_ray, state.bounce, state.transparent_bounce);
kernel_volume_decoupled_record(kg, &state, kernel_volume_decoupled_record(kg, &state,
&volume_ray, &volume_sd, &volume_segment, heterogeneous); &volume_ray, &volume_sd, &volume_segment, heterogeneous);
@ -1196,7 +1196,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#ifdef __BACKGROUND__ #ifdef __BACKGROUND__
/* sample background shader */ /* sample background shader */
float3 L_background = indirect_background(kg, &ray, state.flag, state.ray_pdf, state.bounce); float3 L_background = indirect_background(kg, &ray, state.flag, state.ray_pdf, state.bounce, state.transparent_bounce);
path_radiance_accum_background(&L, throughput, L_background, state.bounce); path_radiance_accum_background(&L, throughput, L_background, state.bounce);
#endif #endif
@ -1205,7 +1205,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
/* setup shading */ /* setup shading */
ShaderData sd; ShaderData sd;
shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce); shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce, state.transparent_bounce);
shader_eval_surface(kg, &sd, 0.0f, state.flag, SHADER_CONTEXT_MAIN); shader_eval_surface(kg, &sd, 0.0f, state.flag, SHADER_CONTEXT_MAIN);
shader_merge_closures(&sd); shader_merge_closures(&sd);

@ -49,7 +49,7 @@ ccl_device void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd
#endif #endif
ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
const Intersection *isect, const Ray *ray, int bounce) const Intersection *isect, const Ray *ray, int bounce, int transparent_bounce)
{ {
#ifdef __INSTANCING__ #ifdef __INSTANCING__
sd->object = (isect->object == PRIM_NONE)? kernel_tex_fetch(__prim_object, isect->prim): isect->object; sd->object = (isect->object == PRIM_NONE)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
@ -67,6 +67,7 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
sd->prim = kernel_tex_fetch(__prim_index, isect->prim); sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
sd->ray_length = isect->t; sd->ray_length = isect->t;
sd->ray_depth = bounce; sd->ray_depth = bounce;
sd->transparent_depth = transparent_bounce;
#ifdef __UV__ #ifdef __UV__
sd->u = isect->u; sd->u = isect->u;
@ -228,7 +229,7 @@ ccl_device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderDat
ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
const float3 P, const float3 Ng, const float3 I, const float3 P, const float3 Ng, const float3 I,
int shader, int object, int prim, float u, float v, float t, float time, int bounce) int shader, int object, int prim, float u, float v, float t, float time, int bounce, int transparent_bounce)
{ {
/* vectors */ /* vectors */
sd->P = P; sd->P = P;
@ -250,6 +251,7 @@ ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
#endif #endif
sd->ray_length = t; sd->ray_length = t;
sd->ray_depth = bounce; sd->ray_depth = bounce;
sd->transparent_depth = transparent_bounce;
/* detect instancing, for non-instanced the object index is -object-1 */ /* detect instancing, for non-instanced the object index is -object-1 */
#ifdef __INSTANCING__ #ifdef __INSTANCING__
@ -347,12 +349,12 @@ ccl_device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
/* watch out: no instance transform currently */ /* watch out: no instance transform currently */
shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v, 0.0f, TIME_INVALID, 0); shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v, 0.0f, TIME_INVALID, 0, 0);
} }
/* ShaderData setup from ray into background */ /* ShaderData setup from ray into background */
ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray, int bounce) ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray, int bounce, int transparent_bounce)
{ {
/* vectors */ /* vectors */
sd->P = ray->D; sd->P = ray->D;
@ -366,6 +368,7 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderDat
#endif #endif
sd->ray_length = 0.0f; sd->ray_length = 0.0f;
sd->ray_depth = bounce; sd->ray_depth = bounce;
sd->transparent_depth = transparent_bounce;
#ifdef __INSTANCING__ #ifdef __INSTANCING__
sd->object = PRIM_NONE; sd->object = PRIM_NONE;
@ -395,7 +398,7 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderDat
/* ShaderData setup from point inside volume */ /* ShaderData setup from point inside volume */
ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *sd, const Ray *ray, int bounce) ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *sd, const Ray *ray, int bounce, int transparent_bounce)
{ {
/* vectors */ /* vectors */
sd->P = ray->P; sd->P = ray->P;
@ -409,6 +412,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s
#endif #endif
sd->ray_length = 0.0f; /* todo: can we set this to some useful value? */ sd->ray_length = 0.0f; /* todo: can we set this to some useful value? */
sd->ray_depth = bounce; sd->ray_depth = bounce;
sd->transparent_depth = transparent_bounce;
#ifdef __INSTANCING__ #ifdef __INSTANCING__
sd->object = PRIM_NONE; /* todo: fill this for texture coordinates */ sd->object = PRIM_NONE; /* todo: fill this for texture coordinates */

@ -95,7 +95,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *
/* setup shader data at surface */ /* setup shader data at surface */
ShaderData sd; ShaderData sd;
shader_setup_from_ray(kg, &sd, &isect, ray, state->bounce+1); shader_setup_from_ray(kg, &sd, &isect, ray, ps.bounce+1, ps.transparent_bounce);
/* attenuation from transparent surface */ /* attenuation from transparent surface */
if(!(sd.flag & SD_HAS_ONLY_VOLUME)) { if(!(sd.flag & SD_HAS_ONLY_VOLUME)) {

@ -609,6 +609,9 @@ typedef struct ShaderData {
/* ray bounce depth */ /* ray bounce depth */
int ray_depth; int ray_depth;
/* ray transparent depth */
int transparent_depth;
#ifdef __RAY_DIFFERENTIALS__ #ifdef __RAY_DIFFERENTIALS__
/* differential of P. these are orthogonal to Ng, not N */ /* differential of P. these are orthogonal to Ng, not N */
differential3 dP; differential3 dP;

@ -184,7 +184,7 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, PathState
ccl_device_noinline void kernel_volume_shadow(KernelGlobals *kg, PathState *state, Ray *ray, float3 *throughput) ccl_device_noinline void kernel_volume_shadow(KernelGlobals *kg, PathState *state, Ray *ray, float3 *throughput)
{ {
ShaderData sd; ShaderData sd;
shader_setup_from_volume(kg, &sd, ray, state->bounce); shader_setup_from_volume(kg, &sd, ray, state->bounce, state->transparent_bounce);
if(volume_stack_is_heterogeneous(kg, state->volume_stack)) if(volume_stack_is_heterogeneous(kg, state->volume_stack))
kernel_volume_shadow_heterogeneous(kg, state, ray, &sd, throughput); kernel_volume_shadow_heterogeneous(kg, state, ray, &sd, throughput);
@ -828,7 +828,7 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(KernelGlobals
/* debugging code to compare decoupled ray marching */ /* debugging code to compare decoupled ray marching */
VolumeSegment segment; VolumeSegment segment;
shader_setup_from_volume(kg, sd, ray, state->bounce); shader_setup_from_volume(kg, sd, ray, state->bounce, state->transparent_bounce);
kernel_volume_decoupled_record(kg, state, ray, sd, &segment, heterogeneous); kernel_volume_decoupled_record(kg, state, ray, sd, &segment, heterogeneous);
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg, state, ray, sd, throughput, &tmp_rng, &segment); VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg, state, ray, sd, throughput, &tmp_rng, &segment);
@ -837,7 +837,7 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(KernelGlobals
return result; return result;
#else #else
shader_setup_from_volume(kg, sd, ray, state->bounce); shader_setup_from_volume(kg, sd, ray, state->bounce, state->transparent_bounce);
if(heterogeneous) if(heterogeneous)
return kernel_volume_integrate_heterogeneous(kg, state, ray, sd, L, throughput, &tmp_rng); return kernel_volume_integrate_heterogeneous(kg, state, ray, sd, L, throughput, &tmp_rng);

@ -85,6 +85,7 @@ ustring OSLRenderServices::u_curve_tangent_normal("geom:curve_tangent_normal");
#endif #endif
ustring OSLRenderServices::u_path_ray_length("path:ray_length"); ustring OSLRenderServices::u_path_ray_length("path:ray_length");
ustring OSLRenderServices::u_path_ray_depth("path:ray_depth"); ustring OSLRenderServices::u_path_ray_depth("path:ray_depth");
ustring OSLRenderServices::u_path_transparent_depth("path:transparent_depth");
ustring OSLRenderServices::u_trace("trace"); ustring OSLRenderServices::u_trace("trace");
ustring OSLRenderServices::u_hit("hit"); ustring OSLRenderServices::u_hit("hit");
ustring OSLRenderServices::u_hitdist("hitdist"); ustring OSLRenderServices::u_hitdist("hitdist");
@ -701,6 +702,11 @@ bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData *
int f = sd->ray_depth; int f = sd->ray_depth;
return set_attribute_int(f, type, derivatives, val); return set_attribute_int(f, type, derivatives, val);
} }
else if (name == u_path_transparent_depth) {
/* Ray Depth */
int f = sd->transparent_depth;
return set_attribute_int(f, type, derivatives, val);
}
else if (name == u_ndc) { else if (name == u_ndc) {
/* NDC coordinates with special exception for otho */ /* NDC coordinates with special exception for otho */
OSLThreadData *tdata = kg->osl_tdata; OSLThreadData *tdata = kg->osl_tdata;
@ -1031,8 +1037,9 @@ bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg, ustring source, ustri
/* lazy shader data setup */ /* lazy shader data setup */
ShaderData *original_sd = (ShaderData *)(sg->renderstate); ShaderData *original_sd = (ShaderData *)(sg->renderstate);
int bounce = original_sd->ray_depth + 1; int bounce = original_sd->ray_depth + 1;
int transparent_bounce = original_sd->transparent_depth;
shader_setup_from_ray(kg, sd, &tracedata->isect, &tracedata->ray, bounce); shader_setup_from_ray(kg, sd, &tracedata->isect, &tracedata->ray, bounce, transparent_bounce);
tracedata->setup = true; tracedata->setup = true;
} }

@ -144,6 +144,7 @@ public:
static ustring u_curve_tangent_normal; static ustring u_curve_tangent_normal;
static ustring u_path_ray_length; static ustring u_path_ray_length;
static ustring u_path_ray_depth; static ustring u_path_ray_depth;
static ustring u_path_transparent_depth;
static ustring u_trace; static ustring u_trace;
static ustring u_hit; static ustring u_hit;
static ustring u_hitdist; static ustring u_hitdist;

@ -26,7 +26,8 @@ shader node_light_path(
output float IsTransmissionRay = 0.0, output float IsTransmissionRay = 0.0,
output float IsVolumeScatterRay = 0.0, output float IsVolumeScatterRay = 0.0,
output float RayLength = 0.0, output float RayLength = 0.0,
output float RayDepth = 0.0) output float RayDepth = 0.0,
output float TransparentDepth = 0.0)
{ {
IsCameraRay = raytype("camera"); IsCameraRay = raytype("camera");
IsShadowRay = raytype("shadow"); IsShadowRay = raytype("shadow");
@ -42,5 +43,9 @@ shader node_light_path(
int ray_depth; int ray_depth;
getattribute("path:ray_depth", ray_depth); getattribute("path:ray_depth", ray_depth);
RayDepth = (float)ray_depth; RayDepth = (float)ray_depth;
int transparent_depth;
getattribute("path:transparent_depth", transparent_depth);
TransparentDepth = (float)transparent_depth;
} }

@ -34,6 +34,7 @@ ccl_device void svm_node_light_path(ShaderData *sd, float *stack, uint type, uin
case NODE_LP_backfacing: info = (sd->flag & SD_BACKFACING)? 1.0f: 0.0f; break; case NODE_LP_backfacing: info = (sd->flag & SD_BACKFACING)? 1.0f: 0.0f; break;
case NODE_LP_ray_length: info = sd->ray_length; break; case NODE_LP_ray_length: info = sd->ray_length; break;
case NODE_LP_ray_depth: info = (float)sd->ray_depth; break; case NODE_LP_ray_depth: info = (float)sd->ray_depth; break;
case NODE_LP_ray_transparent: info = sd->transparent_depth; break;
} }
stack_store_float(stack, out_offset, info); stack_store_float(stack, out_offset, info);

@ -160,7 +160,8 @@ typedef enum NodeLightPath {
NODE_LP_volume_scatter, NODE_LP_volume_scatter,
NODE_LP_backfacing, NODE_LP_backfacing,
NODE_LP_ray_length, NODE_LP_ray_length,
NODE_LP_ray_depth NODE_LP_ray_depth,
NODE_LP_ray_transparent
} NodeLightPath; } NodeLightPath;
typedef enum NodeLightFalloff { typedef enum NodeLightFalloff {

@ -2419,6 +2419,7 @@ LightPathNode::LightPathNode()
add_output("Is Volume Scatter Ray", SHADER_SOCKET_FLOAT); add_output("Is Volume Scatter Ray", SHADER_SOCKET_FLOAT);
add_output("Ray Length", SHADER_SOCKET_FLOAT); add_output("Ray Length", SHADER_SOCKET_FLOAT);
add_output("Ray Depth", SHADER_SOCKET_FLOAT); add_output("Ray Depth", SHADER_SOCKET_FLOAT);
add_output("Transparent Depth", SHADER_SOCKET_FLOAT);
} }
void LightPathNode::compile(SVMCompiler& compiler) void LightPathNode::compile(SVMCompiler& compiler)
@ -2486,6 +2487,11 @@ void LightPathNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_depth, out->stack_offset); compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_depth, out->stack_offset);
} }
out = output("Transparent Depth");
if(!out->links.empty()) {
compiler.stack_assign(out);
compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transparent, out->stack_offset);
}
} }
void LightPathNode::compile(OSLCompiler& compiler) void LightPathNode::compile(OSLCompiler& compiler)

@ -39,6 +39,7 @@ static bNodeSocketTemplate sh_node_light_path_out[] = {
{ SOCK_FLOAT, 0, N_("Is Transmission Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Is Transmission Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Ray Length"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Ray Length"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Ray Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Ray Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Transparent Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" } { -1, 0, "" }
}; };