From 3840e0b2347200ceb414f12deb3436b20d274c66 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 31 Jul 2013 20:30:37 +0000 Subject: Cycles / Ray Depth: * Added a Ray Depth output to the Light Path node, which gives the user access to the current bounce. This can be used to limit the maximum ray bounce on a per shader basis. Another use case is to restrict light influence with this, to have a lamp only contribute to the direct lighting. http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/More#Light_Path This is part of my GSoC 2013 project. SVN merge of r58091 and r58772 from soc-2013-dingto. --- intern/cycles/kernel/kernel_displace.h | 2 +- intern/cycles/kernel/kernel_emission.h | 20 +++++++++--------- intern/cycles/kernel/kernel_path.h | 26 ++++++++++++------------ intern/cycles/kernel/kernel_shader.h | 11 ++++++---- intern/cycles/kernel/kernel_types.h | 3 +++ intern/cycles/kernel/osl/osl_services.cpp | 11 +++++++++- intern/cycles/kernel/osl/osl_services.h | 1 + intern/cycles/kernel/shaders/node_light_path.osl | 7 ++++++- intern/cycles/kernel/svm/svm_light_path.h | 1 + intern/cycles/kernel/svm/svm_types.h | 3 ++- intern/cycles/render/nodes.cpp | 7 +++++++ 11 files changed, 61 insertions(+), 31 deletions(-) (limited to 'intern/cycles') diff --git a/intern/cycles/kernel/kernel_displace.h b/intern/cycles/kernel/kernel_displace.h index ae2e35e8d93..b4ece1610be 100644 --- a/intern/cycles/kernel/kernel_displace.h +++ b/intern/cycles/kernel/kernel_displace.h @@ -57,7 +57,7 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, __global uint4 *input, _ #endif /* setup shader data */ - shader_setup_from_background(kg, &sd, &ray); + shader_setup_from_background(kg, &sd, &ray, 0); /* evaluate */ int flag = 0; /* we can't know which type of BSDF this is for */ diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 77dc59d2691..a6bd3ed2850 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -21,7 +21,7 @@ CCL_NAMESPACE_BEGIN /* Direction Emission */ __device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando, - LightSample *ls, float u, float v, float3 I, differential3 dI, float t, float time) + LightSample *ls, float u, float v, float3 I, differential3 dI, float t, float time, int bounce) { /* setup shading at emitter */ ShaderData sd; @@ -41,7 +41,7 @@ __device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando, #ifdef __CAMERA_MOTION__ ray.time = time; #endif - shader_setup_from_background(kg, &sd, &ray); + shader_setup_from_background(kg, &sd, &ray, bounce+1); eval = shader_eval_background(kg, &sd, 0, SHADER_CONTEXT_EMISSION); } else @@ -49,10 +49,10 @@ __device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando, { #ifdef __HAIR__ if(ls->type == LIGHT_STRAND) - shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time, ls->prim); + shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time, bounce+1, ls->prim); else #endif - shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time, ~0); + shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time, bounce+1, ~0); ls->Ng = sd.Ng; @@ -74,7 +74,7 @@ __device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando, __device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex, float randt, float rando, float randu, float randv, Ray *ray, BsdfEval *eval, - bool *is_lamp) + bool *is_lamp, int bounce) { LightSample ls; @@ -97,7 +97,7 @@ __device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, int li differential3 dD = differential3_zero(); /* evaluate closure */ - float3 light_eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -ls.D, dD, ls.t, sd->time); + float3 light_eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -ls.D, dD, ls.t, sd->time, bounce); if(is_zero(light_eval)) return false; @@ -185,7 +185,7 @@ __device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, ShaderDa /* Indirect Lamp Emission */ -__device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf, float randt, float3 *emission) +__device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf, float randt, float3 *emission, int bounce) { LightSample ls; int lamp = lamp_light_eval_sample(kg, randt); @@ -209,7 +209,7 @@ __device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int p /* todo: missing texture coordinates */ float u = 0.0f; float v = 0.0f; - float3 L = direct_emissive_eval(kg, 0.0f, &ls, u, v, -ray->D, ray->dD, ls.t, ray->time); + float3 L = direct_emissive_eval(kg, 0.0f, &ls, u, v, -ray->D, ray->dD, ls.t, ray->time, bounce); if(!(path_flag & PATH_RAY_MIS_SKIP)) { /* multiple importance sampling, get regular light pdf, @@ -224,7 +224,7 @@ __device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int p /* Indirect Background */ -__device_noinline float3 indirect_background(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf) +__device_noinline float3 indirect_background(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf, int bounce) { #ifdef __BACKGROUND__ int shader = kernel_data.background.shader; @@ -240,7 +240,7 @@ __device_noinline float3 indirect_background(KernelGlobals *kg, Ray *ray, int pa /* evaluate background closure */ ShaderData sd; - shader_setup_from_background(kg, &sd, ray); + shader_setup_from_background(kg, &sd, ray, bounce+1); float3 L = shader_eval_background(kg, &sd, path_flag, SHADER_CONTEXT_EMISSION); diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 0ef255786fa..40ecb1be91b 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -215,7 +215,7 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra return true; ShaderData sd; - shader_setup_from_ray(kg, &sd, &isect, ray); + shader_setup_from_ray(kg, &sd, &isect, ray, state->bounce+1); shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW); throughput *= shader_bsdf_transparency(kg, &sd); @@ -300,7 +300,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, float light_t = path_rng_1D(kg, rng, sample, num_samples, rng_offset + PRNG_LIGHT); float3 emission; - if(indirect_lamp_emission(kg, &light_ray, state.flag, ray_pdf, light_t, &emission)) + if(indirect_lamp_emission(kg, &light_ray, state.flag, ray_pdf, light_t, &emission, state.bounce)) path_radiance_accum_emission(&L, throughput, emission, state.bounce); } #endif @@ -318,7 +318,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, #ifdef __BACKGROUND__ /* sample background shader */ - float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf); + float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf, state.bounce); path_radiance_accum_background(&L, throughput, L_background, state.bounce); #endif @@ -327,7 +327,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, /* setup shading */ ShaderData sd; - shader_setup_from_ray(kg, &sd, &isect, &ray); + shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce); float rbsdf = path_rng_1D(kg, rng, sample, num_samples, rng_offset + PRNG_BSDF); shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_MAIN); @@ -464,7 +464,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, light_ray.time = sd.time; #endif - if(direct_emission(kg, &sd, -1, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp)) { + if(direct_emission(kg, &sd, -1, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp, state.bounce)) { /* trace shadow ray */ float3 shadow; @@ -575,7 +575,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray float light_t = path_rng_1D(kg, rng, sample, num_total_samples, rng_offset + PRNG_LIGHT); float3 emission; - if(indirect_lamp_emission(kg, &light_ray, state.flag, ray_pdf, light_t, &emission)) + if(indirect_lamp_emission(kg, &light_ray, state.flag, ray_pdf, light_t, &emission, state.bounce)) path_radiance_accum_emission(L, throughput, emission, state.bounce); } #endif @@ -583,7 +583,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray if(!hit) { #ifdef __BACKGROUND__ /* sample background shader */ - float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf); + float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf, state.bounce); path_radiance_accum_background(L, throughput, L_background, state.bounce); #endif @@ -592,7 +592,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray /* setup shading */ ShaderData sd; - shader_setup_from_ray(kg, &sd, &isect, &ray); + shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce); 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); shader_merge_closures(kg, &sd); @@ -706,7 +706,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray #endif /* sample random light */ - if(direct_emission(kg, &sd, -1, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp)) { + if(direct_emission(kg, &sd, -1, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp, state.bounce)) { /* trace shadow ray */ float3 shadow; @@ -838,7 +838,7 @@ __device_noinline void kernel_path_non_progressive_lighting(KernelGlobals *kg, R float light_u, light_v; path_rng_2D(kg, &lamp_rng, sample*num_samples + j, aa_samples*num_samples, rng_offset + 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)) { + if(direct_emission(kg, sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state.bounce)) { /* trace shadow ray */ float3 shadow; @@ -867,7 +867,7 @@ __device_noinline void kernel_path_non_progressive_lighting(KernelGlobals *kg, R if(kernel_data.integrator.num_all_lights) light_t = 0.5f*light_t; - if(direct_emission(kg, sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) { + if(direct_emission(kg, sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state.bounce)) { /* trace shadow ray */ float3 shadow; @@ -1013,7 +1013,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam #ifdef __BACKGROUND__ /* sample background shader */ - float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf); + float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf, state.bounce); path_radiance_accum_background(&L, throughput, L_background, state.bounce); #endif @@ -1022,7 +1022,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam /* setup shading */ ShaderData sd; - shader_setup_from_ray(kg, &sd, &isect, &ray); + 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); diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 039981a031a..b902230a9b9 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -64,7 +64,7 @@ __device_noinline __device #endif void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, - const Intersection *isect, const Ray *ray) + const Intersection *isect, const Ray *ray, int bounce) { #ifdef __INSTANCING__ sd->object = (isect->object == ~0)? kernel_tex_fetch(__prim_object, isect->prim): isect->object; @@ -80,6 +80,7 @@ void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, sd->prim = kernel_tex_fetch(__prim_index, isect->prim); sd->ray_length = isect->t; + sd->ray_depth = bounce; #ifdef __HAIR__ if(kernel_tex_fetch(__prim_segment, isect->prim) != ~0) { @@ -277,7 +278,7 @@ __device #endif void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, const float3 P, const float3 Ng, const float3 I, - int shader, int object, int prim, float u, float v, float t, float time, int segment) + int shader, int object, int prim, float u, float v, float t, float time, int bounce, int segment) { /* vectors */ sd->P = P; @@ -300,6 +301,7 @@ void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, sd->v = v; #endif sd->ray_length = t; + sd->ray_depth = bounce; /* detect instancing, for non-instanced the object index is -object-1 */ #ifdef __INSTANCING__ @@ -408,12 +410,12 @@ __device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd, /* 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 */ -__device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray) +__device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray, int bounce) { /* vectors */ sd->P = ray->D; @@ -426,6 +428,7 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData sd->time = ray->time; #endif sd->ray_length = 0.0f; + sd->ray_depth = bounce; #ifdef __INSTANCING__ sd->object = ~0; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 38ababa96bd..733eb665860 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -540,6 +540,9 @@ typedef struct ShaderData { /* length of the ray being shaded */ float ray_length; + + /* ray bounce depth */ + int ray_depth; #ifdef __RAY_DIFFERENTIALS__ /* differential of P. these are orthogonal to Ng, not N */ diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index e1e43b117e7..f3b79da8894 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -84,6 +84,7 @@ ustring OSLRenderServices::u_curve_thickness("geom:curve_thickness"); ustring OSLRenderServices::u_curve_tangent_normal("geom:curve_tangent_normal"); #endif ustring OSLRenderServices::u_path_ray_length("path:ray_length"); +ustring OSLRenderServices::u_path_ray_depth("path:ray_depth"); ustring OSLRenderServices::u_trace("trace"); ustring OSLRenderServices::u_hit("hit"); ustring OSLRenderServices::u_hitdist("hitdist"); @@ -660,6 +661,11 @@ bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData * float f = sd->ray_length; return set_attribute_float(f, type, derivatives, val); } + else if (name == u_path_ray_depth) { + /* Ray Depth */ + int f = sd->ray_depth; + return set_attribute_int(f, type, derivatives, val); + } else if (name == u_ndc) { /* NDC coordinates with special exception for otho */ OSLThreadData *tdata = kg->osl_tdata; @@ -919,7 +925,10 @@ bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg, ustring source, ustri if(!tracedata->setup) { /* lazy shader data setup */ - shader_setup_from_ray(kg, sd, &tracedata->isect, &tracedata->ray); + ShaderData *original_sd = (ShaderData *)(sg->renderstate); + int bounce = original_sd->ray_depth + 1; + + shader_setup_from_ray(kg, sd, &tracedata->isect, &tracedata->ray, bounce); tracedata->setup = true; } diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index ca18c85a167..5ec4673ef37 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -135,6 +135,7 @@ public: static ustring u_curve_thickness; static ustring u_curve_tangent_normal; static ustring u_path_ray_length; + static ustring u_path_ray_depth; static ustring u_trace; static ustring u_hit; static ustring u_hitdist; diff --git a/intern/cycles/kernel/shaders/node_light_path.osl b/intern/cycles/kernel/shaders/node_light_path.osl index 9e3f6c7b4a9..ed3c6969970 100644 --- a/intern/cycles/kernel/shaders/node_light_path.osl +++ b/intern/cycles/kernel/shaders/node_light_path.osl @@ -26,7 +26,8 @@ shader node_light_path( output float IsSingularRay = 0.0, output float IsReflectionRay = 0.0, output float IsTransmissionRay = 0.0, - output float RayLength = 0.0) + output float RayLength = 0.0, + output float RayDepth = 0.0) { IsCameraRay = raytype("camera"); IsShadowRay = raytype("shadow"); @@ -37,5 +38,9 @@ shader node_light_path( IsTransmissionRay = raytype("refraction"); getattribute("path:ray_length", RayLength); + + int ray_depth; + getattribute("path:ray_depth", ray_depth); + RayDepth = (float)ray_depth; } diff --git a/intern/cycles/kernel/svm/svm_light_path.h b/intern/cycles/kernel/svm/svm_light_path.h index b29dc9cbd45..0f16ef83894 100644 --- a/intern/cycles/kernel/svm/svm_light_path.h +++ b/intern/cycles/kernel/svm/svm_light_path.h @@ -34,6 +34,7 @@ __device void svm_node_light_path(ShaderData *sd, float *stack, uint type, uint case NODE_LP_transmission: info = (path_flag & PATH_RAY_TRANSMIT)? 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_depth: info = (float)sd->ray_depth; break; } stack_store_float(stack, out_offset, info); diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index e5b3e2b972f..85719265292 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -153,7 +153,8 @@ typedef enum NodeLightPath { NODE_LP_reflection, NODE_LP_transmission, NODE_LP_backfacing, - NODE_LP_ray_length + NODE_LP_ray_length, + NODE_LP_ray_depth } NodeLightPath; typedef enum NodeLightFalloff { diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 029b948332a..bd254c8e0d1 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -2064,6 +2064,7 @@ LightPathNode::LightPathNode() add_output("Is Reflection Ray", SHADER_SOCKET_FLOAT); add_output("Is Transmission Ray", SHADER_SOCKET_FLOAT); add_output("Ray Length", SHADER_SOCKET_FLOAT); + add_output("Ray Depth", SHADER_SOCKET_FLOAT); } void LightPathNode::compile(SVMCompiler& compiler) @@ -2118,6 +2119,12 @@ void LightPathNode::compile(SVMCompiler& compiler) compiler.stack_assign(out); compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_length, out->stack_offset); } + + out = output("Ray Depth"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_depth, out->stack_offset); + } } -- cgit v1.2.3