From 153f14be2b67fba0d3d92eb08eff7659f2dffae7 Mon Sep 17 00:00:00 2001 From: Habib Gahbiche Date: Sun, 3 Dec 2023 23:20:44 +0100 Subject: [PATCH] Compositor: Make split viewer a regular split node Changes: - Renamed Split Viewer Node to Split Node - Split Node is now under `Utilities` (similar to Switch node) - Versioning: split viewer from 4.0 and before is replaced with the new split node connected to a new viewer node. Pull Request: https://projects.blender.org/blender/blender/pulls/114245 --- .../startup/bl_ui/node_add_menu_compositor.py | 2 +- source/blender/blenkernel/BKE_node.h | 4 +- source/blender/blenkernel/intern/node.cc | 7 +- .../blenloader/intern/versioning_260.cc | 2 +- .../blenloader/intern/versioning_400.cc | 34 ++++ .../blenloader/intern/versioning_legacy.cc | 2 +- source/blender/compositor/CMakeLists.txt | 4 +- .../compositor/intern/COM_Converter.cc | 6 +- .../blender/compositor/nodes/COM_SplitNode.cc | 33 ++++ ...{COM_SplitViewerNode.h => COM_SplitNode.h} | 6 +- .../compositor/nodes/COM_SplitViewerNode.cc | 63 -------- .../operations/COM_SplitOperation.cc | 2 + .../realtime_compositor/CMakeLists.txt | 4 +- .../realtime_compositor/intern/scheduler.cc | 10 +- ...plit_viewer.glsl => compositor_split.glsl} | 7 +- ...iewer_info.hh => compositor_split_info.hh} | 14 +- .../editors/space_image/image_buttons.cc | 2 +- .../blender/editors/space_node/node_edit.cc | 6 +- .../blender/editors/space_node/node_gizmo.cc | 2 +- .../editors/space_node/node_relationships.cc | 2 +- source/blender/makesdna/DNA_node_types.h | 10 +- .../blender/makesrna/intern/rna_nodetree.cc | 2 +- source/blender/nodes/NOD_static_types.h | 2 +- source/blender/nodes/composite/CMakeLists.txt | 2 +- .../composite/node_composite_register.cc | 2 +- .../composite/node_composite_register.hh | 2 +- .../nodes/composite/node_composite_tree.cc | 4 +- .../composite/nodes/node_composite_split.cc | 123 ++++++++++++++ .../nodes/node_composite_split_viewer.cc | 150 ------------------ 29 files changed, 240 insertions(+), 269 deletions(-) create mode 100644 source/blender/compositor/nodes/COM_SplitNode.cc rename source/blender/compositor/nodes/{COM_SplitViewerNode.h => COM_SplitNode.h} (79%) delete mode 100644 source/blender/compositor/nodes/COM_SplitViewerNode.cc rename source/blender/compositor/realtime_compositor/shaders/{compositor_split_viewer.glsl => compositor_split.glsl} (68%) rename source/blender/compositor/realtime_compositor/shaders/infos/{compositor_split_viewer_info.hh => compositor_split_info.hh} (55%) create mode 100644 source/blender/nodes/composite/nodes/node_composite_split.cc delete mode 100644 source/blender/nodes/composite/nodes/node_composite_split_viewer.cc diff --git a/scripts/startup/bl_ui/node_add_menu_compositor.py b/scripts/startup/bl_ui/node_add_menu_compositor.py index 28ff54992bd..44089d92566 100644 --- a/scripts/startup/bl_ui/node_add_menu_compositor.py +++ b/scripts/startup/bl_ui/node_add_menu_compositor.py @@ -71,7 +71,6 @@ class NODE_MT_category_compositor_output(Menu): layout = self.layout node_add_menu.add_node_type(layout, "CompositorNodeComposite") - node_add_menu.add_node_type(layout, "CompositorNodeSplitViewer") node_add_menu.add_node_type(layout, "CompositorNodeViewer") layout.separator() node_add_menu.add_node_type(layout, "CompositorNodeOutputFile") @@ -279,6 +278,7 @@ class NODE_MT_category_compositor_utilities(Menu): node_add_menu.add_node_type(layout, "CompositorNodeLevels") node_add_menu.add_node_type(layout, "CompositorNodeNormalize") layout.separator() + node_add_menu.add_node_type(layout, "CompositorNodeSplit") node_add_menu.add_node_type(layout, "CompositorNodeSwitch") node_add_menu.add_node_type( layout, "CompositorNodeSwitchView", diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index e7b62f3d43b..20f379556a1 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1017,7 +1017,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i #define CMP_NODE_CHROMA_MATTE 237 #define CMP_NODE_CHANNEL_MATTE 238 #define CMP_NODE_FLIP 239 -#define CMP_NODE_SPLITVIEWER 240 +/* Split viewer node is now a regular split node: CMP_NODE_SPLIT. */ +#define CMP_NODE_SPLITVIEWER__DEPRECATED 240 // #define CMP_NODE_INDEX_MASK 241 #define CMP_NODE_MAP_UV 242 #define CMP_NODE_ID_MASK 243 @@ -1054,6 +1055,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i #define CMP_NODE_DESPECKLE 273 #define CMP_NODE_ANTIALIASING 274 #define CMP_NODE_KUWAHARA 275 +#define CMP_NODE_SPLIT 276 #define CMP_NODE_GLARE 301 #define CMP_NODE_TONEMAP 302 diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index bf7f733a6ad..6c73a12ebb1 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -993,8 +993,7 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree) } case CMP_NODE_IMAGE: case CMP_NODE_R_LAYERS: - case CMP_NODE_VIEWER: - case CMP_NODE_SPLITVIEWER: { + case CMP_NODE_VIEWER: { ImageUser *iuser = static_cast(node->storage); iuser->scene = nullptr; break; @@ -3458,7 +3457,7 @@ void ntreeSetOutput(bNodeTree *ntree) if (ELEM(node->type, CMP_NODE_OUTPUT_FILE, GEO_NODE_VIEWER)) { continue; } - const bool node_is_output = ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER); + const bool node_is_output = node->type == CMP_NODE_VIEWER; int output = 0; /* there is more types having output class, each one is checked */ @@ -3469,7 +3468,7 @@ void ntreeSetOutput(bNodeTree *ntree) } /* same type, exception for viewer */ - const bool tnode_is_output = ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER); + const bool tnode_is_output = tnode->type == CMP_NODE_VIEWER; const bool compositor_case = is_compositor && tnode_is_output && node_is_output; if (tnode->type == node->type || compositor_case) { if (tnode->flag & NODE_DO_OUTPUT) { diff --git a/source/blender/blenloader/intern/versioning_260.cc b/source/blender/blenloader/intern/versioning_260.cc index d7306e8ccf0..5a946711597 100644 --- a/source/blender/blenloader/intern/versioning_260.cc +++ b/source/blender/blenloader/intern/versioning_260.cc @@ -708,7 +708,7 @@ static const char *node_get_static_idname(int type, int treetype) return "CompositorNodeChannelMatte"; case CMP_NODE_FLIP: return "CompositorNodeFlip"; - case CMP_NODE_SPLITVIEWER: + case CMP_NODE_SPLITVIEWER__DEPRECATED: return "CompositorNodeSplitViewer"; case CMP_NODE_MAP_UV: return "CompositorNodeMapUV"; diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 78bd7dcd2ea..6c70fab0686 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -325,6 +325,33 @@ static void versioning_eevee_shadow_settings(Object *object) SET_FLAG_FROM_TEST(object->visibility_flag, hide_shadows, OB_HIDE_SHADOW); } +static void versioning_replace_splitviewer(bNodeTree *ntree) +{ + /* Split viewer was replaced with a regular split node, so add a viewer node, + * and link it to the new split node to achive the same behavior of the split viewer node. */ + + LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) { + if (node->type != CMP_NODE_SPLITVIEWER__DEPRECATED) { + continue; + } + + STRNCPY(node->idname, "CompositorNodeSplit"); + node->type = CMP_NODE_SPLIT; + MEM_freeN(node->storage); + + bNode *viewer_node = nodeAddStaticNode(nullptr, ntree, CMP_NODE_VIEWER); + /* Nodes are created stacked on top of each other, so separate them a bit. */ + viewer_node->locx = node->locx + node->width + viewer_node->width / 4.0f; + viewer_node->locy = node->locy; + + bNodeSocket *split_out_socket = nodeAddStaticSocket( + ntree, node, SOCK_OUT, SOCK_IMAGE, PROP_NONE, "Image", "Image"); + bNodeSocket *viewer_in_socket = nodeFindSocket(viewer_node, SOCK_IN, "Image"); + + nodeAddLink(ntree, node, split_out_socket, viewer_node, viewer_in_socket); + } +} + void do_versions_after_linking_400(FileData *fd, Main *bmain) { if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 9)) { @@ -2431,6 +2458,13 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) SET_FLAG_FROM_TEST(material->blend_flag, transparent_shadow, MA_BL_TRANSPARENT_SHADOW); } } + + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_COMPOSIT) { + versioning_replace_splitviewer(ntree); + } + } + FOREACH_NODETREE_END; } /* 401 6 did not require any do_version here. */ diff --git a/source/blender/blenloader/intern/versioning_legacy.cc b/source/blender/blenloader/intern/versioning_legacy.cc index a6f516383fe..cf032f1cc03 100644 --- a/source/blender/blenloader/intern/versioning_legacy.cc +++ b/source/blender/blenloader/intern/versioning_legacy.cc @@ -363,7 +363,7 @@ static void do_version_ntree_242_2(bNodeTree *ntree) { if (ntree->type == NTREE_COMPOSIT) { LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER)) { /* only image had storage */ if (node->storage) { NodeImageAnim *nia = static_cast(node->storage); diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 9976ffcb40d..fe7e71e012f 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -122,6 +122,8 @@ if(WITH_COMPOSITOR_CPU) nodes/COM_RenderLayersNode.h nodes/COM_SceneTimeNode.cc nodes/COM_SceneTimeNode.h + nodes/COM_SplitNode.cc + nodes/COM_SplitNode.h nodes/COM_SwitchNode.cc nodes/COM_SwitchNode.h nodes/COM_SwitchViewNode.cc @@ -136,8 +138,6 @@ if(WITH_COMPOSITOR_CPU) # output nodes nodes/COM_CompositorNode.cc nodes/COM_CompositorNode.h - nodes/COM_SplitViewerNode.cc - nodes/COM_SplitViewerNode.h nodes/COM_ViewLevelsNode.cc nodes/COM_ViewLevelsNode.h nodes/COM_ViewerNode.cc diff --git a/source/blender/compositor/intern/COM_Converter.cc b/source/blender/compositor/intern/COM_Converter.cc index 59aa6413ee3..43d03a475fc 100644 --- a/source/blender/compositor/intern/COM_Converter.cc +++ b/source/blender/compositor/intern/COM_Converter.cc @@ -89,7 +89,7 @@ #include "COM_SeparateXYZNode.h" #include "COM_SetAlphaNode.h" #include "COM_SetValueOperation.h" -#include "COM_SplitViewerNode.h" +#include "COM_SplitNode.h" #include "COM_Stabilize2dNode.h" #include "COM_SunBeamsNode.h" #include "COM_SwitchNode.h" @@ -212,8 +212,8 @@ Node *COM_convert_bnode(bNode *b_node) case CMP_NODE_VIEWER: node = new ViewerNode(b_node); break; - case CMP_NODE_SPLITVIEWER: - node = new SplitViewerNode(b_node); + case CMP_NODE_SPLIT: + node = new SplitNode(b_node); break; case CMP_NODE_INVERT: node = new InvertNode(b_node); diff --git a/source/blender/compositor/nodes/COM_SplitNode.cc b/source/blender/compositor/nodes/COM_SplitNode.cc new file mode 100644 index 00000000000..dd6c81949d9 --- /dev/null +++ b/source/blender/compositor/nodes/COM_SplitNode.cc @@ -0,0 +1,33 @@ +/* SPDX-FileCopyrightText: 2011 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "COM_SplitNode.h" + +#include "COM_SplitOperation.h" + +namespace blender::compositor { + +SplitNode::SplitNode(bNode *editor_node) : Node(editor_node) +{ + /* pass */ +} + +void SplitNode::convert_to_operations(NodeConverter &converter, + const CompositorContext & /* context */) const +{ + const bNode *node = this->get_bnode(); + + SplitOperation *split_operation = new SplitOperation(); + split_operation->set_split_percentage(node->custom1); + split_operation->set_xsplit(node->custom2 == CMP_NODE_SPLIT_HORIZONTAL); + + converter.add_operation(split_operation); + converter.map_input_socket(get_input_socket(0), split_operation->get_input_socket(0)); + converter.map_input_socket(get_input_socket(1), split_operation->get_input_socket(1)); + converter.map_output_socket(get_output_socket(0), split_operation->get_output_socket(0)); + + converter.add_preview(split_operation->get_output_socket()); +} + +} // namespace blender::compositor diff --git a/source/blender/compositor/nodes/COM_SplitViewerNode.h b/source/blender/compositor/nodes/COM_SplitNode.h similarity index 79% rename from source/blender/compositor/nodes/COM_SplitViewerNode.h rename to source/blender/compositor/nodes/COM_SplitNode.h index 6ab83f1d6a3..19c6345043c 100644 --- a/source/blender/compositor/nodes/COM_SplitViewerNode.h +++ b/source/blender/compositor/nodes/COM_SplitNode.h @@ -10,12 +10,12 @@ namespace blender::compositor { /** - * \brief SplitViewerNode + * \brief SplitNode * \ingroup Node */ -class SplitViewerNode : public Node { +class SplitNode : public Node { public: - SplitViewerNode(bNode *editor_node); + SplitNode(bNode *node); void convert_to_operations(NodeConverter &converter, const CompositorContext &context) const override; }; diff --git a/source/blender/compositor/nodes/COM_SplitViewerNode.cc b/source/blender/compositor/nodes/COM_SplitViewerNode.cc deleted file mode 100644 index bfd5640e9e7..00000000000 --- a/source/blender/compositor/nodes/COM_SplitViewerNode.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-FileCopyrightText: 2011 Blender Authors - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "COM_SplitViewerNode.h" - -#include "COM_SplitOperation.h" -#include "COM_ViewerOperation.h" - -namespace blender::compositor { - -SplitViewerNode::SplitViewerNode(bNode *editor_node) : Node(editor_node) -{ - /* pass */ -} - -void SplitViewerNode::convert_to_operations(NodeConverter &converter, - const CompositorContext &context) const -{ - const bNode *editor_node = this->get_bnode(); - bool is_active = (editor_node->flag & NODE_DO_OUTPUT_RECALC || context.is_rendering()) && - (editor_node->flag & NODE_DO_OUTPUT); - - NodeInput *image1Socket = this->get_input_socket(0); - NodeInput *image2Socket = this->get_input_socket(1); - Image *image = (Image *)this->get_bnode()->id; - ImageUser *image_user = (ImageUser *)this->get_bnode()->storage; - Scene *scene = context.get_scene(); - - SplitOperation *split_viewer_operation = new SplitOperation(); - split_viewer_operation->set_split_percentage(this->get_bnode()->custom1); - split_viewer_operation->set_xsplit(!this->get_bnode()->custom2); - - converter.add_operation(split_viewer_operation); - converter.map_input_socket(image1Socket, split_viewer_operation->get_input_socket(0)); - converter.map_input_socket(image2Socket, split_viewer_operation->get_input_socket(1)); - - ViewerOperation *viewer_operation = new ViewerOperation(); - viewer_operation->set_image(image); - viewer_operation->set_image_user(image_user); - viewer_operation->set_view_settings(&scene->view_settings); - viewer_operation->set_display_settings(&scene->display_settings); - viewer_operation->set_render_data(context.get_render_data()); - viewer_operation->set_view_name(context.get_view_name()); - - /* defaults - the viewer node has these options but not exposed for split view - * we could use the split to define an area of interest on one axis at least */ - viewer_operation->set_chunk_order(ChunkOrdering::Default); - viewer_operation->setCenterX(0.5f); - viewer_operation->setCenterY(0.5f); - - converter.add_operation(viewer_operation); - converter.add_link(split_viewer_operation->get_output_socket(), - viewer_operation->get_input_socket(0)); - - converter.add_preview(split_viewer_operation->get_output_socket()); - - if (is_active) { - converter.register_viewer(viewer_operation); - } -} - -} // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_SplitOperation.cc b/source/blender/compositor/operations/COM_SplitOperation.cc index 8060497bc97..f18178082ce 100644 --- a/source/blender/compositor/operations/COM_SplitOperation.cc +++ b/source/blender/compositor/operations/COM_SplitOperation.cc @@ -13,6 +13,8 @@ SplitOperation::SplitOperation() this->add_output_socket(DataType::Color); image1Input_ = nullptr; image2Input_ = nullptr; + + flags_.can_be_constant = true; } void SplitOperation::init_execution() diff --git a/source/blender/compositor/realtime_compositor/CMakeLists.txt b/source/blender/compositor/realtime_compositor/CMakeLists.txt index 862a8d31265..83867a99e1f 100644 --- a/source/blender/compositor/realtime_compositor/CMakeLists.txt +++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt @@ -179,7 +179,7 @@ set(GLSL_SRC shaders/compositor_smaa_blending_weight_calculation.glsl shaders/compositor_smaa_edge_detection.glsl shaders/compositor_smaa_neighborhood_blending.glsl - shaders/compositor_split_viewer.glsl + shaders/compositor_split.glsl shaders/compositor_summed_area_table_compute_complete_blocks.glsl shaders/compositor_summed_area_table_compute_complete_x_prologues.glsl shaders/compositor_summed_area_table_compute_complete_y_prologues.glsl @@ -294,7 +294,7 @@ set(SRC_SHADER_CREATE_INFOS shaders/infos/compositor_realize_on_domain_info.hh shaders/infos/compositor_screen_lens_distortion_info.hh shaders/infos/compositor_smaa_info.hh - shaders/infos/compositor_split_viewer_info.hh + shaders/infos/compositor_split_info.hh shaders/infos/compositor_summed_area_table_info.hh shaders/infos/compositor_sun_beams_info.hh shaders/infos/compositor_symmetric_blur_info.hh diff --git a/source/blender/compositor/realtime_compositor/intern/scheduler.cc b/source/blender/compositor/realtime_compositor/intern/scheduler.cc index 759a9f5c023..9312e917c04 100644 --- a/source/blender/compositor/realtime_compositor/intern/scheduler.cc +++ b/source/blender/compositor/realtime_compositor/intern/scheduler.cc @@ -22,8 +22,7 @@ namespace blender::realtime_compositor { using namespace nodes::derived_node_tree_types; /* Add the viewer node which is marked as NODE_DO_OUTPUT in the given context to the given stack. - * If multiple types of viewer nodes are marked, then the preference will be CMP_NODE_VIEWER > - * CMP_NODE_SPLITVIEWER. If no viewer nodes were found, composite nodes can be added as a fallback + * If no viewer nodes were found, composite nodes can be added as a fallback * viewer node. */ static bool add_viewer_nodes_in_context(const DTreeContext *context, Stack &node_stack) { @@ -34,13 +33,6 @@ static bool add_viewer_nodes_in_context(const DTreeContext *context, Stackbtree().nodes_by_type("CompositorNodeSplitViewer")) { - if (node->flag & NODE_DO_OUTPUT && !(node->flag & NODE_MUTED)) { - node_stack.push(DNode(context, node)); - return true; - } - } - /* The active Composite node was already added, no need to add it again, see the next block. */ if (!node_stack.is_empty() && node_stack.peek()->type == CMP_NODE_COMPOSITE) { return false; diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_split_viewer.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_split.glsl similarity index 68% rename from source/blender/compositor/realtime_compositor/shaders/compositor_split_viewer.glsl rename to source/blender/compositor/realtime_compositor/shaders/compositor_split.glsl index a1fbf12b77f..b7d2bef7673 100644 --- a/source/blender/compositor/realtime_compositor/shaders/compositor_split_viewer.glsl +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_split.glsl @@ -7,12 +7,13 @@ void main() { ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + ivec2 output_size = imageSize(output_img); #if defined(SPLIT_HORIZONTAL) - bool condition = (view_size.x * split_ratio) < texel.x; + bool condition = (output_size.x * split_ratio) < texel.x; #elif defined(SPLIT_VERTICAL) - bool condition = (view_size.y * split_ratio) < texel.y; + bool condition = (output_size.y * split_ratio) < texel.y; #endif vec4 color = condition ? texture_load(first_image_tx, texel) : texture_load(second_image_tx, texel); - imageStore(output_img, texel + lower_bound, color); + imageStore(output_img, texel, color); } diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_split_viewer_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_split_info.hh similarity index 55% rename from source/blender/compositor/realtime_compositor/shaders/infos/compositor_split_viewer_info.hh rename to source/blender/compositor/realtime_compositor/shaders/infos/compositor_split_info.hh index cda83dc4e26..0529a8469f2 100644 --- a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_split_viewer_info.hh +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_split_info.hh @@ -4,22 +4,20 @@ #include "gpu_shader_create_info.hh" -GPU_SHADER_CREATE_INFO(compositor_split_viewer_shared) +GPU_SHADER_CREATE_INFO(compositor_split_shared) .local_group_size(16, 16) .push_constant(Type::FLOAT, "split_ratio") - .push_constant(Type::IVEC2, "view_size") - .push_constant(Type::IVEC2, "lower_bound") .sampler(0, ImageType::FLOAT_2D, "first_image_tx") .sampler(1, ImageType::FLOAT_2D, "second_image_tx") .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .compute_source("compositor_split_viewer.glsl"); + .compute_source("compositor_split.glsl"); -GPU_SHADER_CREATE_INFO(compositor_split_viewer_horizontal) - .additional_info("compositor_split_viewer_shared") +GPU_SHADER_CREATE_INFO(compositor_split_horizontal) + .additional_info("compositor_split_shared") .define("SPLIT_HORIZONTAL") .do_static_compilation(true); -GPU_SHADER_CREATE_INFO(compositor_split_viewer_vertical) - .additional_info("compositor_split_viewer_shared") +GPU_SHADER_CREATE_INFO(compositor_split_vertical) + .additional_info("compositor_split_shared") .define("SPLIT_VERTICAL") .do_static_compilation(true); diff --git a/source/blender/editors/space_image/image_buttons.cc b/source/blender/editors/space_image/image_buttons.cc index 0831a8590a3..708a735150f 100644 --- a/source/blender/editors/space_image/image_buttons.cc +++ b/source/blender/editors/space_image/image_buttons.cc @@ -53,7 +53,7 @@ ImageUser *ntree_get_active_iuser(bNodeTree *ntree) { if (ntree) { LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (node->type == CMP_NODE_VIEWER) { if (node->flag & NODE_DO_OUTPUT) { return static_cast(node->storage); } diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index c7d07c7bac1..cecb378d2b1 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -133,7 +133,7 @@ static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags) node->flag |= NODE_DO_OUTPUT_RECALC; } } - else if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + else if (node->type == CMP_NODE_VIEWER) { if (recalc_flags & COM_RECALC_VIEWER) { node->flag |= NODE_DO_OUTPUT_RECALC; } @@ -813,9 +813,9 @@ void ED_node_set_active( } else if (ntree->type == NTREE_COMPOSIT) { /* Make active viewer, currently only one is supported. */ - if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (node->type == CMP_NODE_VIEWER) { for (bNode *node_iter : ntree->all_nodes()) { - if (ELEM(node_iter->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (node_iter->type == CMP_NODE_VIEWER) { node_iter->flag &= ~NODE_DO_OUTPUT; } } diff --git a/source/blender/editors/space_node/node_gizmo.cc b/source/blender/editors/space_node/node_gizmo.cc index 7341b5b52eb..dcb82abad97 100644 --- a/source/blender/editors/space_node/node_gizmo.cc +++ b/source/blender/editors/space_node/node_gizmo.cc @@ -103,7 +103,7 @@ static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmGizmoGroupType if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { bNode *node = nodeGetActive(snode->edittree); - if (node && ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (node && ELEM(node->type, CMP_NODE_VIEWER)) { return true; } } diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index 296ad2c7ee7..262941646de 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -471,7 +471,7 @@ static bNodeSocket *node_link_viewer_get_socket(bNodeTree &ntree, static bool is_viewer_node(const bNode &node) { - return ELEM(node.type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER); + return ELEM(node.type, CMP_NODE_VIEWER, GEO_NODE_VIEWER); } static bool is_viewer_socket_in_viewer(const bNodeSocket &socket) diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 07743f271de..58f5137fb01 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -2365,11 +2365,11 @@ enum { CMP_NODE_OUTPUT_IGNORE_ALPHA = 1, }; -/** Split Viewer Node. Stored in `custom2`. */ -typedef enum CMPNodeSplitViewerAxis { - CMP_NODE_SPLIT_VIEWER_HORIZONTAL = 0, - CMP_NODE_SPLIT_VIEWER_VERTICAL = 1, -} CMPNodeSplitViewerAxis; +/** Split Node. Stored in `custom2`. */ +typedef enum CMPNodeSplitAxis { + CMP_NODE_SPLIT_HORIZONTAL = 0, + CMP_NODE_SPLIT_VERTICAL = 1, +} CMPNodeSplitAxis; /** Color Balance Node. Stored in `custom1`. */ typedef enum CMPNodeColorBalanceMethod { diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index 8febc4fbcbf..e5c7ed9258d 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -6847,7 +6847,7 @@ static void def_cmp_flip(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } -static void def_cmp_splitviewer(StructRNA *srna) +static void def_cmp_split(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 3f1b8058f6d..62499142c74 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -167,7 +167,7 @@ DefNode(CompositorNode, CMP_NODE_COLOR_SPILL, def_cmp_color_spill, "COLOR_ DefNode(CompositorNode, CMP_NODE_CHROMA_MATTE, def_cmp_chroma_matte, "CHROMA_MATTE", ChromaMatte, "Chroma Key", "" ) DefNode(CompositorNode, CMP_NODE_CHANNEL_MATTE, def_cmp_channel_matte, "CHANNEL_MATTE", ChannelMatte, "Channel Key", "" ) DefNode(CompositorNode, CMP_NODE_FLIP, def_cmp_flip, "FLIP", Flip, "Flip", "" ) -DefNode(CompositorNode, CMP_NODE_SPLITVIEWER, def_cmp_splitviewer, "SPLITVIEWER", SplitViewer, "Split Viewer", "" ) +DefNode(CompositorNode, CMP_NODE_SPLIT, def_cmp_split, "SPLIT", Split, "Split", "" ) DefNode(CompositorNode, CMP_NODE_MAP_UV, def_cmp_map_uv, "MAP_UV", MapUV, "Map UV", "" ) DefNode(CompositorNode, CMP_NODE_ID_MASK, def_cmp_id_mask, "ID_MASK", IDMask, "ID Mask", "" ) DefNode(CompositorNode, CMP_NODE_DOUBLEEDGEMASK, def_cmp_double_edge_mask,"DOUBLEEDGEMASK", DoubleEdgeMask, "Double Edge Mask", "" ) diff --git a/source/blender/nodes/composite/CMakeLists.txt b/source/blender/nodes/composite/CMakeLists.txt index 17d345016d1..8616b3e6624 100644 --- a/source/blender/nodes/composite/CMakeLists.txt +++ b/source/blender/nodes/composite/CMakeLists.txt @@ -99,7 +99,7 @@ set(SRC nodes/node_composite_sepcomb_ycca.cc nodes/node_composite_sepcomb_yuva.cc nodes/node_composite_setalpha.cc - nodes/node_composite_split_viewer.cc + nodes/node_composite_split.cc nodes/node_composite_stabilize2d.cc nodes/node_composite_sunbeams.cc nodes/node_composite_switch.cc diff --git a/source/blender/nodes/composite/node_composite_register.cc b/source/blender/nodes/composite/node_composite_register.cc index 89c3639d730..fa56a6d1f82 100644 --- a/source/blender/nodes/composite/node_composite_register.cc +++ b/source/blender/nodes/composite/node_composite_register.cc @@ -95,7 +95,7 @@ void register_composite_nodes() register_node_type_cmp_sepycca(); register_node_type_cmp_sepyuva(); register_node_type_cmp_setalpha(); - register_node_type_cmp_splitviewer(); + register_node_type_cmp_split(); register_node_type_cmp_stabilize2d(); register_node_type_cmp_sunbeams(); register_node_type_cmp_switch_view(); diff --git a/source/blender/nodes/composite/node_composite_register.hh b/source/blender/nodes/composite/node_composite_register.hh index 39e55e3d20d..85996327d97 100644 --- a/source/blender/nodes/composite/node_composite_register.hh +++ b/source/blender/nodes/composite/node_composite_register.hh @@ -91,7 +91,7 @@ void register_node_type_cmp_seprgba(); void register_node_type_cmp_sepycca(); void register_node_type_cmp_sepyuva(); void register_node_type_cmp_setalpha(); -void register_node_type_cmp_splitviewer(); +void register_node_type_cmp_split(); void register_node_type_cmp_stabilize2d(); void register_node_type_cmp_sunbeams(); void register_node_type_cmp_switch_view(); diff --git a/source/blender/nodes/composite/node_composite_tree.cc b/source/blender/nodes/composite/node_composite_tree.cc index 1d1e9f7e236..a48ba88c77c 100644 --- a/source/blender/nodes/composite/node_composite_tree.cc +++ b/source/blender/nodes/composite/node_composite_tree.cc @@ -78,7 +78,7 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree) /* move over the compbufs */ /* right after #blender::bke::ntreeCopyTree() `oldsock` pointers are valid */ - if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (node->type == CMP_NODE_VIEWER) { if (node->id) { if (node->flag & NODE_DO_OUTPUT) { local_node->id = (ID *)node->id; @@ -101,7 +101,7 @@ static void local_merge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree) LISTBASE_FOREACH (bNode *, lnode, &localtree->nodes) { if (bNode *orig_node = nodeFindNodebyName(ntree, lnode->name)) { - if (ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if (lnode->type == CMP_NODE_VIEWER) { if (lnode->id && (lnode->flag & NODE_DO_OUTPUT)) { /* image_merge does sanity check for pointers */ BKE_image_merge(bmain, (Image *)orig_node->id, (Image *)lnode->id); diff --git a/source/blender/nodes/composite/nodes/node_composite_split.cc b/source/blender/nodes/composite/nodes/node_composite_split.cc new file mode 100644 index 00000000000..e78959aaf35 --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_split.cc @@ -0,0 +1,123 @@ +/* SPDX-FileCopyrightText: 2006 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup cmpnodes + */ + +#include "BKE_global.h" +#include "BKE_image.h" + +#include "UI_interface.hh" +#include "UI_resources.hh" + +#include "GPU_shader.h" +#include "GPU_texture.h" + +#include "COM_node_operation.hh" +#include "COM_utilities.hh" + +#include "node_composite_util.hh" + +/* **************** SPLIT NODE ******************** */ + +namespace blender::nodes::node_composite_split_cc { + +static void cmp_node_split_declare(NodeDeclarationBuilder &b) +{ + b.add_input("Image"); + b.add_input("Image", "Image_001"); + b.add_output("Image"); +} + +static void node_composit_init_split(bNodeTree * /*ntree*/, bNode *node) +{ + node->custom1 = 50; /* default 50% split */ +} + +static void node_composit_buts_split(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) +{ + uiLayout *row, *col; + + col = uiLayoutColumn(layout, false); + row = uiLayoutRow(col, false); + uiItemR(row, ptr, "axis", UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); + uiItemR(col, ptr, "factor", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); +} + +using namespace blender::realtime_compositor; + +class SplitOperation : public NodeOperation { + public: + using NodeOperation::NodeOperation; + + void execute() override + { + GPUShader *shader = get_split_shader(); + GPU_shader_bind(shader); + + GPU_shader_uniform_1f(shader, "split_ratio", get_split_ratio()); + + const Result &first_image = get_input("Image"); + first_image.bind_as_texture(shader, "first_image_tx"); + const Result &second_image = get_input("Image_001"); + second_image.bind_as_texture(shader, "second_image_tx"); + + const Domain domain = compute_domain(); + Result &output_image = get_result("Image"); + output_image.allocate_texture(domain); + output_image.bind_as_image(shader, "output_img"); + + compute_dispatch_threads_at_least(shader, domain.size); + + first_image.unbind_as_texture(); + second_image.unbind_as_texture(); + output_image.unbind_as_image(); + GPU_shader_unbind(); + } + + GPUShader *get_split_shader() + { + if (get_split_axis() == CMP_NODE_SPLIT_HORIZONTAL) { + return context().get_shader("compositor_split_horizontal"); + } + + return context().get_shader("compositor_split_vertical"); + } + + CMPNodeSplitAxis get_split_axis() + { + return (CMPNodeSplitAxis)bnode().custom2; + } + + float get_split_ratio() + { + return bnode().custom1 / 100.0f; + } +}; + +static NodeOperation *get_compositor_operation(Context &context, DNode node) +{ + return new SplitOperation(context, node); +} + +} // namespace blender::nodes::node_composite_split_cc + +void register_node_type_cmp_split() +{ + namespace file_ns = blender::nodes::node_composite_split_cc; + + static bNodeType ntype; + + cmp_node_type_base(&ntype, CMP_NODE_SPLIT, "Split", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::cmp_node_split_declare; + ntype.draw_buttons = file_ns::node_composit_buts_split; + ntype.flag |= NODE_PREVIEW; + ntype.initfunc = file_ns::node_composit_init_split; + ntype.get_compositor_operation = file_ns::get_compositor_operation; + + ntype.no_muting = true; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/composite/nodes/node_composite_split_viewer.cc b/source/blender/nodes/composite/nodes/node_composite_split_viewer.cc deleted file mode 100644 index 299e46aa2a8..00000000000 --- a/source/blender/nodes/composite/nodes/node_composite_split_viewer.cc +++ /dev/null @@ -1,150 +0,0 @@ -/* SPDX-FileCopyrightText: 2006 Blender Authors - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup cmpnodes - */ - -#include "BKE_global.h" -#include "BKE_image.h" - -#include "UI_interface.hh" -#include "UI_resources.hh" - -#include "GPU_shader.h" -#include "GPU_texture.h" - -#include "COM_node_operation.hh" -#include "COM_utilities.hh" - -#include "node_composite_util.hh" - -/* **************** SPLIT VIEWER ******************** */ - -namespace blender::nodes::node_composite_split_viewer_cc { - -static void cmp_node_split_viewer_declare(NodeDeclarationBuilder &b) -{ - b.add_input("Image"); - b.add_input("Image", "Image_001"); -} - -static void node_composit_init_splitviewer(bNodeTree * /*ntree*/, bNode *node) -{ - ImageUser *iuser = MEM_cnew(__func__); - node->storage = iuser; - iuser->sfra = 1; - node->custom1 = 50; /* default 50% split */ - - node->id = (ID *)BKE_image_ensure_viewer(G.main, IMA_TYPE_COMPOSITE, "Viewer Node"); -} - -static void node_composit_buts_splitviewer(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) -{ - uiLayout *row, *col; - - col = uiLayoutColumn(layout, false); - row = uiLayoutRow(col, false); - uiItemR(row, ptr, "axis", UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); - uiItemR(col, ptr, "factor", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); -} - -using namespace blender::realtime_compositor; - -class ViewerOperation : public NodeOperation { - public: - using NodeOperation::NodeOperation; - - void execute() override - { - GPUShader *shader = get_split_viewer_shader(); - GPU_shader_bind(shader); - - /* The compositing space might be limited to a subset of the output texture, so only write into - * that compositing region. */ - const rcti compositing_region = context().get_compositing_region(); - const int2 lower_bound = int2(compositing_region.xmin, compositing_region.ymin); - GPU_shader_uniform_2iv(shader, "lower_bound", lower_bound); - - GPU_shader_uniform_1f(shader, "split_ratio", get_split_ratio()); - - const int2 compositing_region_size = context().get_compositing_region_size(); - GPU_shader_uniform_2iv(shader, "view_size", compositing_region_size); - - const Result &first_image = get_input("Image"); - first_image.bind_as_texture(shader, "first_image_tx"); - const Result &second_image = get_input("Image_001"); - second_image.bind_as_texture(shader, "second_image_tx"); - - const int2 viewer_size = compute_domain().size; - GPUTexture *output_texture = context().get_viewer_output_texture(viewer_size); - const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img"); - GPU_texture_image_bind(output_texture, image_unit); - - compute_dispatch_threads_at_least(shader, viewer_size); - - first_image.unbind_as_texture(); - second_image.unbind_as_texture(); - GPU_texture_image_unbind(output_texture); - GPU_shader_unbind(); - } - - Domain compute_domain() override - { - /* The context can use the composite output and thus has a dedicated viewer of an arbitrary - * size, so use the input directly. Otherwise, no dedicated viewer exist so the input should be - * in the domain of the compositing region. */ - if (context().use_composite_output()) { - return NodeOperation::compute_domain(); - } - else { - return Domain(context().get_compositing_region_size()); - } - } - - GPUShader *get_split_viewer_shader() - { - if (get_split_axis() == CMP_NODE_SPLIT_VIEWER_HORIZONTAL) { - return context().get_shader("compositor_split_viewer_horizontal", ResultPrecision::Half); - } - - return context().get_shader("compositor_split_viewer_vertical", ResultPrecision::Half); - } - - CMPNodeSplitViewerAxis get_split_axis() - { - return (CMPNodeSplitViewerAxis)bnode().custom2; - } - - float get_split_ratio() - { - return bnode().custom1 / 100.0f; - } -}; - -static NodeOperation *get_compositor_operation(Context &context, DNode node) -{ - return new ViewerOperation(context, node); -} - -} // namespace blender::nodes::node_composite_split_viewer_cc - -void register_node_type_cmp_splitviewer() -{ - namespace file_ns = blender::nodes::node_composite_split_viewer_cc; - - static bNodeType ntype; - - cmp_node_type_base(&ntype, CMP_NODE_SPLITVIEWER, "Split Viewer", NODE_CLASS_OUTPUT); - ntype.declare = file_ns::cmp_node_split_viewer_declare; - ntype.draw_buttons = file_ns::node_composit_buts_splitviewer; - ntype.flag |= NODE_PREVIEW; - ntype.initfunc = file_ns::node_composit_init_splitviewer; - node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage); - ntype.get_compositor_operation = file_ns::get_compositor_operation; - - ntype.no_muting = true; - - nodeRegisterType(&ntype); -}