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:
committed by
Habib Gahbiche
parent
b1ac047af4
commit
153f14be2b
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
33
source/blender/compositor/nodes/COM_SplitNode.cc
Normal file
33
source/blender/compositor/nodes/COM_SplitNode.cc
Normal 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
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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", "" )
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
123
source/blender/nodes/composite/nodes/node_composite_split.cc
Normal file
123
source/blender/nodes/composite/nodes/node_composite_split.cc
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user