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
Member

Behavior:

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.

Todo after submitting the patch:

  • Translation
  • Add regression tests for CPU and GPU compositors
Behavior: <img src="/attachments/bc2d9e9c-743a-4354-888a-299038518158" width="700" /> 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. Todo after submitting the patch: - [x] Translation - [x] Add regression tests for CPU and GPU compositors
Habib Gahbiche added 3 commits 2023-10-29 10:37:24 +01:00
Habib Gahbiche changed title from Compositor: Make split viewer a regular split node to WIP: Compositor: Make split viewer a regular split node 2023-10-29 10:50:45 +01:00
Member

I am aware this is still a WIP, but the domain of the node should no longer be dependent on the render region size. For the realtime compositor, to correct that, the compute_domain method should just be removed.

I am aware this is still a WIP, but the domain of the node should no longer be dependent on the render region size. For the realtime compositor, to correct that, the `compute_domain` method should just be removed.
Author
Member

@OmarEmaraDev I see thanks.

I am not sure how to unify behaviors here. For me, the tiled/full frame behavior seems more reasonable because factor = 50% always cuts both inputs in half, whereas for GPU compositor seems to compute the 50% threshold based on the output size, not the input image sizes.

I'm curious... Does computing the domain based on the input size and the output size align well with the GPU compositor Domain design?

@OmarEmaraDev I see thanks. I am not sure how to unify behaviors here. For me, the tiled/full frame behavior seems more reasonable because `factor = 50%` always cuts both inputs in half, whereas for GPU compositor seems to compute the 50% threshold based on the output size, not the input image sizes. I'm curious... Does computing the domain based on the input size _and_ the output size align well with the GPU compositor `Domain` design?
Member

Does computing the domain based on the input size and the output size align well with the GPU compositor Domain design?

What do you mean by the output size here? The render size?

> Does computing the domain based on the input size and the output size align well with the GPU compositor Domain design? What do you mean by the output size here? The render size?
Author
Member

Yes, I mean render or viewer size (where viewer size can be different from final render size - at least for full frame compositor)

Yes, I mean render or viewer size (where viewer size can be different from final render size - at least for full frame compositor)
Member
  • The viewer size is determined by the domain of the input to the viewer node, so making the domain of a node depend on the viewer size doesn't really make sense. You can, however, depend on the render size as well as the inputs. This is how the Ellipse and Box Mask nodess work for instance. See their compute_domain method.
  • My opinion is that the node is no longer a viewer node, it is just a normal node and should not get special treatment or operate in the domain of the render size.
  • Realistically, the node is typically used when both inputs have a similar size, so we should not care much about special cases where the images have significantly different domains as you demonstrated in your examples.
- The viewer size is determined by the domain of the input to the viewer node, so making the domain of a node depend on the viewer size doesn't really make sense. You can, however, depend on the render size as well as the inputs. This is how the Ellipse and Box Mask nodess work for instance. See their `compute_domain` method. - My opinion is that the node is no longer a viewer node, it is just a normal node and should not get special treatment or operate in the domain of the render size. - Realistically, the node is typically used when both inputs have a similar size, so we should not care much about special cases where the images have significantly different domains as you demonstrated in your examples.
Sergey Sharybin added this to the Compositing project 2023-11-01 10:27:28 +01:00
Author
Member

Thanks for clarifying :)

My opinion is that the node is no longer a viewer node, it is just a normal node and should not get special treatment or operate in the domain of the render size.

I agree here, I was just wondering about the design in general.

Realistically, the node is typically used when both inputs have a similar size, so we should not care much about special cases where the images have significantly different domains as you demonstrated in your examples.

That might be the case, but I think it makes sense to unify behaviors when possible, especially between viewport and final render.

Thanks for clarifying :) > My opinion is that the node is no longer a viewer node, it is just a normal node and should not get special treatment or operate in the domain of the render size. I agree here, I was just wondering about the design in general. > Realistically, the node is typically used when both inputs have a similar size, so we should not care much about special cases where the images have significantly different domains as you demonstrated in your examples. That might be the case, but I think it makes sense to unify behaviors when possible, especially between viewport and final render.
Habib Gahbiche added 4 commits 2023-11-01 11:07:02 +01:00
Member

That might be the case, but I think it makes sense to unify behaviors when possible, especially between viewport and final render.

Definitely. I was talking about the 50% difference you mentioned in your previous comment.

