Cycles: constant folding for RGB/Vector Curves and Color Ramp.
[blender.git] / intern / cycles / render / nodes.cpp
index ed4debdddfcb9ecce0598f25578afef616446571..b3b010841e99a388378f2f0feb26b37c86f8c2e1 100644 (file)
@@ -20,6 +20,7 @@
 #include "scene.h"
 #include "svm.h"
 #include "svm_color_util.h"
+#include "svm_ramp_util.h"
 #include "svm_math_util.h"
 #include "osl.h"
 #include "constant_fold.h"
@@ -2295,6 +2296,7 @@ NODE_DEFINE(SubsurfaceScatteringNode)
 SubsurfaceScatteringNode::SubsurfaceScatteringNode()
 : BsdfNode(node_type)
 {
+       closure = falloff;
 }
 
 void SubsurfaceScatteringNode::compile(SVMCompiler& compiler)
@@ -2305,6 +2307,7 @@ void SubsurfaceScatteringNode::compile(SVMCompiler& compiler)
 
 void SubsurfaceScatteringNode::compile(OSLCompiler& compiler)
 {
+       closure = falloff;
        compiler.parameter(this, "falloff");
        compiler.add(this, "node_subsurface_scattering");
 }
@@ -4853,6 +4856,30 @@ CurvesNode::CurvesNode(const NodeType *node_type)
 {
 }
 
+void CurvesNode::constant_fold(const ConstantFolder& folder, ShaderInput *value_in)
+{
+       ShaderInput *fac_in = input("Fac");
+
+       /* remove no-op node */
+       if(!fac_in->link && fac == 0.0f) {
+               folder.bypass(value_in->link);
+       }
+       /* evaluate fully constant node */
+       else if(folder.all_inputs_constant()) {
+               if (curves.size() == 0)
+                       return;
+
+               float3 pos = (value - make_float3(min_x, min_x, min_x)) / (max_x - min_x);
+               float3 result;
+
+               result[0] = rgb_ramp_lookup(curves.data(), pos[0], true, true, curves.size()).x;
+               result[1] = rgb_ramp_lookup(curves.data(), pos[1], true, true, curves.size()).y;
+               result[2] = rgb_ramp_lookup(curves.data(), pos[2], true, true, curves.size()).z;
+
+               folder.make_constant(interp(value, result, fac));
+       }
+}
+
 void CurvesNode::compile(SVMCompiler& compiler, int type, ShaderInput *value_in, ShaderOutput *value_out)
 {
        if(curves.size() == 0)
@@ -4916,6 +4943,11 @@ RGBCurvesNode::RGBCurvesNode()
 {
 }
 
+void RGBCurvesNode::constant_fold(const ConstantFolder& folder)
+{
+       CurvesNode::constant_fold(folder, input("Color"));
+}
+
 void RGBCurvesNode::compile(SVMCompiler& compiler)
 {
        CurvesNode::compile(compiler, NODE_RGB_CURVES, input("Color"), output("Color"));
@@ -4949,6 +4981,11 @@ VectorCurvesNode::VectorCurvesNode()
 {
 }
 
+void VectorCurvesNode::constant_fold(const ConstantFolder& folder)
+{
+       CurvesNode::constant_fold(folder, input("Vector"));
+}
+
 void VectorCurvesNode::compile(SVMCompiler& compiler)
 {
        CurvesNode::compile(compiler, NODE_VECTOR_CURVES, input("Vector"), output("Vector"));
@@ -4982,6 +5019,31 @@ RGBRampNode::RGBRampNode()
 {
 }
 
+void RGBRampNode::constant_fold(const ConstantFolder& folder)
+{
+       if(ramp.size() == 0 || ramp.size() != ramp_alpha.size())
+               return;
+
+       if(folder.all_inputs_constant()) {
+               float f = clamp(fac, 0.0f, 1.0f) * (ramp.size() - 1);
+
+               /* clamp int as well in case of NaN */
+               int i = clamp((int)f, 0, ramp.size()-1);
+               float t = f - (float)i;
+
+               bool use_lerp = interpolate && t > 0.0f;
+
+               if(folder.output == output("Color")) {
+                       float3 color = rgb_ramp_lookup(ramp.data(), fac, use_lerp, false, ramp.size());
+                       folder.make_constant(color);
+               }
+               else if(folder.output == output("Alpha")) {
+                       float alpha = float_ramp_lookup(ramp_alpha.data(), fac, use_lerp, false, ramp_alpha.size());
+                       folder.make_constant(alpha);
+               }
+       }
+}
+
 void RGBRampNode::compile(SVMCompiler& compiler)
 {
        if(ramp.size() == 0 || ramp.size() != ramp_alpha.size())