Compositor: Make split viewer a regular split node #114245

Merged
Habib Gahbiche merged 20 commits from zazizizou/blender:com-split-node into main 2023-12-03 23:20:55 +01:00
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
zazizizou marked this conversation as resolved Outdated

Put the comment above the define. I know other places do it the current way, but that shouldn't be.

Put the comment above the define. I know other places do it the current way, but that shouldn't be.
// #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;
zazizizou marked this conversation as resolved Outdated

Change the type of the node directly. Most of other code can be removed then.

STRNCPY(node->idname, "CompositorNodeSplit");
node->type = CMP_NODE_SPLIT;
MEM_freeN(node->storage);
Change the type of the node directly. Most of other code can be removed then. ``` STRNCPY(node->idname, "CompositorNodeSplit"); node->type = CMP_NODE_SPLIT; MEM_freeN(node->storage); ```

I'm not sure how to achieve that. node doesn't have an output socket so linking to viewer node doesn't work. So I took version_geometry_nodes_replace_transfer_attribute_node() from versioning_300.cc as a reference.

I'm not sure how to achieve that. `node` doesn't have an output socket so linking to viewer node doesn't work. So I took `version_geometry_nodes_replace_transfer_attribute_node()` from `versioning_300.cc` as a reference.

Can you try adding the socket using nodeAddStaticSocket?

Can you try adding the socket using `nodeAddStaticSocket`?

Change type, manually free storage and add output socket.... isn't deleting and constructing a new node cleaner at this point? :)

Change type, manually free storage and add output socket.... isn't deleting and constructing a new node cleaner at this point? :)

You would still need to manually delete the existing node and its storage. But the main advantage is that you will not have to relink the inputs, transfer the data, or mess with typeinfo; which is most of the versioning code you have now.

You would still need to manually delete the existing node and its storage. But the main advantage is that you will not have to relink the inputs, transfer the data, or mess with typeinfo; which is most of the versioning code you have now.

Ok, I don't mind either way

Ok, I don't mind either way
MEM_freeN(node->storage);
OmarEmaraDev marked this conversation as resolved
Review
node->storage = nullptr;
``` node->storage = nullptr; ```
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;
OmarEmaraDev marked this conversation as resolved
Review
viewer_node->flag &= ~NODE_PREVIEW;
``` viewer_node->flag &= ~NODE_PREVIEW; ```
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);
zazizizou marked this conversation as resolved Outdated

Prefer explicit comparison with the enum.

Prefer explicit comparison with the enum.
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", "" )
zazizizou marked this conversation as resolved Outdated

Omit "Node" from the names.

Omit "Node" from the names.
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)) {
zazizizou marked this conversation as resolved Outdated

Replace ELEM by a simple comparison, same for the rest of the patch.

Replace `ELEM` by a simple comparison, same for the rest of the patch.
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
Review

It looks like a new file has been added but it has just been renamed. Do we update the copyright date in this case?

It looks like a new file has been added but it has just been renamed. Do we update the copyright date in this case?
Review

I would just update that.

I would just update that.
*
* 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 */
zazizizou marked this conversation as resolved Outdated

Remove storage.

Remove storage.
}
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;
zazizizou marked this conversation as resolved Outdated

Omit "Node" from the name. NODE_CLASS_LAYOUT seems wrong here, maybe just NODE_CLASS_CONVERTER or NODE_CLASS_OP_FILTER.

Omit "Node" from the name. `NODE_CLASS_LAYOUT` seems wrong here, maybe just `NODE_CLASS_CONVERTER` or `NODE_CLASS_OP_FILTER`.

CONVERTER and FILTER don't sound right either... Switch node also uses NODE_CLASS_LAYOUT. Do you suggest I change that as well (in a separate patch) ?

`CONVERTER` and `FILTER` don't sound right either... Switch node also uses `NODE_CLASS_LAYOUT`. Do you suggest I change that as well (in a separate patch) ?

Switch node could pass as a layout node to me, it doesn't really process anything.
Classes don't make sense for many nodes, so I wouldn't worry too much about it.

Switch node could pass as a layout node to me, it doesn't really process anything. Classes don't make sense for many nodes, so I wouldn't worry too much about it.
ntype.initfunc = file_ns::node_composit_init_split;
ntype.get_compositor_operation = file_ns::get_compositor_operation;
ntype.no_muting = true;
zazizizou marked this conversation as resolved Outdated

The node storage can be removed.

The node storage can be removed.
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);
}