Blender V4.3
node_composite_zcombine.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2006 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_math_base.hh"
10#include "BLI_math_vector.hh"
12
13#include "UI_interface.hh"
14#include "UI_resources.hh"
15
16#include "COM_algorithm_smaa.hh"
17#include "COM_node_operation.hh"
18#include "COM_utilities.hh"
19
20#include "GPU_shader.hh"
21
23
24/* **************** Z COMBINE ******************** */
25
27
29{
30 b.add_input<decl::Color>("Image")
31 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
32 .compositor_domain_priority(0);
33 b.add_input<decl::Float>("Z")
34 .default_value(1.0f)
35 .min(0.0f)
36 .max(10000.0f)
38 b.add_input<decl::Color>("Image", "Image_001")
39 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
40 .compositor_domain_priority(1);
41 b.add_input<decl::Float>("Z", "Z_001")
42 .default_value(1.0f)
43 .min(0.0f)
44 .max(10000.0f)
46 b.add_output<decl::Color>("Image");
47 b.add_output<decl::Float>("Z");
48}
49
51{
53
54 col = uiLayoutColumn(layout, true);
55 uiItemR(col, ptr, "use_alpha", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
56 uiItemR(col, ptr, "use_antialias_z", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
57}
58
59using namespace blender::realtime_compositor;
60
62 public:
64
65 void execute() override
66 {
67 if (compute_domain().size == int2(1)) {
69 }
70 else if (use_anti_aliasing()) {
72 }
73 else {
75 }
76 }
77
79 {
80 const float4 first_color = get_input("Image").get_color_value();
81 const float4 second_color = get_input("Image_001").get_color_value();
82 const float first_z_value = get_input("Z").get_float_value();
83 const float second_z_value = get_input("Z_001").get_float_value();
84
85 /* Mix between the first and second images using a mask such that the image with the object
86 * closer to the camera is returned. The mask value is then 1, and thus returns the first image
87 * if its Z value is less than that of the second image. Otherwise, its value is 0, and thus
88 * returns the second image. Furthermore, if the object in the first image is closer but has a
89 * non-opaque alpha, then the alpha is used as a mask, but only if Use Alpha is enabled. */
90 const float z_combine_factor = float(first_z_value < second_z_value);
91 const float alpha_factor = use_alpha() ? first_color.w : 1.0f;
92 const float mix_factor = z_combine_factor * alpha_factor;
93
94 Result &combined = get_result("Image");
95 if (combined.should_compute()) {
96 float4 combined_color = math::interpolate(second_color, first_color, mix_factor);
97 /* Use the more opaque alpha from the two images. */
98 combined_color.w = use_alpha() ? math::max(second_color.w, first_color.w) : combined_color.w;
99
100 combined.allocate_single_value();
101 combined.set_color_value(combined_color);
102 }
103
104 Result &combined_z = get_result("Z");
105 if (combined_z.should_compute()) {
106 const float combined_z_value = math::interpolate(second_z_value, first_z_value, mix_factor);
107 combined_z.allocate_single_value();
108 combined_z.set_float_value(combined_z_value);
109 }
110 }
111
113 {
114 GPUShader *shader = context().get_shader("compositor_z_combine_simple");
115 GPU_shader_bind(shader);
116
117 GPU_shader_uniform_1b(shader, "use_alpha", use_alpha());
118
119 const Result &first = get_input("Image");
120 first.bind_as_texture(shader, "first_tx");
121 const Result &first_z = get_input("Z");
122 first_z.bind_as_texture(shader, "first_z_tx");
123 const Result &second = get_input("Image_001");
124 second.bind_as_texture(shader, "second_tx");
125 const Result &second_z = get_input("Z_001");
126 second_z.bind_as_texture(shader, "second_z_tx");
127
128 Result &combined = get_result("Image");
129 const Domain domain = compute_domain();
130 combined.allocate_texture(domain);
131 combined.bind_as_image(shader, "combined_img");
132
133 Result &combined_z = get_result("Z");
134 combined_z.allocate_texture(domain);
135 combined_z.bind_as_image(shader, "combined_z_img");
136
137 compute_dispatch_threads_at_least(shader, domain.size);
138
139 first.unbind_as_texture();
140 first_z.unbind_as_texture();
141 second.unbind_as_texture();
142 second_z.unbind_as_texture();
143 combined.unbind_as_image();
144 combined_z.unbind_as_image();
146 }
147
149 {
150 Result mask = compute_mask();
151
152 GPUShader *shader = context().get_shader("compositor_z_combine_from_mask");
153 GPU_shader_bind(shader);
154
155 GPU_shader_uniform_1b(shader, "use_alpha", use_alpha());
156
157 const Result &first = get_input("Image");
158 first.bind_as_texture(shader, "first_tx");
159 const Result &first_z = get_input("Z");
160 first_z.bind_as_texture(shader, "first_z_tx");
161 const Result &second = get_input("Image_001");
162 second.bind_as_texture(shader, "second_tx");
163 const Result &second_z = get_input("Z_001");
164 second_z.bind_as_texture(shader, "second_z_tx");
165 mask.bind_as_texture(shader, "mask_tx");
166
167 Result &combined = get_result("Image");
168 const Domain domain = compute_domain();
169 combined.allocate_texture(domain);
170 combined.bind_as_image(shader, "combined_img");
171
172 Result &combined_z = get_result("Z");
173 combined_z.allocate_texture(domain);
174 combined_z.bind_as_image(shader, "combined_z_img");
175
176 compute_dispatch_threads_at_least(shader, domain.size);
177
178 first.unbind_as_texture();
179 first_z.unbind_as_texture();
180 second.unbind_as_texture();
181 second_z.unbind_as_texture();
182 mask.unbind_as_texture();
183 combined.unbind_as_image();
184 combined_z.unbind_as_image();
186
187 mask.release();
188 }
189
191 {
192 GPUShader *shader = context().get_shader("compositor_z_combine_compute_mask");
193 GPU_shader_bind(shader);
194
195 const Result &first_z = get_input("Z");
196 first_z.bind_as_texture(shader, "first_z_tx");
197 const Result &second_z = get_input("Z_001");
198 second_z.bind_as_texture(shader, "second_z_tx");
199
200 const Domain domain = compute_domain();
201 Result mask = context().create_result(ResultType::Float);
202 mask.allocate_texture(domain);
203 mask.bind_as_image(shader, "mask_img");
204
205 compute_dispatch_threads_at_least(shader, domain.size);
206
207 first_z.unbind_as_texture();
208 second_z.unbind_as_texture();
209 mask.unbind_as_image();
211
212 Result anti_aliased_mask = context().create_result(ResultType::Float);
213 smaa(context(), mask, anti_aliased_mask);
214 mask.release();
215
216 return anti_aliased_mask;
217 }
218
220 {
221 return bnode().custom1 != 0;
222 }
223
225 {
226 return bnode().custom2 == 0;
227 }
228};
229
231{
232 return new ZCombineOperation(context, node);
233}
234
235} // namespace blender::nodes::node_composite_zcombine_cc
236
238{
240
241 static blender::bke::bNodeType ntype;
242
243 cmp_node_type_base(&ntype, CMP_NODE_ZCOMBINE, "Z Combine", NODE_CLASS_OP_COLOR);
244 ntype.declare = file_ns::cmp_node_zcombine_declare;
245 ntype.draw_buttons = file_ns::node_composit_buts_zcombine;
246 ntype.get_compositor_operation = file_ns::get_compositor_operation;
247
249}
#define NODE_CLASS_OP_COLOR
Definition BKE_node.hh:406
void GPU_shader_bind(GPUShader *shader)
void GPU_shader_uniform_1b(GPUShader *sh, const char *name, bool value)
void GPU_shader_unbind()
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
struct GPUShader GPUShader
GPUShader * get_shader(const char *info_name, ResultPrecision precision)
Result create_result(ResultType type, ResultPrecision precision)
NodeOperation(Context &context, DNode node)
Result & get_input(StringRef identifier) const
Definition operation.cc:144
Result & get_result(StringRef identifier)
Definition operation.cc:46
void bind_as_image(GPUShader *shader, const char *image_name, bool read=false) const
Definition result.cc:264
void set_float_value(float value)
Definition result.cc:467
void allocate_texture(Domain domain, bool from_pool=true)
Definition result.cc:204
void set_color_value(const float4 &value)
Definition result.cc:507
void bind_as_texture(GPUShader *shader, const char *texture_name) const
Definition result.cc:253
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
uint col
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
T interpolate(const T &a, const T &b, const FactorT &t)
T max(const T &a, const T &b)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
static void node_composit_buts_zcombine(uiLayout *layout, bContext *, PointerRNA *ptr)
static void cmp_node_zcombine_declare(NodeDeclarationBuilder &b)
void smaa(Context &context, Result &input, Result &output, float threshold=0.1f, float local_contrast_adaptation_factor=2.0f, int corner_rounding=25)
Definition smaa.cc:160
void compute_dispatch_threads_at_least(GPUShader *shader, int2 threads_range, int2 local_size=int2(16))
Definition utilities.cc:131
VecBase< int32_t, 2 > int2
void cmp_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void register_node_type_cmp_zcombine()
int16_t custom1
int16_t custom2
Defines a node type.
Definition BKE_node.hh:218
NodeGetCompositorOperationFunction get_compositor_operation
Definition BKE_node.hh:324
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:238
NodeDeclareFunction declare
Definition BKE_node.hh:347
PointerRNA * ptr
Definition wm_files.cc:4126