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
This commit is contained in:
Habib Gahbiche
2023-12-03 23:20:44 +01:00
committed by Habib Gahbiche
parent b1ac047af4
commit 153f14be2b
29 changed files with 240 additions and 269 deletions

View File

@@ -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",

View File

@@ -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

View File

@@ -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<ImageUser *>(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) {

View File

@@ -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";

View File

@@ -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. */

View File

@@ -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<NodeImageAnim *>(node->storage);

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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<DNode> &node_stack)
{
@@ -34,13 +33,6 @@ static bool add_viewer_nodes_in_context(const DTreeContext *context, Stack<DNode
}
}
for (const bNode *node : context->btree().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;

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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<ImageUser *>(node->storage);
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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", "" )

View File

@@ -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

View File

@@ -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();

View File

@@ -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();

View File

@@ -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);

View File

@@ -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<decl::Color>("Image");
b.add_input<decl::Color>("Image", "Image_001");
b.add_output<decl::Color>("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);
}

View File

@@ -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<decl::Color>("Image");
b.add_input<decl::Color>("Image", "Image_001");
}
static void node_composit_init_splitviewer(bNodeTree * /*ntree*/, bNode *node)
{
ImageUser *iuser = MEM_cnew<ImageUser>(__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);
}