Cycles: Optimization for black world backgrounds
authorThomas Dinges <blender@dingto.org>
Wed, 21 Jan 2015 19:06:53 +0000 (20:06 +0100)
committerThomas Dinges <blender@dingto.org>
Wed, 21 Jan 2015 19:16:18 +0000 (20:16 +0100)
* If a Background node is set to a black color or zero strength,
it now gets removed from the shader graph.

* In case the graph is empty (no background node), the kernel will skip
evaluating it and save some rendertime. This can help quite a bit in scenes,
where the majority of the image consists of a black background.

Example: http://www.pasteall.org/pic/show.php?id=82650
In this case the render is ~16% faster.

Differential Revision: https://developer.blender.org/D972

intern/cycles/render/background.cpp
intern/cycles/render/graph.cpp
intern/cycles/render/graph.h
intern/cycles/render/nodes.cpp

index d731b3346fe18e361fb9b7485873884411bbe2a0..f5e51f2e159fc5487c55a7a818e6fb369e465814 100644 (file)
@@ -72,16 +72,23 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene
        else
                kbackground->volume_shader = SHADER_NONE;
 
-       if(!(visibility & PATH_RAY_DIFFUSE))
-               kbackground->surface_shader |= SHADER_EXCLUDE_DIFFUSE;
-       if(!(visibility & PATH_RAY_GLOSSY))
-               kbackground->surface_shader |= SHADER_EXCLUDE_GLOSSY;
-       if(!(visibility & PATH_RAY_TRANSMIT))
-               kbackground->surface_shader |= SHADER_EXCLUDE_TRANSMIT;
-       if(!(visibility & PATH_RAY_VOLUME_SCATTER))
-               kbackground->surface_shader |= SHADER_EXCLUDE_SCATTER;
-       if(!(visibility & PATH_RAY_CAMERA))
-               kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA;
+       /* No background node, make world shader invisible to all rays, to skip evaluation in kernel. */
+       if(scene->shaders[shader]->graph->nodes.size() <= 1) {
+               kbackground->surface_shader |= SHADER_EXCLUDE_ANY;
+       }
+       /* Background present, check visibilities */
+       else {
+               if(!(visibility & PATH_RAY_DIFFUSE))
+                       kbackground->surface_shader |= SHADER_EXCLUDE_DIFFUSE;
+               if(!(visibility & PATH_RAY_GLOSSY))
+                       kbackground->surface_shader |= SHADER_EXCLUDE_GLOSSY;
+               if(!(visibility & PATH_RAY_TRANSMIT))
+                       kbackground->surface_shader |= SHADER_EXCLUDE_TRANSMIT;
+               if(!(visibility & PATH_RAY_VOLUME_SCATTER))
+                       kbackground->surface_shader |= SHADER_EXCLUDE_SCATTER;
+               if(!(visibility & PATH_RAY_CAMERA))
+                       kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA;
+       }
 
        need_update = false;
 }
index 8f8a69373dafa23c1a59e2b063d7a734885714c3..84fe55b69ddb7d40d4cc450126e228402e098a1b 100644 (file)
@@ -374,6 +374,28 @@ void ShaderGraph::remove_unneeded_nodes()
                        removed[proxy->id] = true;
                        any_node_removed = true;
                }
+               else if(node->special_type == SHADER_SPECIAL_TYPE_BACKGROUND) {
+                       BackgroundNode *bg = static_cast<BackgroundNode*>(node);
+
+                       if(bg->outputs[0]->links.size()) {
+                               /* Black color or zero strength, remove node */
+                               if((!bg->inputs[0]->link && bg->inputs[0]->value == make_float3(0.0f, 0.0f, 0.0f)) ||
+                                  (!bg->inputs[1]->link && bg->inputs[1]->value.x == 0.0f)) {
+                                       vector<ShaderInput*> inputs = bg->outputs[0]->links;
+
+                                       foreach(ShaderInput *sock, bg->inputs) {
+                                               if(sock->link)
+                                                       disconnect(sock);
+                                       }
+
+                                       foreach(ShaderInput *input, inputs)
+                                               disconnect(input);
+
+                                       removed[bg->id] = true;
+                                       any_node_removed = true;
+                               }
+                       }
+               }
                else if(node->special_type == SHADER_SPECIAL_TYPE_MIX_CLOSURE) {
                        MixClosureNode *mix = static_cast<MixClosureNode*>(node);
 
index 9130f7f04a0e603137f1c799972815370199dcc3..f9ac16787e66fc23c63eba270c4c130aa7612dab 100644 (file)
@@ -79,7 +79,8 @@ enum ShaderNodeSpecialType {
        SHADER_SPECIAL_TYPE_MIX_RGB, /* Only Mix subtype */
        SHADER_SPECIAL_TYPE_AUTOCONVERT,
        SHADER_SPECIAL_TYPE_GEOMETRY,
-       SHADER_SPECIAL_TYPE_SCRIPT
+       SHADER_SPECIAL_TYPE_SCRIPT,
+       SHADER_SPECIAL_TYPE_BACKGROUND,
 };
 
 /* Enum
index 625b829ba2432697fea81664b57b9eda115de98f..653bd5dd19c2c870fb8940b550907d184c613f23 100644 (file)
@@ -1946,6 +1946,8 @@ void EmissionNode::compile(OSLCompiler& compiler)
 BackgroundNode::BackgroundNode()
 : ShaderNode("background")
 {
+       special_type = SHADER_SPECIAL_TYPE_BACKGROUND;
+
        add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
        add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
        add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);