diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-05-08 00:24:38 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-05-08 00:24:38 +0400 |
commit | e6a84eb1b542e7cafe5e760530882bb806f3c433 (patch) | |
tree | e3d7b9f8dab6c2d55ec0d45297ba281599f3e92f /intern | |
parent | f44e80e6387601dea6e4e0801d0a387455a02d31 (diff) |
Cycles: add light falloff node, with quadratic/linear/constant falloff and a
smoothing factor to reduce high values near the light.
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/More#Light_Falloff
Note that this was already possible to do manually with the Ray Length, but
this adds a convenient node for it. This commit also makes the mapping node
min/max option work, fixing #31348.
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/blender_shader.cpp | 11 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm.h | 6 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_light_path.h | 27 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_mapping.h | 11 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_types.h | 10 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 61 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 8 |
7 files changed, 133 insertions, 1 deletions
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 52d97753db3..b33de789631 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -97,6 +97,13 @@ static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_map mapping->translation = get_float3(b_mapping.translation()); mapping->rotation = get_float3(b_mapping.rotation()); mapping->scale = get_float3(b_mapping.scale()); + + mapping->use_minmax = b_mapping.use_min() || b_mapping.use_max(); + + if(b_mapping.use_min()) + mapping->min = get_float3(b_mapping.min()); + if(b_mapping.use_max()) + mapping->max = get_float3(b_mapping.max()); } static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNode b_node) @@ -323,6 +330,10 @@ static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Shader node = new LightPathNode(); break; } + case BL::ShaderNode::type_LIGHT_FALLOFF: { + node = new LightFalloffNode(); + break; + } case BL::ShaderNode::type_TEX_IMAGE: { BL::ShaderNodeTexImage b_image_node(b_node); BL::Image b_image(b_image_node.image()); diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 50181c0cf2c..5f4d7bbd0c4 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -326,6 +326,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_MAPPING: svm_node_mapping(kg, sd, stack, node.y, node.z, &offset); break; + case NODE_MIN_MAX: + svm_node_min_max(kg, sd, stack, node.y, node.z, &offset); + break; case NODE_TEX_COORD: svm_node_tex_coord(kg, sd, stack, node.y, node.z); break; @@ -344,6 +347,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_RGB_CURVES: svm_node_rgb_curves(kg, sd, stack, node, &offset); break; + case NODE_LIGHT_FALLOFF: + svm_node_light_falloff(sd, stack, node); + break; case NODE_END: default: #ifndef __MULTI_CLOSURE__ diff --git a/intern/cycles/kernel/svm/svm_light_path.h b/intern/cycles/kernel/svm/svm_light_path.h index ebbcb5be61f..b29dc9cbd45 100644 --- a/intern/cycles/kernel/svm/svm_light_path.h +++ b/intern/cycles/kernel/svm/svm_light_path.h @@ -39,5 +39,32 @@ __device void svm_node_light_path(ShaderData *sd, float *stack, uint type, uint stack_store_float(stack, out_offset, info); } +/* Light Falloff Node */ + +__device void svm_node_light_falloff(ShaderData *sd, float *stack, uint4 node) +{ + uint strength_offset, out_offset, smooth_offset; + + decode_node_uchar4(node.z, &strength_offset, &smooth_offset, &out_offset, NULL); + + float strength = stack_load_float(stack, strength_offset); + uint type = node.y; + + switch(type) { + case NODE_LIGHT_FALLOFF_QUADRATIC: break; + case NODE_LIGHT_FALLOFF_LINEAR: strength *= sd->ray_length; break; + case NODE_LIGHT_FALLOFF_CONSTANT: strength *= sd->ray_length*sd->ray_length; break; + } + + float smooth = stack_load_float(stack, smooth_offset); + + if(smooth > 0.0f) { + float squared = sd->ray_length*sd->ray_length; + strength *= squared/(smooth + squared); + } + + stack_store_float(stack, out_offset, strength); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_mapping.h b/intern/cycles/kernel/svm/svm_mapping.h index 6dc74aece08..96645ac97db 100644 --- a/intern/cycles/kernel/svm/svm_mapping.h +++ b/intern/cycles/kernel/svm/svm_mapping.h @@ -34,5 +34,16 @@ __device void svm_node_mapping(KernelGlobals *kg, ShaderData *sd, float *stack, stack_store_float3(stack, out_offset, r); } +__device void svm_node_min_max(KernelGlobals *kg, ShaderData *sd, float *stack, uint vec_offset, uint out_offset, int *offset) +{ + float3 v = stack_load_float3(stack, vec_offset); + + float3 mn = float4_to_float3(read_node_float(kg, offset)); + float3 mx = float4_to_float3(read_node_float(kg, offset)); + + float3 r = min(max(mn, v), mx); + stack_store_float3(stack, out_offset, r); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 8037c3964a9..867709f29e0 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -90,7 +90,9 @@ typedef enum NodeType { NODE_TEX_CHECKER = 5700, NODE_BRIGHTCONTRAST = 5800, NODE_RGB_RAMP = 5900, - NODE_RGB_CURVES = 6000 + NODE_RGB_CURVES = 6000, + NODE_MIN_MAX = 6100, + NODE_LIGHT_FALLOFF = 6200 } NodeType; typedef enum NodeAttributeType { @@ -119,6 +121,12 @@ typedef enum NodeLightPath { NODE_LP_ray_length } NodeLightPath; +typedef enum NodeLightFalloff { + NODE_LIGHT_FALLOFF_QUADRATIC, + NODE_LIGHT_FALLOFF_LINEAR, + NODE_LIGHT_FALLOFF_CONSTANT +} NodeLightFalloff; + typedef enum NodeTexCoord { NODE_TEXCO_NORMAL, NODE_TEXCO_OBJECT, diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index fd26c552f21..afc59098432 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -33,6 +33,11 @@ TextureMapping::TextureMapping() rotation = make_float3(0.0f, 0.0f, 0.0f); scale = make_float3(1.0f, 1.0f, 1.0f); + min = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX); + max = make_float3(FLT_MAX, FLT_MAX, FLT_MAX); + + use_minmax = false; + x_mapping = X; y_mapping = Y; z_mapping = Z; @@ -69,6 +74,8 @@ bool TextureMapping::skip() if(x_mapping != X || y_mapping != Y || z_mapping != Z) return false; + if(use_minmax) + return false; return true; } @@ -85,6 +92,12 @@ void TextureMapping::compile(SVMCompiler& compiler, int offset_in, int offset_ou compiler.add_node(tfm.y); compiler.add_node(tfm.z); compiler.add_node(tfm.w); + + if(use_minmax) { + compiler.add_node(NODE_MIN_MAX, offset_out, offset_out); + compiler.add_node(float3_to_float4(min)); + compiler.add_node(float3_to_float4(max)); + } } /* Image Texture */ @@ -1686,6 +1699,54 @@ void LightPathNode::compile(OSLCompiler& compiler) compiler.add(this, "node_light_path"); } +/* Light Path */ + +LightFalloffNode::LightFalloffNode() +: ShaderNode("light_path") +{ + add_input("Strength", SHADER_SOCKET_FLOAT, 100.0f); + add_input("Smooth", SHADER_SOCKET_FLOAT, 0.0f); + add_output("Quadratic", SHADER_SOCKET_FLOAT); + add_output("Linear", SHADER_SOCKET_FLOAT); + add_output("Constant", SHADER_SOCKET_FLOAT); +} + +void LightFalloffNode::compile(SVMCompiler& compiler) +{ + ShaderInput *strength_in = input("Strength"); + ShaderInput *smooth_in = input("Smooth"); + + compiler.stack_assign(strength_in); + compiler.stack_assign(smooth_in); + + ShaderOutput *out = output("Quadratic"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_QUADRATIC, + compiler.encode_uchar4(strength_in->stack_offset, smooth_in->stack_offset, out->stack_offset)); + } + + out = output("Linear"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_LINEAR, + compiler.encode_uchar4(strength_in->stack_offset, smooth_in->stack_offset, out->stack_offset)); + compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_LINEAR, out->stack_offset); + } + + out = output("Constant"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_CONSTANT, + compiler.encode_uchar4(strength_in->stack_offset, smooth_in->stack_offset, out->stack_offset)); + } +} + +void LightFalloffNode::compile(OSLCompiler& compiler) +{ + compiler.add(this, "node_light_falloff"); +} + /* Value */ ValueNode::ValueNode() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 364209f8c5e..ff9e3647d01 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -41,6 +41,9 @@ public: float3 rotation; float3 scale; + float3 min, max; + bool use_minmax; + enum Mapping { NONE=0, X=1, Y=2, Z=3 }; Mapping x_mapping, y_mapping, z_mapping; @@ -277,6 +280,11 @@ public: SHADER_NODE_CLASS(LightPathNode) }; +class LightFalloffNode : public ShaderNode { +public: + SHADER_NODE_CLASS(LightFalloffNode) +}; + class ValueNode : public ShaderNode { public: SHADER_NODE_CLASS(ValueNode) |