Cycles: add Ray Length output to Light Path node. This gives the distance travelled

by the last light ray. One use case for this might be to do absorption.

Patch #31232 by Agustin benavidez, see this blog post for details:
http://agus3d.blogspot.com.ar/2012/05/blender-cycles-ray-length-node-output.html
This commit is contained in:
Brecht Van Lommel
2012-05-02 17:03:46 +00:00
parent 89f554fd24
commit d64661b507
7 changed files with 23 additions and 6 deletions

View File

@@ -21,7 +21,7 @@ CCL_NAMESPACE_BEGIN
/* Direction Emission */
__device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
LightSample *ls, float u, float v, float3 I, float time)
LightSample *ls, float u, float v, float3 I, float t, float time)
{
/* setup shading at emitter */
ShaderData sd;
@@ -40,7 +40,7 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
else
#endif
{
shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, time);
shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time);
ls->Ng = sd.Ng;
/* no path flag, we're evaluating this for all closures. that's weak but
@@ -87,7 +87,7 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
return false;
/* evaluate closure */
float3 light_eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -ls.D, sd->time);
float3 light_eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -ls.D, ls.t, sd->time);
if(is_zero(light_eval))
return false;

View File

@@ -77,6 +77,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
sd->N = Ng;
sd->I = -ray->D;
sd->shader = shader;
sd->ray_length = isect->t;
/* smooth normal */
if(sd->shader & SHADER_SMOOTH_NORMAL)
@@ -127,7 +128,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
__device 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 time)
int shader, int object, int prim, float u, float v, float t, float time)
{
/* vectors */
sd->P = P;
@@ -145,6 +146,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
sd->u = u;
sd->v = v;
#endif
sd->ray_length = t;
/* detect instancing, for non-instanced the object index is -object-1 */
#ifdef __INSTANCING__
@@ -242,7 +244,7 @@ __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, TIME_INVALID);
shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v, 0.0f, TIME_INVALID);
}
/* ShaderData setup from ray into background */
@@ -259,6 +261,7 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
#ifdef __MOTION__
sd->time = ray->time;
#endif
sd->ray_length = 0.0f;
#ifdef __INSTANCING__
sd->object = ~0;

View File

@@ -402,6 +402,9 @@ typedef struct ShaderData {
/* motion blur sample time */
float time;
/* length of the ray being shaded */
float ray_length;
#ifdef __MOTION__
/* object <-> world space transformations, cached to avoid
* re-interpolating them constantly for shading */

View File

@@ -33,6 +33,7 @@ __device void svm_node_light_path(ShaderData *sd, float *stack, uint type, uint
case NODE_LP_reflection: info = (path_flag & PATH_RAY_REFLECT)? 1.0f: 0.0f; break;
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;
}
stack_store_float(stack, out_offset, info);

View File

@@ -115,7 +115,8 @@ typedef enum NodeLightPath {
NODE_LP_singular,
NODE_LP_reflection,
NODE_LP_transmission,
NODE_LP_backfacing
NODE_LP_backfacing,
NODE_LP_ray_length
} NodeLightPath;
typedef enum NodeTexCoord {

View File

@@ -1623,6 +1623,7 @@ LightPathNode::LightPathNode()
add_output("Is Singular Ray", SHADER_SOCKET_FLOAT);
add_output("Is Reflection Ray", SHADER_SOCKET_FLOAT);
add_output("Is Transmission Ray", SHADER_SOCKET_FLOAT);
add_output("Ray Length", SHADER_SOCKET_FLOAT);
}
void LightPathNode::compile(SVMCompiler& compiler)
@@ -1671,6 +1672,13 @@ void LightPathNode::compile(SVMCompiler& compiler)
compiler.stack_assign(out);
compiler.add_node(NODE_LIGHT_PATH, NODE_LP_transmission, out->stack_offset);
}
out = output("Ray Length");
if(!out->links.empty()) {
compiler.stack_assign(out);
compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_length, out->stack_offset);
}
}
void LightPathNode::compile(OSLCompiler& compiler)

View File

@@ -37,6 +37,7 @@ static bNodeSocketTemplate sh_node_light_path_out[]= {
{ SOCK_FLOAT, 0, "Is Singular Ray", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, "Is Reflection Ray", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, "Is Transmission Ray", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, "Ray Length", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};