> That might be the case, but I think it makes sense to unify behaviors when possible, especially between viewport and final render. Definitely. I was talking about the 50% difference you mentioned in your previous comment.

To me it does not seem that the missing translation is an intrinsic part of this PR.

There is already plenty of calls Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); which does not interact with the translation mechanism. I think those should become BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, IFACE_("Viewer Node")), (and similar thing for the render result). But that's a bigger change, and best to not mix it with the split node implementation.

To me it does not seem that the missing translation is an intrinsic part of this PR. There is already plenty of calls `Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");` which does not interact with the translation mechanism. I think those should become `BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, IFACE_("Viewer Node"))`, (and similar thing for the render result). But that's a bigger change, and best to not mix it with the split node implementation.
Habib Gahbiche added 3 commits 2023-11-09 23:40:38 +01:00
6cf3cb6d82 Realtime compositor: align behavior with fullframe compositor
- Larger image decides domain size
- Viewport and viewer node behave the same way
buildbot/vexp-code-patch-coordinator Build done. Details
ea06326932
Remove unnecessary variables
Author
Member

@blender-bot build

@blender-bot build
Habib Gahbiche added 1 commit 2023-11-11 17:58:31 +01:00
Habib Gahbiche added 1 commit 2023-11-12 10:09:36 +01:00
buildbot/vexp-code-patch-coordinator Build done. Details
c406392ab5
Support versioning
Author
Member

@blender-bot build

