Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Stockner <lukas.stockner@freenet.de>2017-05-03 01:21:18 +0300
committerLukas Stockner <lukas.stockner@freenet.de>2017-05-03 17:44:52 +0300
commit4cf7fc3b3a4d032f0c0db632a46d40806e906cf1 (patch)
tree511e87033628608dd235ed352a007df4474234fa /source/blender/nodes
parent6bf4115c13962c99d1cdc97f2be92c4922f3fd33 (diff)
Render API/Cycles: Identify Render Passes by their name instead of a type flag
Previously, every RenderPass would have a bitfield that specified its type. That limits the number of passes to 32, which was reached a while ago. However, most of the code already supported arbitrary RenderPasses since they were also used to store Multilayer EXR images. Therefore, this commit completely removes the passflag from RenderPass and changes all code to use the unique pass name for identification. Since Blender Internal relies on hardcoded passes and to preserve compatibility, 32 pass names are reserved for the old hardcoded passes. To support these arbitrary passes, the Render Result compositor node now adds dynamic sockets. For compatibility, the old hardcoded sockets are always stored and just hidden when the corresponding pass isn't available. To use these changes, the Render Engine API now includes a function that allows render engines to add arbitrary passes to the render result. To be able to add options for these passes, addons can now add their own properties to SceneRenderLayers. To keep the compositor input node updated, render engine plugins have to implement a callback that registers all the passes that will be generated. From a user perspective, nothing should change with this commit. Differential Revision: https://developer.blender.org/D2443 Differential Revision: https://developer.blender.org/D2444
Diffstat (limited to 'source/blender/nodes')
-rw-r--r--source/blender/nodes/CMakeLists.txt4
-rw-r--r--source/blender/nodes/NOD_composite.h4
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c35
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c544
4 files changed, 269 insertions, 318 deletions
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 3596a2aa12d..c5a3c70100b 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -289,8 +289,4 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
-if(WITH_CYCLES AND WITH_CYCLES_DEBUG)
- add_definitions(-DWITH_CYCLES_DEBUG)
-endif()
-
blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index 0215db1dd55..a5c2e604f46 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -139,6 +139,8 @@ void register_node_type_cmp_trackpos(void);
void register_node_type_cmp_planetrackdeform(void);
void register_node_type_cmp_cornerpin(void);
-void node_cmp_rlayers_force_hidden_passes(struct bNode *node);
+void node_cmp_rlayers_outputs(struct bNodeTree *ntree, struct bNode *node);
+void node_cmp_rlayers_register_pass(struct bNodeTree *ntree, struct bNode *node, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type);
+const char *node_cmp_rlayers_sock_to_pass(int sock_index);
#endif
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index cb565bd5491..36778a18f77 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -240,8 +240,15 @@ void ntreeCompositExecTree(Scene *scene, bNodeTree *ntree, RenderData *rd, int r
/* *********************************************** */
-/* based on rules, force sockets hidden always */
-void ntreeCompositForceHidden(bNodeTree *ntree)
+/* Update the outputs of the render layer nodes.
+ * Since the outputs depend on the render engine, this part is a bit complex:
+ * - ntreeCompositUpdateRLayers is called and loops over all render layer nodes
+ * - Each render layer node calls the update function of the render engine that's used for its scene
+ * - The render engine calls RE_engine_register_pass for each pass
+ * - RE_engine_register_pass calls ntreeCompositRegisterPass,
+ * which calls node_cmp_rlayers_register_pass for every render layer node
+ */
+void ntreeCompositUpdateRLayers(bNodeTree *ntree)
{
bNode *node;
@@ -249,16 +256,20 @@ void ntreeCompositForceHidden(bNodeTree *ntree)
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == CMP_NODE_R_LAYERS)
- node_cmp_rlayers_force_hidden_passes(node);
-
- /* XXX this stuff is called all the time, don't want that.
- * Updates should only happen when actually necessary.
- */
-#if 0
- else if (node->type == CMP_NODE_IMAGE) {
- nodeUpdate(ntree, node);
- }
-#endif
+ node_cmp_rlayers_outputs(ntree, node);
+ }
+
+}
+
+void ntreeCompositRegisterPass(bNodeTree *ntree, Scene *scene, SceneRenderLayer *srl, const char *name, int type)
+{
+ bNode *node;
+
+ if (ntree == NULL) return;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_R_LAYERS)
+ node_cmp_rlayers_register_pass(ntree, node, scene, srl, name, type);
}
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index 4f02c106569..510e24554f0 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -32,192 +32,104 @@
#include "node_composite_util.h"
#include "BLI_utildefines.h"
+#include "BLI_linklist.h"
#include "DNA_scene_types.h"
+#include "RE_engine.h"
+
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
-#ifdef WITH_CYCLES_DEBUG
-# include "RE_pipeline.h"
-#endif
-
/* **************** IMAGE (and RenderResult, multilayer image) ******************** */
static bNodeSocketTemplate cmp_node_rlayers_out[] = {
- { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("Z"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_VECTOR, 0, N_("UV"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_VECTOR, 0, N_("Speed"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Diffuse"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Specular"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Shadow"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("AO"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Reflect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Refract"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("IndexOB"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("IndexMA"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("Mist"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Emit"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Environment"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Diffuse Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Diffuse Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Diffuse Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Glossy Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Glossy Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Glossy Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Transmission Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Transmission Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Transmission Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Subsurface Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Subsurface Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Subsurface Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
-#ifdef WITH_CYCLES_DEBUG
- { SOCK_RGBA, 0, N_("Debug"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
-#endif
+ { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_(RE_PASSNAME_Z), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, N_(RE_PASSNAME_NORMAL), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, N_(RE_PASSNAME_UV), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, N_(RE_PASSNAME_VECTOR), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_RGBA), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_SPEC), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_SHADOW), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_AO), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_REFLECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_REFRACT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_(RE_PASSNAME_INDEXOB), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_(RE_PASSNAME_INDEXMA), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_(RE_PASSNAME_MIST), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_EMIT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_ENVIRONMENT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
-static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNode *node, int pass, int rres_index)
+static void cmp_node_image_add_pass_output(bNodeTree *ntree, bNode *node,
+ const char *name, const char *passname,
+ int rres_index, int type, int is_rlayers,
+ LinkNodePair *available_sockets, int *prev_index)
{
bNodeSocket *sock;
- NodeImageLayer *sockdata;
-
- sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT);
- /* extra socket info */
- sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
- sock->storage = sockdata;
-
- sockdata->pass_flag = pass;
-
- return sock;
-}
-
-static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node, int passflag)
-{
- if (passflag & SCE_PASS_COMBINED) {
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_IMAGE);
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_ALPHA);
- }
-
- if (passflag & SCE_PASS_Z)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_Z, RRES_OUT_Z);
- if (passflag & SCE_PASS_NORMAL)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_NORMAL, RRES_OUT_NORMAL);
- if (passflag & SCE_PASS_VECTOR)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_VECTOR, RRES_OUT_VEC);
- if (passflag & SCE_PASS_UV)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_UV, RRES_OUT_UV);
- if (passflag & SCE_PASS_RGBA)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_RGBA, RRES_OUT_RGBA);
- if (passflag & SCE_PASS_DIFFUSE)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE, RRES_OUT_DIFF);
- if (passflag & SCE_PASS_SPEC)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SPEC, RRES_OUT_SPEC);
- if (passflag & SCE_PASS_SHADOW)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SHADOW, RRES_OUT_SHADOW);
- if (passflag & SCE_PASS_AO)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_AO, RRES_OUT_AO);
- if (passflag & SCE_PASS_REFLECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFLECT, RRES_OUT_REFLECT);
- if (passflag & SCE_PASS_REFRACT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFRACT, RRES_OUT_REFRACT);
- if (passflag & SCE_PASS_INDIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDIRECT, RRES_OUT_INDIRECT);
- if (passflag & SCE_PASS_INDEXOB)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXOB, RRES_OUT_INDEXOB);
- if (passflag & SCE_PASS_INDEXMA)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXMA, RRES_OUT_INDEXMA);
- if (passflag & SCE_PASS_MIST)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_MIST, RRES_OUT_MIST);
- if (passflag & SCE_PASS_EMIT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_EMIT, RRES_OUT_EMIT);
- if (passflag & SCE_PASS_ENVIRONMENT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_ENVIRONMENT, RRES_OUT_ENV);
-
- if (passflag & SCE_PASS_DIFFUSE_DIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_DIRECT, RRES_OUT_DIFF_DIRECT);
- if (passflag & SCE_PASS_DIFFUSE_INDIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_INDIRECT, RRES_OUT_DIFF_INDIRECT);
- if (passflag & SCE_PASS_DIFFUSE_COLOR)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_COLOR, RRES_OUT_DIFF_COLOR);
-
- if (passflag & SCE_PASS_GLOSSY_DIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_DIRECT, RRES_OUT_GLOSSY_DIRECT);
- if (passflag & SCE_PASS_GLOSSY_INDIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_INDIRECT, RRES_OUT_GLOSSY_INDIRECT);
- if (passflag & SCE_PASS_GLOSSY_COLOR)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_COLOR, RRES_OUT_GLOSSY_COLOR);
-
- if (passflag & SCE_PASS_TRANSM_DIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_DIRECT, RRES_OUT_TRANSM_DIRECT);
- if (passflag & SCE_PASS_TRANSM_INDIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_INDIRECT, RRES_OUT_TRANSM_INDIRECT);
- if (passflag & SCE_PASS_TRANSM_COLOR)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_COLOR, RRES_OUT_TRANSM_COLOR);
-
- if (passflag & SCE_PASS_SUBSURFACE_DIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_DIRECT, RRES_OUT_SUBSURFACE_DIRECT);
- if (passflag & SCE_PASS_SUBSURFACE_INDIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_INDIRECT, RRES_OUT_SUBSURFACE_INDIRECT);
- if (passflag & SCE_PASS_SUBSURFACE_COLOR)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_COLOR, RRES_OUT_SUBSURFACE_COLOR);
-
-#ifdef WITH_CYCLES_DEBUG
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DEBUG, RRES_OUT_DEBUG);
-#endif
-}
-
-static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl)
-{
- bNodeSocket *sock;
- NodeImageLayer *sockdata;
- RenderPass *rpass;
- int index;
- int passflag = 0;
- for (rpass = rl->passes.first, index = 0; rpass; rpass = rpass->next, ++index) {
- int type;
- if (rpass->channels == 1)
- type = SOCK_FLOAT;
- else
- type = SOCK_RGBA;
-
- /* we only need one socket per type */
- if (passflag & rpass->passtype)
- continue;
-
- passflag |= rpass->passtype;
-
- sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->internal_name, rpass->internal_name);
+ int sock_index = BLI_findstringindex(&node->outputs, name, offsetof(bNodeSocket, name));
+
+ if (sock_index < 0) {
+ /* The first 31 sockets always are the legacy hardcoded sockets.
+ * Any dynamically allocated sockets follow afterwards, and are sorted in the order in which they were stored in the RenderResult.
+ * Therefore, we remember the index of the last matched socket. New sockets are placed behind the previously traversed one, but always after the first 31. */
+ int after_index = *prev_index;
+ if (is_rlayers && after_index < 30)
+ after_index = 30;
+
+ if (rres_index >= 0) {
+ sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT);
+ }
+ else {
+ sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, name, name);
+ }
/* extra socket info */
- sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
+ NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
sock->storage = sockdata;
-
- sockdata->pass_index = index;
- sockdata->pass_flag = rpass->passtype;
-
- if (rpass->passtype == SCE_PASS_COMBINED) {
- sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_FLOAT, PROP_NONE, "Alpha", "Alpha");
- sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
- sock->storage = sockdata;
- sockdata->pass_index = index;
- sockdata->pass_flag = rpass->passtype;
+
+ BLI_strncpy(sockdata->pass_name, passname, sizeof(sockdata->pass_name));
+
+ sock_index = BLI_listbase_count(&node->outputs)-1;
+ if (sock_index != after_index+1) {
+ bNodeSocket *after_sock = BLI_findlink(&node->outputs, after_index);
+ BLI_remlink(&node->outputs, sock);
+ BLI_insertlinkafter(&node->outputs, after_sock, sock);
}
}
+ else {
+ sock = BLI_findlink(&node->outputs, sock_index);
+ }
+
+ BLI_linklist_append(available_sockets, sock);
+ *prev_index = sock_index;
}
-static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
+static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets)
{
Image *ima = (Image *)node->id;
+ ImBuf *ibuf;
+ int prev_index = -1;
if (ima) {
ImageUser *iuser = node->storage;
ImageUser load_iuser = {NULL};
- ImBuf *ibuf;
int offset = BKE_image_sequence_guess_offset(ima);
/* It is possible that image user in this node is not
@@ -238,104 +150,150 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
RenderLayer *rl = BLI_findlink(&ima->rr->layers, iuser->layer);
if (rl) {
- if (ima->type != IMA_TYPE_MULTILAYER)
- cmp_node_image_add_render_pass_outputs(ntree, node, rl->passflag);
- else
- cmp_node_image_add_multilayer_outputs(ntree, node, rl);
+ RenderPass *rpass;
+ for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
+ int type;
+ if (rpass->channels == 1)
+ type = SOCK_FLOAT;
+ else
+ type = SOCK_RGBA;
+
+ /* Special handling for the Combined pass to ensure compatibility. */
+ if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
+ cmp_node_image_add_pass_output(ntree, node, "Image", rpass->name, -1, type, false, available_sockets, &prev_index);
+ cmp_node_image_add_pass_output(ntree, node, "Alpha", rpass->name, -1, SOCK_FLOAT, false, available_sockets, &prev_index);
+ }
+ else {
+ cmp_node_image_add_pass_output(ntree, node, rpass->name, rpass->name, -1, type, false, available_sockets, &prev_index);
+ }
+ }
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return;
}
- else
- cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA);
}
- else
- cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA | RRES_OUT_Z);
-
+ }
+
+ cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, RRES_OUT_IMAGE, SOCK_RGBA, false, available_sockets, &prev_index);
+ cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, RRES_OUT_ALPHA, SOCK_FLOAT, false, available_sockets, &prev_index);
+
+ if (ima) {
+ if (!ima->rr) {
+ cmp_node_image_add_pass_output(ntree, node, RE_PASSNAME_Z, RE_PASSNAME_Z, RRES_OUT_Z, SOCK_FLOAT, false, available_sockets, &prev_index);
+ }
BKE_image_release_ibuf(ima, ibuf, NULL);
}
- else
- cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA);
}
-static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeSocket *newsock, ListBase *oldsocklist)
-{
- bNodeSocket *sock;
-
- for (sock = oldsocklist->first; sock; sock = sock->next)
- if (STREQ(sock->name, newsock->name))
- return sock;
- return NULL;
-}
+typedef struct RLayerUpdateData {
+ LinkNodePair *available_sockets;
+ int prev_index;
+} RLayerUpdateData;
-static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex)
+void node_cmp_rlayers_register_pass(bNodeTree *ntree, bNode *node, Scene *scene, SceneRenderLayer *srl, const char *name, int type)
{
- bNodeSocket *sock;
-
- /* first try to find matching socket name */
- for (sock = node->outputs.first; sock; sock = sock->next)
- if (STREQ(sock->name, oldsock->name))
- return sock;
-
- /* no matching name, simply link to same index */
- return BLI_findlink(&node->outputs, oldindex);
+ RLayerUpdateData *data = node->storage;
+
+ if (scene == NULL || srl == NULL || data == NULL || node->id != scene) {
+ return;
+ }
+
+ SceneRenderLayer *node_srl = BLI_findlink(&scene->r.layers, node->custom1);
+ if (node_srl != srl) {
+ return;
+ }
+
+ /* Special handling for the Combined pass to ensure compatibility. */
+ if (STREQ(name, RE_PASSNAME_COMBINED)) {
+ cmp_node_image_add_pass_output(ntree, node, "Image", name, -1, type, true, data->available_sockets, &data->prev_index);
+ cmp_node_image_add_pass_output(ntree, node, "Alpha", name, -1, SOCK_FLOAT, true, data->available_sockets, &data->prev_index);
+ }
+ else {
+ cmp_node_image_add_pass_output(ntree, node, name, name, -1, type, true, data->available_sockets, &data->prev_index);
+ }
}
-static void cmp_node_image_sync_output(bNode *UNUSED(node), bNodeSocket *UNUSED(newsock), bNodeSocket *UNUSED(oldsock))
+static void cmp_node_rlayer_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets)
{
- /* pass */
+ Scene *scene = (Scene *)node->id;
+
+ if (scene) {
+ RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
+ if(engine_type && engine_type->update_render_passes) {
+ SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, node->custom1);
+ if(srl) {
+ RLayerUpdateData *data = MEM_mallocN(sizeof(RLayerUpdateData), "render layer update data");
+ data->available_sockets = available_sockets;
+ data->prev_index = -1;
+ node->storage = data;
+
+ RenderEngine *engine = RE_engine_create(engine_type);
+ engine_type->update_render_passes(engine, scene, srl);
+ RE_engine_free(engine);
+
+ MEM_freeN(data);
+ node->storage = NULL;
+
+ return;
+ }
+ }
+ }
+
+ int prev_index = -1;
+ cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, RRES_OUT_IMAGE, SOCK_RGBA, true, available_sockets, &prev_index);
+ cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, RRES_OUT_ALPHA, SOCK_FLOAT, true, available_sockets, &prev_index);
}
/* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */
-static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node)
+static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rlayer)
{
- bNodeSocket *newsock, *oldsock, *oldsock_next;
- ListBase oldsocklist;
- int oldindex;
- bNodeLink *link;
-
- /* store current nodes in oldsocklist, then clear socket list */
- oldsocklist = node->outputs;
- BLI_listbase_clear(&node->outputs);
+ bNodeSocket *sock, *sock_next;
+ LinkNodePair available_sockets = {NULL, NULL};
+ int sock_index;
/* XXX make callback */
- cmp_node_image_create_outputs(ntree, node);
-
- for (newsock = node->outputs.first; newsock; newsock = newsock->next) {
- /* XXX make callback */
- oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist);
- if (oldsock) {
- /* XXX make callback */
- cmp_node_image_sync_output(node, newsock, oldsock);
+ if (rlayer)
+ cmp_node_rlayer_create_outputs(ntree, node, &available_sockets);
+ else
+ cmp_node_image_create_outputs(ntree, node, &available_sockets);
+
+ /* Get rid of sockets whose passes are not available in the image.
+ * If sockets that are not available would be deleted, the connections to them would be lost
+ * when e.g. opening a file (since there's no render at all yet).
+ * Therefore, sockets with connected links will just be set as unavailable.
+ *
+ * Another important detail comes from compatibility with the older socket model, where there
+ * was a fixed socket per pass type that was just hidden or not. Therefore, older versions expect
+ * the first 31 passes to belong to a specific pass type.
+ * So, we keep those 31 always allocated before the others as well, even if they have no links attached. */
+ sock_index = 0;
+ for (sock = node->outputs.first; sock; sock = sock_next, sock_index++) {
+ sock_next = sock->next;
+ if (BLI_linklist_index(available_sockets.list, sock) >= 0) {
+ sock->flag &= ~(SOCK_UNAVAIL | SOCK_HIDDEN);
}
- }
-
- /* move links to new socket */
- for (oldsock = oldsocklist.first, oldindex = 0; oldsock; oldsock = oldsock->next, ++oldindex) {
- newsock = cmp_node_image_output_relink(node, oldsock, oldindex);
-
- if (newsock) {
+ else {
+ bNodeLink *link;
for (link = ntree->links.first; link; link = link->next) {
- if (link->fromsock == oldsock)
- link->fromsock = newsock;
+ if (link->fromsock == sock) break;
+ }
+ if (!link && sock_index > 30) {
+ MEM_freeN(sock->storage);
+ nodeRemoveSocket(ntree, node, sock);
+ }
+ else {
+ sock->flag |= SOCK_UNAVAIL;
}
}
}
-
- /* delete old sockets
- * XXX oldsock is not actually in the node->outputs list any more,
- * but the nodeRemoveSocket function works anyway. In future this
- * should become part of the core code, so can take care of this behavior.
- */
- for (oldsock = oldsocklist.first; oldsock; oldsock = oldsock_next) {
- oldsock_next = oldsock->next;
- MEM_freeN(oldsock->storage);
- nodeRemoveSocket(ntree, node, oldsock);
- }
+
+ BLI_linklist_free(available_sockets.list, NULL);
}
static void cmp_node_image_update(bNodeTree *ntree, bNode *node)
{
/* avoid unnecessary updates, only changes to the image/image user data are of interest */
if (node->update & NODE_UPDATE_ID)
- cmp_node_image_verify_outputs(ntree, node);
+ cmp_node_image_verify_outputs(ntree, node, false);
}
static void node_composit_init_image(bNodeTree *ntree, bNode *node)
@@ -348,7 +306,7 @@ static void node_composit_init_image(bNodeTree *ntree, bNode *node)
iuser->ok = 1;
/* setup initial outputs */
- cmp_node_image_verify_outputs(ntree, node);
+ cmp_node_image_verify_outputs(ntree, node, false);
}
static void node_composit_free_image(bNode *node)
@@ -388,87 +346,45 @@ void register_node_type_cmp_image(void)
/* **************** RENDER RESULT ******************** */
-static void set_output_visible(bNode *node, int passflag, int index, int pass)
+void node_cmp_rlayers_outputs(bNodeTree *ntree, bNode *node)
{
- bNodeSocket *sock = BLI_findlink(&node->outputs, index);
- bool pass_enabled = ((passflag & pass) != 0);
-#ifdef WITH_CYCLES_DEBUG
- pass_enabled |= (pass == SCE_PASS_DEBUG);
-#endif
- /* clear the SOCK_HIDDEN flag as well, in case a socket was hidden before */
- if (pass_enabled)
- sock->flag &= ~(SOCK_HIDDEN | SOCK_UNAVAIL);
- else
- sock->flag |= SOCK_UNAVAIL;
+ cmp_node_image_verify_outputs(ntree, node, true);
}
-/* clumsy checking... should do dynamic outputs once */
-void node_cmp_rlayers_force_hidden_passes(bNode *node)
+const char* node_cmp_rlayers_sock_to_pass(int sock_index)
{
- Scene *scene = (Scene *)node->id;
- SceneRenderLayer *srl;
- int passflag;
- bNodeSocket *sock;
-
- /* must always have valid scene pointer */
- if (!scene)
- return;
-
- srl = BLI_findlink(&scene->r.layers, node->custom1);
- if (!srl)
- return;
-
- passflag = srl->passflag;
-
- for (sock = node->outputs.first; sock; sock = sock->next)
- sock->flag &= ~SOCK_UNAVAIL;
-
- set_output_visible(node, passflag, RRES_OUT_IMAGE, SCE_PASS_COMBINED);
- set_output_visible(node, passflag, RRES_OUT_ALPHA, SCE_PASS_COMBINED);
-
- set_output_visible(node, passflag, RRES_OUT_Z, SCE_PASS_Z);
- set_output_visible(node, passflag, RRES_OUT_NORMAL, SCE_PASS_NORMAL);
- set_output_visible(node, passflag, RRES_OUT_VEC, SCE_PASS_VECTOR);
- set_output_visible(node, passflag, RRES_OUT_UV, SCE_PASS_UV);
- set_output_visible(node, passflag, RRES_OUT_RGBA, SCE_PASS_RGBA);
- set_output_visible(node, passflag, RRES_OUT_DIFF, SCE_PASS_DIFFUSE);
- set_output_visible(node, passflag, RRES_OUT_SPEC, SCE_PASS_SPEC);
- set_output_visible(node, passflag, RRES_OUT_SHADOW, SCE_PASS_SHADOW);
- set_output_visible(node, passflag, RRES_OUT_AO, SCE_PASS_AO);
- set_output_visible(node, passflag, RRES_OUT_REFLECT, SCE_PASS_REFLECT);
- set_output_visible(node, passflag, RRES_OUT_REFRACT, SCE_PASS_REFRACT);
- set_output_visible(node, passflag, RRES_OUT_INDIRECT, SCE_PASS_INDIRECT);
- set_output_visible(node, passflag, RRES_OUT_INDEXOB, SCE_PASS_INDEXOB);
- set_output_visible(node, passflag, RRES_OUT_INDEXMA, SCE_PASS_INDEXMA);
- set_output_visible(node, passflag, RRES_OUT_MIST, SCE_PASS_MIST);
- set_output_visible(node, passflag, RRES_OUT_EMIT, SCE_PASS_EMIT);
- set_output_visible(node, passflag, RRES_OUT_ENV, SCE_PASS_ENVIRONMENT);
- set_output_visible(node, passflag, RRES_OUT_DIFF_DIRECT, SCE_PASS_DIFFUSE_DIRECT);
- set_output_visible(node, passflag, RRES_OUT_DIFF_INDIRECT, SCE_PASS_DIFFUSE_INDIRECT);
- set_output_visible(node, passflag, RRES_OUT_DIFF_COLOR, SCE_PASS_DIFFUSE_COLOR);
- set_output_visible(node, passflag, RRES_OUT_GLOSSY_DIRECT, SCE_PASS_GLOSSY_DIRECT);
- set_output_visible(node, passflag, RRES_OUT_GLOSSY_INDIRECT, SCE_PASS_GLOSSY_INDIRECT);
- set_output_visible(node, passflag, RRES_OUT_GLOSSY_COLOR, SCE_PASS_GLOSSY_COLOR);
- set_output_visible(node, passflag, RRES_OUT_TRANSM_DIRECT, SCE_PASS_TRANSM_DIRECT);
- set_output_visible(node, passflag, RRES_OUT_TRANSM_INDIRECT, SCE_PASS_TRANSM_INDIRECT);
- set_output_visible(node, passflag, RRES_OUT_TRANSM_COLOR, SCE_PASS_TRANSM_COLOR);
- set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_DIRECT, SCE_PASS_SUBSURFACE_DIRECT);
- set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_INDIRECT, SCE_PASS_SUBSURFACE_INDIRECT);
- set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_COLOR, SCE_PASS_SUBSURFACE_COLOR);
-
-#ifdef WITH_CYCLES_DEBUG
- set_output_visible(node, passflag, RRES_OUT_DEBUG, SCE_PASS_DEBUG);
-#endif
+ const char* sock_to_passname[] = {
+ RE_PASSNAME_COMBINED, RE_PASSNAME_COMBINED,
+ RE_PASSNAME_Z, RE_PASSNAME_NORMAL, RE_PASSNAME_UV, RE_PASSNAME_VECTOR, RE_PASSNAME_RGBA,
+ RE_PASSNAME_DIFFUSE, RE_PASSNAME_SPEC, RE_PASSNAME_SHADOW, RE_PASSNAME_AO,
+ RE_PASSNAME_REFLECT, RE_PASSNAME_REFRACT, RE_PASSNAME_INDIRECT,
+ RE_PASSNAME_INDEXOB, RE_PASSNAME_INDEXMA, RE_PASSNAME_MIST, RE_PASSNAME_EMIT, RE_PASSNAME_ENVIRONMENT,
+ RE_PASSNAME_DIFFUSE_DIRECT, RE_PASSNAME_DIFFUSE_INDIRECT, RE_PASSNAME_DIFFUSE_COLOR,
+ RE_PASSNAME_GLOSSY_DIRECT, RE_PASSNAME_GLOSSY_INDIRECT, RE_PASSNAME_GLOSSY_COLOR,
+ RE_PASSNAME_TRANSM_DIRECT, RE_PASSNAME_TRANSM_INDIRECT, RE_PASSNAME_TRANSM_COLOR,
+ RE_PASSNAME_SUBSURFACE_DIRECT, RE_PASSNAME_SUBSURFACE_INDIRECT, RE_PASSNAME_SUBSURFACE_COLOR
+ };
+ if (sock_index > 30) {
+ return NULL;
+ }
+ return sock_to_passname[sock_index];
}
static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
bNode *node = ptr->data;
-
+ int sock_index = 0;
+
node->id = &scene->id;
-
- node_cmp_rlayers_force_hidden_passes(node);
+
+ for (bNodeSocket *sock = node->outputs.first; sock; sock = sock->next, sock_index++)
+ {
+ NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
+ sock->storage = sockdata;
+
+ BLI_strncpy(sockdata->pass_name, node_cmp_rlayers_sock_to_pass(sock_index), sizeof(sockdata->pass_name));
+ }
}
static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree)
@@ -489,6 +405,29 @@ static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree
return false;
}
+static void node_composit_free_rlayers(bNode *node)
+{
+ bNodeSocket *sock;
+
+ /* free extra socket info */
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ MEM_freeN(sock->storage);
+}
+
+static void node_composit_copy_rlayers(bNodeTree *UNUSED(dest_ntree), bNode *UNUSED(dest_node), bNode *src_node)
+{
+ bNodeSocket *sock;
+
+ /* copy extra socket info */
+ for (sock = src_node->outputs.first; sock; sock = sock->next)
+ sock->new_sock->storage = MEM_dupallocN(sock->storage);
+}
+
+static void cmp_node_rlayers_update(bNodeTree *ntree, bNode *node)
+{
+ cmp_node_image_verify_outputs(ntree, node, true);
+}
+
void register_node_type_cmp_rlayers(void)
{
static bNodeType ntype;
@@ -497,6 +436,9 @@ void register_node_type_cmp_rlayers(void)
node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out);
ntype.initfunc_api = node_composit_init_rlayers;
ntype.poll = node_composit_poll_rlayers;
+ node_type_storage(&ntype, NULL, node_composit_free_rlayers, node_composit_copy_rlayers);
+ node_type_update(&ntype, cmp_node_rlayers_update, NULL);
+ node_type_init(&ntype, node_cmp_rlayers_outputs);
nodeRegisterType(&ntype);
}