35 if (done.find(in->link->parent) == done.end()) {
179 for (
int i = 0; i <
inputs.size(); ++i) {
187 else if (input_a->
link !=
NULL && input_b->link !=
NULL) {
189 if (input_a->
link != input_b->link) {
211 add(create_node<OutputNode>());
240 fprintf(stderr,
"Cycles shader graph connect: input already connected.\n");
248 "Cycles shader graph connect: can only connect closure to closure "
249 "(%s.%s to %s.%s).\n",
250 from->parent->name.c_str(),
251 from->name().c_str(),
264 emission->set_strength(1.0f);
268 convert_in =
convert->input(
"Strength");
271 convert_in =
convert->input(
"Color");
276 convert_in =
convert->inputs[0];
285 from->links.push_back(to);
378 if (surface_in->
link)
385 else if (do_simplify) {
395 if (
node !=
NULL && dependencies.find(
node) == dependencies.end()) {
399 dependencies.insert(
node);
419 nnodemap[
node] = nnode;
457 bool any_node_removed =
false;
479 bool all_links_removed =
true;
486 all_links_removed =
false;
489 if (all_links_removed)
490 removed[tonode->
id] =
true;
500 removed[proxy->
id] =
true;
501 any_node_removed =
true;
506 if (any_node_removed) {
507 list<ShaderNode *> newnodes;
510 if (!removed[
node->id])
511 newnodes.push_back(
node);
528 queue<ShaderNode *> traverse_queue;
535 traverse_queue.push(
node);
536 scheduled.insert(
node);
540 while (!traverse_queue.empty()) {
542 traverse_queue.pop();
545 if (
output->links.size() == 0) {
552 if (scheduled.find(
input->parent) != scheduled.end()) {
560 traverse_queue.push(
input->parent);
561 scheduled.insert(
input->parent);
566 node->constant_fold(folder);
574 if (has_displacement && !
output()->
input(
"Displacement")->link) {
603 map<ustring, ShaderNodeSet> candidates;
604 queue<ShaderNode *> traverse_queue;
605 int num_deduplicated = 0;
610 traverse_queue.push(
node);
611 scheduled.insert(
node);
615 while (!traverse_queue.empty()) {
617 traverse_queue.pop();
620 bool has_output_links =
false;
623 has_output_links =
true;
624 if (scheduled.find(
input->parent) != scheduled.end()) {
632 traverse_queue.push(
input->parent);
633 scheduled.insert(
input->parent);
638 if (!has_output_links) {
644 if (
node != other_node &&
node->equals(*other_node)) {
645 merge_with = other_node;
650 if (merge_with !=
NULL) {
651 for (
int i = 0; i <
node->outputs.size(); ++i) {
657 candidates[
node->type->name].insert(
node);
661 if (num_deduplicated > 0) {
662 VLOG_DEBUG <<
"Deduplicated " << num_deduplicated <<
" nodes.";
676 bool has_valid_volume =
false;
678 queue<ShaderNode *> traverse_queue;
683 while (!traverse_queue.empty()) {
685 traverse_queue.pop();
687 if (
node->has_volume_support()) {
688 has_valid_volume =
true;
695 if (scheduled.find(
input->link->parent) != scheduled.end()) {
698 traverse_queue.push(
input->link->parent);
699 scheduled.insert(
input->link->parent);
702 if (!has_valid_volume) {
703 VLOG_DEBUG <<
"Disconnect meaningless volume output.";
711 on_stack[
node->id] =
true;
717 if (on_stack[depnode->
id]) {
720 fprintf(stderr,
"Cycles shader graph: detected cycle in graph, connection removed.\n");
729 on_stack[
node->id] =
false;
738 if (!displacement_in->
link) {
750 int link_id = (
input->link) ?
input->link->parent->id : 0;
806 list<ShaderNode *> newnodes;
810 newnodes.push_back(
node);
839 texco = create_node<TextureCoordinateNode>();
845 texco = create_node<TextureCoordinateNode>();
851 texco = create_node<TextureCoordinateNode>();
857 geom = create_node<GeometryNode>();
863 geom = create_node<GeometryNode>();
869 geom = create_node<GeometryNode>();
875 geom = create_node<GeometryNode>();
961 if (!displacement_in->
link)
979 foreach (
NodePair &pair, nodes_center)
994 bump->set_use_object_space(use_object_space);
995 bump->set_distance(1.0f);
1032 foreach (
NodePair &pair, nodes_center)
1066 connect(weight_out, weight_in);
1068 weight1_out = mix_node->
output(
"Weight1");
1069 weight2_out = mix_node->
output(
"Weight2");
1073 weight1_out = weight_out;
1074 weight2_out = weight_out;
1083 ShaderInput *weight_in =
node->input((volume) ?
"VolumeMixWeight" :
"SurfaceMixWeight");
1091 if (weight_in->
link || weight_value != 0.0f) {
1092 MathNode *math_node = create_node<MathNode>();
1095 if (weight_in->
link)
1098 math_node->set_value1(weight_value);
1103 math_node->set_value2(1.0f);
1105 weight_out = math_node->
output(
"Value");
1106 if (weight_in->
link)
1112 connect(weight_out, weight_in);
1120 int num_closures = 0;
1150 return num_closures;
1155 FILE *fd = fopen(filename,
"w");
1158 printf(
"Error opening file for dumping the graph: %s\n", filename);
1162 fprintf(fd,
"digraph shader_graph {\n");
1163 fprintf(fd,
"ranksep=1.5\n");
1164 fprintf(fd,
"rankdir=LR\n");
1165 fprintf(fd,
"splines=false\n");
1168 fprintf(fd,
"// NODE: %p\n",
node);
1169 fprintf(fd,
"\"%p\" [shape=record,label=\"{",
node);
1170 if (
node->inputs.size()) {
1173 if (socket !=
node->inputs[0]) {
1176 fprintf(fd,
"<IN_%p>%s", socket, socket->
name().c_str());
1180 fprintf(fd,
"%s",
node->name.c_str());
1182 fprintf(fd,
" (bump:center)");
1185 fprintf(fd,
" (bump:dx)");
1188 fprintf(fd,
" (bump:dy)");
1190 if (
node->outputs.size()) {
1193 if (socket !=
node->outputs[0]) {
1196 fprintf(fd,
"<OUT_%p>%s", socket, socket->
name().c_str());
1200 fprintf(fd,
"}\"]");
1207 "// CONNECTION: OUT_%p->IN_%p (%s:%s)\n",
1211 input->name().c_str());
1213 "\"%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n",
@ NODE_VECTOR_MATH_DOT_PRODUCT
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
void append(const uint8_t *data, int size)
void find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input)
list< ShaderNode * > nodes
void verify_volume_output()
void simplify(Scene *scene)
void disconnect(ShaderOutput *from)
void delete_node(T *node)
void break_cycles(ShaderNode *node, vector< bool > &visited, vector< bool > &on_stack)
void copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap)
pair< ShaderNode *const, ShaderNode * > NodePair
void compute_displacement_hash()
void default_inputs(bool do_osl)
void connect(ShaderOutput *from, ShaderInput *to)
void relink(ShaderInput *from, ShaderInput *to)
void constant_fold(Scene *scene)
void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume)
void remove_proxy_nodes()
void simplify_settings(Scene *scene)
void bump_from_displacement(bool use_object_space)
void finalize(Scene *scene, bool do_bump=false, bool do_simplify=false, bool bump_in_object_space=false)
ShaderNode * add(ShaderNode *node)
void dump_graph(const char *filename)
ShaderInput * input(const char *name)
vector< ShaderOutput * > outputs
void remove_input(ShaderInput *input)
ShaderNodeSpecialType special_type
vector< ShaderInput * > inputs
virtual bool equals(const ShaderNode &other)
ShaderNode(const NodeType *type)
void create_inputs_outputs(const NodeType *type)
ShaderOutput * output(const char *name)
virtual void attributes(Shader *shader, AttributeRequestSet *attributes)
vector< ShaderInput * > links
bool has_surface_link() const
#define CCL_NAMESPACE_END
Set< ComponentNode * > visited
ccl_global KernelShaderEvalInput * input
#define CLOSURE_IS_GLASS(type)
#define CLOSURE_IS_VOLUME(type)
#define CLOSURE_IS_PRINCIPLED(type)
@ CLOSURE_BSDF_HAIR_PRINCIPLED_ID
#define CLOSURE_IS_BSSRDF(type)
#define CLOSURE_IS_BSDF_MULTISCATTER(type)
#define MAX_VOLUME_STACK_SIZE
@ ATTR_STD_GENERATED_TRANSFORM
ccl_device_inline float3 one_float3()
bool check_node_inputs_traversed(const ShaderNode *node, const ShaderNodeSet &done)
bool check_node_inputs_has_links(const ShaderNode *node)
bool remove(void *owner, const AttributeIDRef &attribute_id)
struct blender::gpu::ShaderInput ShaderInput
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
static bNodeSocketTemplate outputs[]
@ SHADER_SPECIAL_TYPE_PROXY
@ SHADER_SPECIAL_TYPE_OUTPUT_AOV
@ SHADER_SPECIAL_TYPE_COMBINE_CLOSURE
@ SHADER_SPECIAL_TYPE_BUMP
@ SHADER_SPECIAL_TYPE_AUTOCONVERT
@ SHADER_SPECIAL_TYPE_NONE
@ SHADER_SPECIAL_TYPE_OSL
set< ShaderNode *, ShaderNodeIDComparator > ShaderNodeSet
map< ShaderNode *, ShaderNode *, ShaderNodeIDComparator > ShaderNodeMap
vector< SocketType, std::allocator< SocketType > > inputs
vector< SocketType, std::allocator< SocketType > > outputs
void set_value(const SocketType &input, const Node &other, const SocketType &other_input)
void copy_value(const SocketType &input, const Node &other, const SocketType &other_input)
bool equals_value(const Node &other, const SocketType &input) const
ShaderManager * shader_manager