Blender V4.3
shader_node.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_assert.h"
6#include "BLI_math_vector.h"
7#include "BLI_string_ref.hh"
8
9#include "DNA_node_types.h"
10
12
13#include "GPU_material.hh"
14
15#include "COM_shader_node.hh"
16#include "COM_utilities.hh"
17
19
20using namespace nodes::derived_node_tree_types;
21
22ShaderNode::ShaderNode(DNode node) : node_(node)
23{
24 populate_inputs();
25 populate_outputs();
26}
27
29{
30 return inputs_.data();
31}
32
34{
35 return outputs_.data();
36}
37
39{
40 return inputs_[node_.input_by_identifier(identifier)->index()];
41}
42
44{
45 return outputs_[node_.output_by_identifier(identifier)->index()];
46}
49{
50 GPUNodeStack &input = get_input(identifier);
51 if (input.link) {
52 return input.link;
53 }
54 return GPU_uniform(input.vec);
55}
56
57const DNode &ShaderNode::node() const
58{
59 return node_;
60}
61
63{
64 return *node_;
65}
66
68{
69 switch (type) {
70 case SOCK_FLOAT:
71 return GPU_FLOAT;
72 case SOCK_VECTOR:
73 return GPU_VEC3;
74 case SOCK_RGBA:
75 return GPU_VEC4;
76 default:
78 return GPU_NONE;
79 }
80}
81
82/* Initializes the vector value of the given GPU node stack from the default value of the given
83 * socket. Note that the type of the stack may not match that of the socket, so perform implicit
84 * conversion if needed. */
85static void gpu_stack_vector_from_socket(GPUNodeStack &stack, const bNodeSocket *socket)
86{
87 switch (socket->type) {
88 case SOCK_FLOAT: {
89 const float value = socket->default_value_typed<bNodeSocketValueFloat>()->value;
90 switch (stack.sockettype) {
91 case SOCK_FLOAT:
92 stack.vec[0] = value;
93 return;
94 case SOCK_VECTOR:
95 copy_v3_fl(stack.vec, value);
96 return;
97 case SOCK_RGBA:
98 copy_v4_fl(stack.vec, value);
99 stack.vec[3] = 1.0f;
100 return;
101 default:
103 return;
104 }
105 }
106 case SOCK_VECTOR: {
107 const float *value = socket->default_value_typed<bNodeSocketValueVector>()->value;
108 switch (stack.sockettype) {
109 case SOCK_FLOAT:
110 stack.vec[0] = (value[0] + value[1] + value[2]) / 3.0f;
111 return;
112 case SOCK_VECTOR:
113 copy_v3_v3(stack.vec, value);
114 return;
115 case SOCK_RGBA:
116 copy_v3_v3(stack.vec, value);
117 stack.vec[3] = 1.0f;
118 return;
119 default:
121 return;
122 }
123 }
124 case SOCK_RGBA: {
125 const float *value = socket->default_value_typed<bNodeSocketValueRGBA>()->value;
126 switch (stack.sockettype) {
127 case SOCK_FLOAT:
128 stack.vec[0] = (value[0] + value[1] + value[2]) / 3.0f;
129 return;
130 case SOCK_VECTOR:
131 copy_v3_v3(stack.vec, value);
132 return;
133 case SOCK_RGBA:
134 copy_v4_v4(stack.vec, value);
135 return;
136 default:
138 return;
139 }
140 }
141 default:
143 }
144}
145
147{
148 /* Make sure this stack is not marked as the end of the stack array. */
149 stack.end = false;
150 /* This will be initialized later by the GPU material compiler or the compile method. */
151 stack.link = nullptr;
152
153 stack.sockettype = socket->type;
155
156 if (socket->is_input()) {
157 const DInputSocket input(socket);
158
159 DSocket origin = get_input_origin_socket(input);
160
161 /* The input is linked if the origin socket is an output socket. Had it been an input socket,
162 * then it is an unlinked input of a group input node. */
163 stack.hasinput = origin->is_output();
164
165 /* Get the socket value from the origin if it is an input, because then it would either be an
166 * unlinked input or an unlinked input of a group input node that the socket is linked to,
167 * otherwise, get the value from the socket itself. */
168 if (origin->is_input()) {
169 gpu_stack_vector_from_socket(stack, origin.bsocket());
170 }
171 else {
172 gpu_stack_vector_from_socket(stack, socket.bsocket());
173 }
174 }
175 else {
176 stack.hasoutput = socket->is_logically_linked();
177 }
178}
179
180void ShaderNode::populate_inputs()
181{
182 /* Reserve a stack for each input in addition to an extra stack at the end to mark the end of the
183 * array, as this is what the GPU module functions expect. */
184 const int num_input_sockets = node_->input_sockets().size();
185 inputs_.resize(num_input_sockets + 1);
186 inputs_.last().end = true;
187
188 for (int i = 0; i < num_input_sockets; i++) {
189 populate_gpu_node_stack(node_.input(i), inputs_[i]);
190 }
191}
192
193void ShaderNode::populate_outputs()
194{
195 /* Reserve a stack for each output in addition to an extra stack at the end to mark the end of
196 * the array, as this is what the GPU module functions expect. */
197 const int num_output_sockets = node_->output_sockets().size();
198 outputs_.resize(num_output_sockets + 1);
199 outputs_.last().end = true;
200
201 for (int i = 0; i < num_output_sockets; i++) {
202 populate_gpu_node_stack(node_.output(i), outputs_[i]);
203 }
204}
205
206} // namespace blender::realtime_compositor
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void copy_v4_fl(float r[4], float f)
eNodeSocketDatatype
@ SOCK_VECTOR
@ SOCK_FLOAT
@ SOCK_RGBA
eGPUType
@ GPU_VEC4
@ GPU_NONE
@ GPU_VEC3
@ GPU_FLOAT
GPUNodeLink * GPU_uniform(const float *num)
const T & last(const int64_t n=0) const
void resize(const int64_t new_size)
const bNodeSocket * bsocket() const
GPUNodeLink * get_input_link(StringRef identifier)
GPUNodeStack & get_input(StringRef identifier)
GPUNodeStack & get_output(StringRef identifier)
static void gpu_stack_vector_from_socket(GPUNodeStack &stack, const bNodeSocket *socket)
static void populate_gpu_node_stack(DSocket socket, GPUNodeStack &stack)
static eGPUType gpu_type_from_socket_type(eNodeSocketDatatype type)
DSocket get_input_origin_socket(DInputSocket input)
Definition utilities.cc:34
eGPUType type
GPUNodeLink * link