diff options
author | Alexander Gavrilov <angavrilov@gmail.com> | 2016-09-29 00:35:53 +0300 |
---|---|---|
committer | Alexander Gavrilov <angavrilov@gmail.com> | 2016-10-01 14:37:03 +0300 |
commit | 40eedd5df9083ce54c38c6307946488a1fa8aae0 (patch) | |
tree | e3060fcab4e8ead3d6ec6c9254fddf5cf0b35aec /intern/cycles | |
parent | 95fa303efd0b6e2963af423e601bb2869ac82520 (diff) |
Cycles: implement partial constant folding for exponentiation.
This is also an important mathematical operation that can be folded
if it is known that one argument is a certain constant. For colors
the operation is provided as a Gamma node.
The SVM Gamma node needs a small fix to make it follow the 0 ^ 0 == 1
rule, same as the Power node, or the Gamma node itself in OSL mode.
Reviewers: #cycles
Differential Revision: https://developer.blender.org/D2263
Diffstat (limited to 'intern/cycles')
-rw-r--r-- | intern/cycles/kernel/svm/svm_math_util.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/constant_fold.cpp | 22 | ||||
-rw-r--r-- | intern/cycles/render/constant_fold.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 13 | ||||
-rw-r--r-- | intern/cycles/test/render_graph_finalize_test.cpp | 100 |
5 files changed, 139 insertions, 0 deletions
diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h index 6d13a0d8e02..01547b60014 100644 --- a/intern/cycles/kernel/svm/svm_math_util.h +++ b/intern/cycles/kernel/svm/svm_math_util.h @@ -164,6 +164,9 @@ ccl_device float3 svm_math_blackbody_color(float t) { ccl_device_inline float3 svm_math_gamma_color(float3 color, float gamma) { + if(gamma == 0.0f) + return make_float3(1.0f, 1.0f, 1.0f); + if(color.x > 0.0f) color.x = powf(color.x, gamma); if(color.y > 0.0f) diff --git a/intern/cycles/render/constant_fold.cpp b/intern/cycles/render/constant_fold.cpp index 200a4c497cd..b7f25663bc3 100644 --- a/intern/cycles/render/constant_fold.cpp +++ b/intern/cycles/render/constant_fold.cpp @@ -89,6 +89,19 @@ void ConstantFolder::make_zero() const } } +void ConstantFolder::make_one() const +{ + if(output->type() == SocketType::FLOAT) { + make_constant(1.0f); + } + else if(SocketType::is_float3(output->type())) { + make_constant(make_float3(1.0f, 1.0f, 1.0f)); + } + else { + assert(0); + } +} + void ConstantFolder::bypass(ShaderOutput *new_output) const { assert(new_output); @@ -321,6 +334,15 @@ void ConstantFolder::fold_math(NodeMath type, bool clamp) const make_zero(); } break; + case NODE_MATH_POWER: + /* 1 ^ X == X ^ 0 == 1 */ + if(is_one(value1_in) || is_zero(value2_in)) { + make_one(); + } + /* X ^ 1 == X */ + else if(is_one(value2_in)) { + try_bypass_or_make_constant(value1_in, clamp); + } default: break; } diff --git a/intern/cycles/render/constant_fold.h b/intern/cycles/render/constant_fold.h index 2b31c2a5887..7962698319f 100644 --- a/intern/cycles/render/constant_fold.h +++ b/intern/cycles/render/constant_fold.h @@ -43,6 +43,7 @@ public: void make_constant_clamp(float value, bool clamp) const; void make_constant_clamp(float3 value, bool clamp) const; void make_zero() const; + void make_one() const; /* Bypass node, relinking to another output socket. */ void bypass(ShaderOutput *output) const; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index df43863ea7a..7ea52b28b9c 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -3896,6 +3896,19 @@ void GammaNode::constant_fold(const ConstantFolder& folder) if(folder.all_inputs_constant()) { folder.make_constant(svm_math_gamma_color(color, gamma)); } + else { + ShaderInput *color_in = input("Color"); + ShaderInput *gamma_in = input("Gamma"); + + /* 1 ^ X == X ^ 0 == 1 */ + if(folder.is_one(color_in) || folder.is_zero(gamma_in)) { + folder.make_one(); + } + /* X ^ 1 == X */ + else if(folder.is_one(gamma_in)) { + folder.try_bypass_or_make_constant(color_in, false); + } + } } void GammaNode::compile(SVMCompiler& compiler) diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp index 60e41be16aa..6f1c0b88b51 100644 --- a/intern/cycles/test/render_graph_finalize_test.cpp +++ b/intern/cycles/test/render_graph_finalize_test.cpp @@ -931,6 +931,72 @@ TEST(render_graph, constant_fold_gamma) } /* + * Tests: Gamma with one constant 0 input. + */ +TEST(render_graph, constant_fold_gamma_part_0) +{ + DEFINE_COMMON_VARIABLES(builder, log); + + EXPECT_ANY_MESSAGE(log); + INVALID_INFO_MESSAGE(log, "Folding Gamma_Cx::"); + CORRECT_INFO_MESSAGE(log, "Folding Gamma_xC::Color to constant (1, 1, 1)."); + + builder + .add_attribute("Attribute") + /* constant on the left */ + .add_node(ShaderNodeBuilder<GammaNode>("Gamma_Cx") + .set("Color", make_float3(0.0f, 0.0f, 0.0f))) + .add_connection("Attribute::Fac", "Gamma_Cx::Gamma") + /* constant on the right */ + .add_node(ShaderNodeBuilder<GammaNode>("Gamma_xC") + .set("Gamma", 0.0f)) + .add_connection("Attribute::Color", "Gamma_xC::Color") + /* output sum */ + .add_node(ShaderNodeBuilder<MixNode>("Out") + .set(&MixNode::type, NODE_MIX_ADD) + .set(&MixNode::use_clamp, true) + .set("Fac", 1.0f)) + .add_connection("Gamma_Cx::Color", "Out::Color1") + .add_connection("Gamma_xC::Color", "Out::Color2") + .output_color("Out::Color"); + + graph.finalize(&scene); +} + +/* + * Tests: Gamma with one constant 1 input. + */ +TEST(render_graph, constant_fold_gamma_part_1) +{ + DEFINE_COMMON_VARIABLES(builder, log); + + EXPECT_ANY_MESSAGE(log); + CORRECT_INFO_MESSAGE(log, "Folding Gamma_Cx::Color to constant (1, 1, 1)."); + CORRECT_INFO_MESSAGE(log, "Folding Gamma_xC::Color to socket Attribute::Color."); + + builder + .add_attribute("Attribute") + /* constant on the left */ + .add_node(ShaderNodeBuilder<GammaNode>("Gamma_Cx") + .set("Color", make_float3(1.0f, 1.0f, 1.0f))) + .add_connection("Attribute::Fac", "Gamma_Cx::Gamma") + /* constant on the right */ + .add_node(ShaderNodeBuilder<GammaNode>("Gamma_xC") + .set("Gamma", 1.0f)) + .add_connection("Attribute::Color", "Gamma_xC::Color") + /* output sum */ + .add_node(ShaderNodeBuilder<MixNode>("Out") + .set(&MixNode::type, NODE_MIX_ADD) + .set(&MixNode::use_clamp, true) + .set("Fac", 1.0f)) + .add_connection("Gamma_Cx::Color", "Out::Color1") + .add_connection("Gamma_xC::Color", "Out::Color2") + .output_color("Out::Color"); + + graph.finalize(&scene); +} + +/* * Tests: BrightnessContrast with all constant inputs. */ TEST(render_graph, constant_fold_bright_contrast) @@ -1143,6 +1209,40 @@ TEST(render_graph, constant_fold_part_math_div_0) } /* + * Tests: partial folding for Math Power with known 0. + */ +TEST(render_graph, constant_fold_part_math_pow_0) +{ + DEFINE_COMMON_VARIABLES(builder, log); + + EXPECT_ANY_MESSAGE(log); + /* X ^ 0 == 1 */ + INVALID_INFO_MESSAGE(log, "Folding Math_Cx::"); + CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to constant (1)."); + INVALID_INFO_MESSAGE(log, "Folding Out::"); + + build_math_partial_test_graph(builder, NODE_MATH_POWER, 0.0f); + graph.finalize(&scene); +} + +/* + * Tests: partial folding for Math Power with known 1. + */ +TEST(render_graph, constant_fold_part_math_pow_1) +{ + DEFINE_COMMON_VARIABLES(builder, log); + + EXPECT_ANY_MESSAGE(log); + /* 1 ^ X == 1; X ^ 1 == X */ + CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to constant (1)"); + CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac."); + INVALID_INFO_MESSAGE(log, "Folding Out::"); + + build_math_partial_test_graph(builder, NODE_MATH_POWER, 1.0f); + graph.finalize(&scene); +} + +/* * Tests: Vector Math with all constant inputs. */ TEST(render_graph, constant_fold_vector_math) |