@blender-bot build
Habib Gahbiche changed title from WIP: Compositor: Make split viewer a regular split node to Compositor: Make split viewer a regular split node 2023-11-12 11:34:40 +01:00
Habib Gahbiche requested review from Sergey Sharybin 2023-11-12 11:34:57 +01:00
Habib Gahbiche requested review from Omar Emara 2023-11-12 11:34:57 +01:00
Habib Gahbiche reviewed 2023-11-12 11:38:26 +01:00
@ -419,0 +471,4 @@
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
if (ntree->type == NTREE_COMPOSIT) {
versioning_replace_splitviewer(ntree);
Author
Member

Not sure this belongs here inside do_versions_after_linking_400() or inside blo_do_versions_400() or in both. From testing it doesn't seem to make any difference.

Not sure this belongs here inside `do_versions_after_linking_400()` or inside `blo_do_versions_400()` or in both. From testing it doesn't seem to make any difference.
Member

Put it in blo_do_versions_400, so that we can do the stuff I mentioned above.

Put it in `blo_do_versions_400`, so that we can do the stuff I mentioned above.
zazizizou marked this conversation as resolved
Habib Gahbiche reviewed 2023-11-12 11:39:20 +01:00
@ -0,0 +1,144 @@
/* SPDX-FileCopyrightText: 2006 Blender Authors
Author
Member

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?
Member

I would just update that.

I would just update that.
Member

If input images have different sizes (by area), then output size is equal to the larger image.

This seems to be wrong. The GPU compositor uses the domain of the first linked input, the Full Frame Compositor was also designed like this from the start, so this is how it should be done.

> If input images have different sizes (by area), then output size is equal to the larger image. This seems to be wrong. The GPU compositor uses the domain of the first linked input, the Full Frame Compositor was also designed like this from the start, so this is how it should be done.
Author
Member

The GPU compositor uses the domain of the first linked input, the Full Frame Compositor was also designed like this from the start,.

This doesn't make sense to me for though, at least for this node. But looking more into the other nodes (especially mix/overlay node) I can see this behavior is different. I will update it in the next patch.

> The GPU compositor uses the domain of the first linked input, the Full Frame Compositor was also designed like this from the start,. This doesn't make sense to me for though, at least for this node. But looking more into the other nodes (especially mix/overlay node) I can see this behavior is different. I will update it in the next patch.
Habib Gahbiche added 2 commits 2023-11-13 21:01:48 +01:00
Author
Member

@blender-bot build

@blender-bot build
Omar Emara requested changes 2023-11-15 10:32:28 +01:00
@ -327,0 +336,4 @@
continue;
}
bNodeType *node_type_info = new bNodeType();
node->typeinfo = node_type_info;
Member

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); ```
Author
Member

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.
Member

Can you try adding the socket using nodeAddStaticSocket?

Can you try adding the socket using `nodeAddStaticSocket`?
Author
Member

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? :)
Member

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.
Author
Member

Ok, I don't mind either way

Ok, I don't mind either way
zazizizou marked this conversation as resolved
@ -0,0 +20,4 @@
SplitOperation *split_operation = new SplitOperation();
split_operation->set_split_percentage(node->custom1);
split_operation->set_xsplit(!node->custom2);
Member

Prefer explicit comparison with the enum.

Prefer explicit comparison with the enum.
zazizizou marked this conversation as resolved
@ -169,3 +169,3 @@
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, "SPLITNODE", Split, "Split Node", "" )
Member

Omit "Node" from the names.

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

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.
zazizizou marked this conversation as resolved
@ -0,0 +33,4 @@
static void node_composit_init_split(bNodeTree * /*ntree*/, bNode *node)
{
ImageUser *iuser = MEM_cnew<ImageUser>(__func__);
Member

Remove storage.

Remove storage.
zazizizou marked this conversation as resolved
@ -0,0 +113,4 @@
static bNodeType ntype;
cmp_node_type_base(&ntype, CMP_NODE_SPLIT, "Split Node", NODE_CLASS_LAYOUT);
Member

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`.
Author
Member

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) ?
Member

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.
zazizizou marked this conversation as resolved
@ -0,0 +118,4 @@
ntype.draw_buttons = file_ns::node_composit_buts_split;
ntype.flag |= NODE_PREVIEW;
ntype.initfunc = file_ns::node_composit_init_split;
node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
Member

The node storage can be removed.

The node storage can be removed.
zazizizou marked this conversation as resolved
Habib Gahbiche added 1 commit 2023-11-16 14:01:41 +01:00
Omar Emara requested changes 2023-11-16 15:09:09 +01:00
@ -1019,2 +1019,3 @@
#define CMP_NODE_FLIP 239
#define CMP_NODE_SPLITVIEWER 240
#define CMP_NODE_SPLITVIEWER__DEPRECATED \
240 /* Split viewer node is now a regular split node: CMP_NODE_SPLIT */
Member

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.
zazizizou marked this conversation as resolved
@ -3451,7 +3450,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);
Member

There are still uses of ELEM here and in many other places.

There are still uses of `ELEM` here and in many other places.
Author
Member

ELEM is used in other places for single element comparison. I'm leaving out node_gizmo.cc, to better conform with the coding style rule "When making changes, conform to the style and conventions of the surrounding code."

`ELEM` is used in other places for single element comparison. I'm leaving out `node_gizmo.cc`, to better conform with the coding style rule "When making changes, conform to the style and conventions of the surrounding code."
Member

That file also uses simple comparisons for single values, so I don't think this is a convention really. But don't have a strong opinion, you can leave it as is.

That file also uses simple comparisons for single values, so I don't think this is a convention really. But don't have a strong opinion, you can leave it as is.
Author
Member

👍

👍
Habib Gahbiche added 3 commits 2023-11-17 12:26:23 +01:00
Author
Member

@blender-bot build

@blender-bot build
Member

It seems there are some bad formatting, can you clang format?

It seems there are some bad formatting, can you clang format?
Habib Gahbiche added 1 commit 2023-11-17 12:40:54 +01:00
Omar Emara approved these changes 2023-11-21 17:23:01 +01:00
Omar Emara left a comment
Member

Looks good, except for those two comments.

Looks good, except for those two comments.
@ -328,0 +337,4 @@
STRNCPY(node->idname, "CompositorNodeSplit");
node->type = CMP_NODE_SPLIT;
MEM_freeN(node->storage);
Member
node->storage = nullptr;
``` node->storage = nullptr; ```
OmarEmaraDev marked this conversation as resolved
@ -328,0 +342,4 @@
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;
Member
viewer_node->flag &= ~NODE_PREVIEW;
``` viewer_node->flag &= ~NODE_PREVIEW; ```
OmarEmaraDev marked this conversation as resolved
Habib Gahbiche added 1 commit 2023-12-03 22:34:51 +01:00
Author
Member

@blender-bot build

@blender-bot build
Habib Gahbiche merged commit 153f14be2b into main 2023-12-03 23:20:55 +01:00
Habib Gahbiche deleted branch com-split-node 2023-12-03 23:20:56 +01:00
Member

@zazizizou My two comments above weren't handled.

@zazizizou My two comments above weren't handled.
Member

I fixed the comments in main.

I fixed the comments in main.
Member

The word Node in the name is redundant since all of them are nodes. It should be just Split.

Edit: Just built latest and it's corrected already :)

The word _Node_ in the name is redundant since all of them are nodes. It should be just _Split_. Edit: Just built latest and it's corrected already :)
Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
4 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#114245
No description provided.