diff options
Diffstat (limited to 'source/blender/nodes/shader')
119 files changed, 7500 insertions, 4174 deletions
diff --git a/source/blender/nodes/shader/CMakeLists.txt b/source/blender/nodes/shader/CMakeLists.txt new file mode 100644 index 00000000000..c8eb0b8d570 --- /dev/null +++ b/source/blender/nodes/shader/CMakeLists.txt @@ -0,0 +1,174 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2021, Blender Foundation +# All rights reserved. +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . + .. + ../intern + ../../blenkernel + ../../blenlib + ../../blentranslation + ../../depsgraph + ../../editors/include + ../../functions + ../../gpu + ../../imbuf + ../../makesdna + ../../makesrna + ../../render + ../../windowmanager + ../../../../intern/guardedalloc + ../../../../intern/sky/include +) + + +set(SRC + nodes/node_shader_add_shader.cc + nodes/node_shader_ambient_occlusion.cc + nodes/node_shader_attribute.cc + nodes/node_shader_background.cc + nodes/node_shader_bevel.cc + nodes/node_shader_blackbody.cc + nodes/node_shader_brightness.cc + nodes/node_shader_bsdf_anisotropic.cc + nodes/node_shader_bsdf_diffuse.cc + nodes/node_shader_bsdf_glass.cc + nodes/node_shader_bsdf_glossy.cc + nodes/node_shader_bsdf_hair.cc + nodes/node_shader_bsdf_hair_principled.cc + nodes/node_shader_bsdf_principled.cc + nodes/node_shader_bsdf_refraction.cc + nodes/node_shader_bsdf_toon.cc + nodes/node_shader_bsdf_translucent.cc + nodes/node_shader_bsdf_transparent.cc + nodes/node_shader_bsdf_velvet.cc + nodes/node_shader_bump.cc + nodes/node_shader_camera.cc + nodes/node_shader_clamp.cc + nodes/node_shader_color_ramp.cc + nodes/node_shader_common.cc + nodes/node_shader_curves.cc + nodes/node_shader_displacement.cc + nodes/node_shader_eevee_specular.cc + nodes/node_shader_emission.cc + nodes/node_shader_fresnel.cc + nodes/node_shader_gamma.cc + nodes/node_shader_geometry.cc + nodes/node_shader_hair_info.cc + nodes/node_shader_holdout.cc + nodes/node_shader_hueSatVal.cc + nodes/node_shader_ies_light.cc + nodes/node_shader_invert.cc + nodes/node_shader_layer_weight.cc + nodes/node_shader_light_falloff.cc + nodes/node_shader_light_path.cc + nodes/node_shader_map_range.cc + nodes/node_shader_mapping.cc + nodes/node_shader_math.cc + nodes/node_shader_mix_rgb.cc + nodes/node_shader_mix_shader.cc + nodes/node_shader_normal.cc + nodes/node_shader_normal_map.cc + nodes/node_shader_object_info.cc + nodes/node_shader_output_aov.cc + nodes/node_shader_output_light.cc + nodes/node_shader_output_linestyle.cc + nodes/node_shader_output_material.cc + nodes/node_shader_output_world.cc + nodes/node_shader_particle_info.cc + nodes/node_shader_point_info.cc + nodes/node_shader_rgb.cc + nodes/node_shader_rgb_to_bw.cc + nodes/node_shader_script.cc + nodes/node_shader_sepcomb_hsv.cc + nodes/node_shader_sepcomb_rgb.cc + nodes/node_shader_sepcomb_xyz.cc + nodes/node_shader_shader_to_rgb.cc + nodes/node_shader_squeeze.cc + nodes/node_shader_subsurface_scattering.cc + nodes/node_shader_tangent.cc + nodes/node_shader_tex_brick.cc + nodes/node_shader_tex_checker.cc + nodes/node_shader_tex_coord.cc + nodes/node_shader_tex_environment.cc + nodes/node_shader_tex_gradient.cc + nodes/node_shader_tex_image.cc + nodes/node_shader_tex_magic.cc + nodes/node_shader_tex_musgrave.cc + nodes/node_shader_tex_noise.cc + nodes/node_shader_tex_pointdensity.cc + nodes/node_shader_tex_sky.cc + nodes/node_shader_tex_voronoi.cc + nodes/node_shader_tex_wave.cc + nodes/node_shader_tex_white_noise.cc + nodes/node_shader_uv_along_stroke.cc + nodes/node_shader_uvmap.cc + nodes/node_shader_value.cc + nodes/node_shader_vector_displacement.cc + nodes/node_shader_vector_math.cc + nodes/node_shader_vector_rotate.cc + nodes/node_shader_vector_transform.cc + nodes/node_shader_vertex_color.cc + nodes/node_shader_volume_absorption.cc + nodes/node_shader_volume_info.cc + nodes/node_shader_volume_principled.cc + nodes/node_shader_volume_scatter.cc + nodes/node_shader_wavelength.cc + nodes/node_shader_wireframe.cc + + node_shader_tree.cc + node_shader_util.cc + + node_shader_util.hh +) + +set(LIB + bf_functions + bf_intern_sky +) + +if(WITH_PYTHON) + list(APPEND INC + ../../python + ) + list(APPEND INC_SYS + ${PYTHON_INCLUDE_DIRS} + ) + list(APPEND LIB + ${PYTHON_LINKFLAGS} + ${PYTHON_LIBRARIES} + ) + add_definitions(-DWITH_PYTHON) +endif() + +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + +if(WITH_FREESTYLE) + add_definitions(-DWITH_FREESTYLE) +endif() + +blender_add_lib(bf_nodes_shader "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") + +if(WITH_UNITY_BUILD) + set_target_properties(bf_nodes_shader PROPERTIES UNITY_BUILD ON) + set_target_properties(bf_nodes_shader PROPERTIES UNITY_BUILD_BATCH_SIZE 10) +endif() diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.cc index 46a2f7f1968..1cb1ee3163d 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.cc @@ -21,7 +21,7 @@ * \ingroup nodes */ -#include <string.h> +#include <cstring> #include "DNA_light_types.h" #include "DNA_linestyle_types.h" @@ -44,6 +44,7 @@ #include "BKE_lib_id.h" #include "BKE_linestyle.h" #include "BKE_node.h" +#include "BKE_node_tree_update.h" #include "BKE_scene.h" #include "RNA_access.h" @@ -52,11 +53,13 @@ #include "RE_texture.h" +#include "UI_resources.h" + #include "NOD_common.h" #include "node_common.h" #include "node_exec.h" -#include "node_shader_util.h" +#include "node_shader_util.hh" #include "node_util.h" static bool shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype)) @@ -85,7 +88,7 @@ static void shader_get_from_context(const bContext *C, if (ob) { *r_from = &ob->id; if (ob->type == OB_LAMP) { - *r_id = ob->data; + *r_id = static_cast<ID *>(ob->data); *r_ntree = ((Light *)ob->data)->nodetree; } else { @@ -101,7 +104,7 @@ static void shader_get_from_context(const bContext *C, else if (snode->shaderfrom == SNODE_SHADER_LINESTYLE) { FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer); if (linestyle) { - *r_from = NULL; + *r_from = nullptr; *r_id = &linestyle->id; *r_ntree = linestyle->nodetree; } @@ -109,7 +112,7 @@ static void shader_get_from_context(const bContext *C, #endif else { /* SNODE_SHADER_WORLD */ if (scene->world) { - *r_from = NULL; + *r_from = nullptr; *r_id = &scene->world->id; *r_ntree = scene->world->nodetree; } @@ -133,12 +136,8 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree)) { - bNode *node, *node_next; - /* replace muted nodes and reroute nodes by internal links */ - for (node = localtree->nodes.first; node; node = node_next) { - node_next = node->next; - + LISTBASE_FOREACH_MUTABLE (bNode *, node, &localtree->nodes) { if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { nodeInternalRelink(localtree, node); ntreeFreeLocalNode(localtree, node); @@ -146,34 +145,19 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree)) } } -static void local_sync(bNodeTree *localtree, bNodeTree *ntree) -{ - BKE_node_preview_sync_tree(ntree, localtree); -} - -static void local_merge(Main *UNUSED(bmain), bNodeTree *localtree, bNodeTree *ntree) -{ - BKE_node_preview_merge_tree(ntree, localtree, true); -} - static void update(bNodeTree *ntree) { ntreeSetOutput(ntree); ntree_update_reroute_nodes(ntree); - - if (ntree->update & NTREE_UPDATE_NODES) { - /* clean up preview cache, in case nodes have been removed */ - BKE_node_preview_remove_unused(ntree); - } } -static bool shader_validate_link(bNodeTree *UNUSED(ntree), bNodeLink *link) +static bool shader_validate_link(eNodeSocketDatatype from, eNodeSocketDatatype to) { /* Can't connect shader into other socket types, other way around is fine * since it will be interpreted as emission. */ - if (link->fromsock->type == SOCK_SHADER) { - return (link->tosock->type == SOCK_SHADER); + if (from == SOCK_SHADER) { + return to == SOCK_SHADER; } return true; } @@ -187,21 +171,18 @@ static bool shader_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype), bNodeTreeType *ntreeType_Shader; -void register_node_tree_type_sh(void) +void register_node_tree_type_sh() { - bNodeTreeType *tt = ntreeType_Shader = MEM_callocN(sizeof(bNodeTreeType), - "shader node tree type"); + bNodeTreeType *tt = ntreeType_Shader = MEM_cnew<bNodeTreeType>("shader node tree type"); tt->type = NTREE_SHADER; strcpy(tt->idname, "ShaderNodeTree"); strcpy(tt->ui_name, N_("Shader Editor")); - tt->ui_icon = 0; /* defined in drawnode.c */ + tt->ui_icon = ICON_NODE_MATERIAL; strcpy(tt->ui_description, N_("Shader nodes")); tt->foreach_nodeclass = foreach_nodeclass; tt->localize = localize; - tt->local_sync = local_sync; - tt->local_merge = local_merge; tt->update = update; tt->poll = shader_tree_poll; tt->get_from_context = shader_get_from_context; @@ -215,13 +196,6 @@ void register_node_tree_type_sh(void) /* GPU material from shader nodes */ -/* Find an output node of the shader tree. - * - * NOTE: it will only return output which is NOT in the group, which isn't how - * render engines works but it's how the GPU shader compilation works. This we - * can change in the future and make it a generic function, but for now it stays - * private here. - */ bNode *ntreeShaderOutputNode(bNodeTree *ntree, int target) { /* Make sure we only have single node tagged as output. */ @@ -229,7 +203,7 @@ bNode *ntreeShaderOutputNode(bNodeTree *ntree, int target) /* Find output node that matches type and target. If there are * multiple, we prefer exact target match and active nodes. */ - bNode *output_node = NULL; + bNode *output_node = nullptr; LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (!ELEM(node->type, SH_NODE_OUTPUT_MATERIAL, SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LIGHT)) { @@ -237,7 +211,7 @@ bNode *ntreeShaderOutputNode(bNodeTree *ntree, int target) } if (node->custom1 == SHD_OUTPUT_ALL) { - if (output_node == NULL) { + if (output_node == nullptr) { output_node = node; } else if (output_node->custom1 == SHD_OUTPUT_ALL) { @@ -247,7 +221,7 @@ bNode *ntreeShaderOutputNode(bNodeTree *ntree, int target) } } else if (node->custom1 == target) { - if (output_node == NULL) { + if (output_node == nullptr) { output_node = node; } else if (output_node->custom1 == SHD_OUTPUT_ALL) { @@ -265,12 +239,12 @@ bNode *ntreeShaderOutputNode(bNodeTree *ntree, int target) /* Find socket with a specified identifier. */ static bNodeSocket *ntree_shader_node_find_socket(ListBase *sockets, const char *identifier) { - for (bNodeSocket *sock = sockets->first; sock != NULL; sock = sock->next) { + LISTBASE_FOREACH (bNodeSocket *, sock, sockets) { if (STREQ(sock->identifier, identifier)) { return sock; } } - return NULL; + return nullptr; } /* Find input socket with a specified identifier. */ @@ -311,37 +285,37 @@ static bool ntree_shader_expand_socket_default(bNodeTree *localtree, switch (socket->type) { case SOCK_VECTOR: - value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_RGB); + value_node = nodeAddStaticNode(nullptr, localtree, SH_NODE_RGB); value_socket = ntree_shader_node_find_output(value_node, "Color"); - BLI_assert(value_socket != NULL); - src_vector = socket->default_value; - dst_rgba = value_socket->default_value; + BLI_assert(value_socket != nullptr); + src_vector = static_cast<bNodeSocketValueVector *>(socket->default_value); + dst_rgba = static_cast<bNodeSocketValueRGBA *>(value_socket->default_value); copy_v3_v3(dst_rgba->value, src_vector->value); dst_rgba->value[3] = 1.0f; /* should never be read */ break; case SOCK_RGBA: - value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_RGB); + value_node = nodeAddStaticNode(nullptr, localtree, SH_NODE_RGB); value_socket = ntree_shader_node_find_output(value_node, "Color"); - BLI_assert(value_socket != NULL); - src_rgba = socket->default_value; - dst_rgba = value_socket->default_value; + BLI_assert(value_socket != nullptr); + src_rgba = static_cast<bNodeSocketValueRGBA *>(socket->default_value); + dst_rgba = static_cast<bNodeSocketValueRGBA *>(value_socket->default_value); copy_v4_v4(dst_rgba->value, src_rgba->value); break; case SOCK_INT: /* HACK: Support as float. */ - value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_VALUE); + value_node = nodeAddStaticNode(nullptr, localtree, SH_NODE_VALUE); value_socket = ntree_shader_node_find_output(value_node, "Value"); - BLI_assert(value_socket != NULL); - src_int = socket->default_value; - dst_float = value_socket->default_value; + BLI_assert(value_socket != nullptr); + src_int = static_cast<bNodeSocketValueInt *>(socket->default_value); + dst_float = static_cast<bNodeSocketValueFloat *>(value_socket->default_value); dst_float->value = (float)(src_int->value); break; case SOCK_FLOAT: - value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_VALUE); + value_node = nodeAddStaticNode(nullptr, localtree, SH_NODE_VALUE); value_socket = ntree_shader_node_find_output(value_node, "Value"); - BLI_assert(value_socket != NULL); - src_float = socket->default_value; - dst_float = value_socket->default_value; + BLI_assert(value_socket != nullptr); + src_float = static_cast<bNodeSocketValueFloat *>(socket->default_value); + dst_float = static_cast<bNodeSocketValueFloat *>(value_socket->default_value); dst_float->value = src_float->value; break; default: @@ -354,11 +328,10 @@ static bool ntree_shader_expand_socket_default(bNodeTree *localtree, static void ntree_shader_unlink_hidden_value_sockets(bNode *group_node, bNodeSocket *isock) { bNodeTree *group_ntree = (bNodeTree *)group_node->id; - bNode *node; bool removed_link = false; - for (node = group_ntree->nodes.first; node; node = node->next) { - const bool is_group = ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && (node->id != NULL); + LISTBASE_FOREACH (bNode *, node, &group_ntree->nodes) { + const bool is_group = ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && (node->id != nullptr); LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { if (!is_group && (sock->flag & SOCK_HIDE_VALUE) == 0) { @@ -381,7 +354,7 @@ static void ntree_shader_unlink_hidden_value_sockets(bNode *group_node, bNodeSoc } if (removed_link) { - ntreeUpdateTree(G.main, group_ntree); + BKE_ntree_update_main_tree(G.main, group_ntree, nullptr); } } @@ -392,7 +365,7 @@ static void ntree_shader_groups_expand_inputs(bNodeTree *localtree) bool link_added = false; LISTBASE_FOREACH (bNode *, node, &localtree->nodes) { - const bool is_group = ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && (node->id != NULL); + const bool is_group = ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && (node->id != nullptr); const bool is_group_output = node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT); if (is_group) { @@ -402,25 +375,32 @@ static void ntree_shader_groups_expand_inputs(bNodeTree *localtree) if (is_group || is_group_output) { LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { - if (socket->link != NULL && !(socket->link->flag & NODE_LINK_MUTED)) { + if (socket->link != nullptr && !(socket->link->flag & NODE_LINK_MUTED)) { bNodeLink *link = socket->link; /* Fix the case where the socket is actually converting the data. (see T71374) * We only do the case of lossy conversion to float. */ if ((socket->type == SOCK_FLOAT) && (link->fromsock->type != link->tosock->type)) { if (link->fromsock->type == SOCK_RGBA) { - bNode *tmp = nodeAddStaticNode(NULL, localtree, SH_NODE_RGBTOBW); - nodeAddLink(localtree, link->fromnode, link->fromsock, tmp, tmp->inputs.first); - nodeAddLink(localtree, tmp, tmp->outputs.first, node, socket); + bNode *tmp = nodeAddStaticNode(nullptr, localtree, SH_NODE_RGBTOBW); + nodeAddLink(localtree, + link->fromnode, + link->fromsock, + tmp, + static_cast<bNodeSocket *>(tmp->inputs.first)); + nodeAddLink( + localtree, tmp, static_cast<bNodeSocket *>(tmp->outputs.first), node, socket); } else if (link->fromsock->type == SOCK_VECTOR) { - bNode *tmp = nodeAddStaticNode(NULL, localtree, SH_NODE_VECTOR_MATH); + bNode *tmp = nodeAddStaticNode(nullptr, localtree, SH_NODE_VECTOR_MATH); tmp->custom1 = NODE_VECTOR_MATH_DOT_PRODUCT; - bNodeSocket *dot_input1 = tmp->inputs.first; - bNodeSocket *dot_input2 = dot_input1->next; - bNodeSocketValueVector *input2_socket_value = dot_input2->default_value; + bNodeSocket *dot_input1 = static_cast<bNodeSocket *>(tmp->inputs.first); + bNodeSocket *dot_input2 = static_cast<bNodeSocket *>(dot_input1->next); + bNodeSocketValueVector *input2_socket_value = static_cast<bNodeSocketValueVector *>( + dot_input2->default_value); copy_v3_fl(input2_socket_value->value, 1.0f / 3.0f); nodeAddLink(localtree, link->fromnode, link->fromsock, tmp, dot_input1); - nodeAddLink(localtree, tmp, tmp->outputs.last, node, socket); + nodeAddLink( + localtree, tmp, static_cast<bNodeSocket *>(tmp->outputs.last), node, socket); } } continue; @@ -440,22 +420,33 @@ static void ntree_shader_groups_expand_inputs(bNodeTree *localtree) } if (link_added) { - ntreeUpdateTree(G.main, localtree); + BKE_ntree_update_main_tree(G.main, localtree, nullptr); } } -static void flatten_group_do(bNodeTree *ntree, bNode *gnode) +static void ntree_shader_groups_remove_muted_links(bNodeTree *ntree) { - bNodeLink *link, *linkn, *tlink; - bNode *node, *nextnode; - bNodeTree *ngroup; - LinkNode *group_interface_nodes = NULL; + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type == NODE_GROUP) { + if (node->id != nullptr) { + ntree_shader_groups_remove_muted_links(reinterpret_cast<bNodeTree *>(node->id)); + } + } + } + LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->flag & NODE_LINK_MUTED) { + nodeRemLink(ntree, link); + } + } +} - ngroup = (bNodeTree *)gnode->id; +static void flatten_group_do(bNodeTree *ntree, bNode *gnode) +{ + LinkNode *group_interface_nodes = nullptr; + bNodeTree *ngroup = (bNodeTree *)gnode->id; /* Add the nodes into the ntree */ - for (node = ngroup->nodes.first; node; node = nextnode) { - nextnode = node->next; + LISTBASE_FOREACH_MUTABLE (bNode *, node, &ngroup->nodes) { /* Remove interface nodes. * This also removes remaining links to and from interface nodes. * We must delay removal since sockets will reference this node. see: T52092 */ @@ -471,25 +462,26 @@ static void flatten_group_do(bNodeTree *ntree, bNode *gnode) } /* Save first and last link to iterate over flattened group links. */ - bNodeLink *glinks_first = ntree->links.last; + bNodeLink *glinks_first = static_cast<bNodeLink *>(ntree->links.last); /* Add internal links to the ntree */ - for (link = ngroup->links.first; link; link = linkn) { - linkn = link->next; + LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ngroup->links) { BLI_remlink(&ngroup->links, link); BLI_addtail(&ntree->links, link); } - bNodeLink *glinks_last = ntree->links.last; + bNodeLink *glinks_last = static_cast<bNodeLink *>(ntree->links.last); /* restore external links to and from the gnode */ - if (glinks_first != NULL) { + if (glinks_first != nullptr) { /* input links */ - for (link = glinks_first->next; link != glinks_last->next; link = link->next) { + for (bNodeLink *link = glinks_first->next; link != glinks_last->next; link = link->next) { if (link->fromnode->type == NODE_GROUP_INPUT) { const char *identifier = link->fromsock->identifier; /* find external links to this input */ - for (tlink = ntree->links.first; tlink != glinks_first->next; tlink = tlink->next) { + for (bNodeLink *tlink = static_cast<bNodeLink *>(ntree->links.first); + tlink != glinks_first->next; + tlink = tlink->next) { if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) { nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode, link->tosock); } @@ -497,13 +489,15 @@ static void flatten_group_do(bNodeTree *ntree, bNode *gnode) } } /* Also iterate over the new links to cover passthrough links. */ - glinks_last = ntree->links.last; + glinks_last = static_cast<bNodeLink *>(ntree->links.last); /* output links */ - for (tlink = ntree->links.first; tlink != glinks_first->next; tlink = tlink->next) { + for (bNodeLink *tlink = static_cast<bNodeLink *>(ntree->links.first); + tlink != glinks_first->next; + tlink = tlink->next) { if (tlink->fromnode == gnode) { const char *identifier = tlink->fromsock->identifier; /* find internal links to this output */ - for (link = glinks_first->next; link != glinks_last->next; link = link->next) { + for (bNodeLink *link = glinks_first->next; link != glinks_last->next; link = link->next) { /* only use active output node */ if (link->tonode->type == NODE_GROUP_OUTPUT && (link->tonode->flag & NODE_DO_OUTPUT)) { if (STREQ(link->tosock->identifier, identifier)) { @@ -516,11 +510,11 @@ static void flatten_group_do(bNodeTree *ntree, bNode *gnode) } while (group_interface_nodes) { - node = BLI_linklist_pop(&group_interface_nodes); + bNode *node = static_cast<bNode *>(BLI_linklist_pop(&group_interface_nodes)); ntreeFreeLocalNode(ntree, node); } - ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS; + BKE_ntree_update_tag_all(ntree); } /* Flatten group to only have a simple single tree */ @@ -528,8 +522,9 @@ static void ntree_shader_groups_flatten(bNodeTree *localtree) { /* This is effectively recursive as the flattened groups will add * nodes at the end of the list, which will also get evaluated. */ - for (bNode *node = localtree->nodes.first, *node_next; node; node = node_next) { - if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id != NULL) { + for (bNode *node = static_cast<bNode *>(localtree->nodes.first), *node_next; node; + node = node_next) { + if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id != nullptr) { flatten_group_do(localtree, node); /* Continue even on new flattened nodes. */ node_next = node->next; @@ -545,7 +540,7 @@ static void ntree_shader_groups_flatten(bNodeTree *localtree) } } - ntreeUpdateTree(G.main, localtree); + BKE_ntree_update_main_tree(G.main, localtree, nullptr); } /* Check whether shader has a displacement. @@ -560,20 +555,20 @@ static bool ntree_shader_has_displacement(bNodeTree *ntree, bNodeSocket **r_socket, bNodeLink **r_link) { - if (output_node == NULL) { + if (output_node == nullptr) { /* We can't have displacement without output node, apparently. */ return false; } /* Make sure sockets links pointers are correct. */ - ntreeUpdateTree(G.main, ntree); + BKE_ntree_update_main_tree(G.main, ntree, nullptr); bNodeSocket *displacement = ntree_shader_node_find_input(output_node, "Displacement"); - if (displacement == NULL) { + if (displacement == nullptr) { /* Non-cycles node is used as an output. */ return false; } - if ((displacement->link != NULL) && !(displacement->link->flag & NODE_LINK_MUTED)) { + if ((displacement->link != nullptr) && !(displacement->link->flag & NODE_LINK_MUTED)) { *r_node = displacement->link->fromnode; *r_socket = displacement->link->fromsock; *r_link = displacement->link; @@ -591,7 +586,7 @@ static void ntree_shader_relink_node_normal(bNodeTree *ntree, * matching? */ LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - if (STREQ(sock->identifier, "Normal") && sock->link == NULL) { + if (STREQ(sock->identifier, "Normal") && sock->link == nullptr) { /* It's a normal input and nothing is connected to it. */ nodeAddLink(ntree, node_from, socket_from, node, sock); } @@ -611,7 +606,7 @@ static void ntree_shader_link_builtin_normal(bNodeTree *ntree, bNode *node_from, bNodeSocket *socket_from) { - for (bNode *node = ntree->nodes.first; node != NULL; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node == node_from) { /* Don't connect node itself! */ continue; @@ -636,7 +631,7 @@ static void ntree_shader_bypass_bump_link(bNodeTree *ntree, bNode *bump_node, bN fromnode = bump_normal_input->link->fromnode; } else { - fromnode = nodeAddStaticNode(NULL, ntree, SH_NODE_NEW_GEOMETRY); + fromnode = nodeAddStaticNode(nullptr, ntree, SH_NODE_NEW_GEOMETRY); fromsock = ntree_shader_node_find_output(fromnode, "Normal"); } /* Bypass the bump node by creating a link between the previous and next node. */ @@ -654,7 +649,7 @@ static void ntree_shader_bypass_tagged_bump_nodes(bNodeTree *ntree) ntree_shader_bypass_bump_link(ntree, node, link); } } - ntreeUpdateTree(G.main, ntree); + BKE_ntree_update_main_tree(G.main, ntree, nullptr); } static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata) @@ -688,19 +683,19 @@ static bNode *ntree_shader_copy_branch(bNodeTree *ntree, int node_count = 1; nodeChainIterBackwards(ntree, start_node, ntree_branch_count_and_tag_nodes, &node_count, 1); /* Make a full copy of the branch */ - bNode **nodes_copy = MEM_mallocN(sizeof(bNode *) * node_count, __func__); + bNode **nodes_copy = static_cast<bNode **>(MEM_mallocN(sizeof(bNode *) * node_count, __func__)); LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->tmp_flag >= 0) { int id = node->tmp_flag; - nodes_copy[id] = BKE_node_copy_ex( - ntree, node, LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN, false); + nodes_copy[id] = blender::bke::node_copy( + ntree, *node, LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN, false); nodes_copy[id]->tmp_flag = -2; /* Copy */ /* Make sure to clear all sockets links as they are invalid. */ LISTBASE_FOREACH (bNodeSocket *, sock, &nodes_copy[id]->inputs) { - sock->link = NULL; + sock->link = nullptr; } LISTBASE_FOREACH (bNodeSocket *, sock, &nodes_copy[id]->outputs) { - sock->link = NULL; + sock->link = nullptr; } } } @@ -733,13 +728,13 @@ static void ntree_shader_copy_branch_displacement(bNodeTree *ntree, /* Replace displacement socket/node/link. */ bNode *tonode = displacement_link->tonode; bNodeSocket *tosock = displacement_link->tosock; - displacement_node = ntree_shader_copy_branch(ntree, displacement_node, NULL, 0); + displacement_node = ntree_shader_copy_branch(ntree, displacement_node, nullptr, 0); displacement_socket = ntree_shader_node_find_output(displacement_node, displacement_socket->identifier); nodeRemLink(ntree, displacement_link); nodeAddLink(ntree, displacement_node, displacement_socket, tonode, tosock); - ntreeUpdateTree(G.main, ntree); + BKE_ntree_update_main_tree(G.main, ntree, nullptr); } /* Re-link displacement output to unconnected normal sockets via bump node. @@ -773,11 +768,11 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod nodeRemLink(ntree, displacement_link); /* Convert displacement vector to bump height. */ - bNode *dot_node = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH); - bNode *geo_node = nodeAddStaticNode(NULL, ntree, SH_NODE_NEW_GEOMETRY); + bNode *dot_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_VECTOR_MATH); + bNode *geo_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_NEW_GEOMETRY); bNodeSocket *normal_socket = ntree_shader_node_find_output(geo_node, "Normal"); - bNodeSocket *dot_input1 = dot_node->inputs.first; - bNodeSocket *dot_input2 = dot_input1->next; + bNodeSocket *dot_input1 = static_cast<bNodeSocket *>(dot_node->inputs.first); + bNodeSocket *dot_input2 = static_cast<bNodeSocket *>(dot_input1->next); dot_node->custom1 = NODE_VECTOR_MATH_DOT_PRODUCT; nodeAddLink(ntree, displacement_node, displacement_socket, dot_node, dot_input1); @@ -788,11 +783,11 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod /* We can't connect displacement to normal directly, use bump node for that * and hope that it gives good enough approximation. */ - bNode *bump_node = nodeAddStaticNode(NULL, ntree, SH_NODE_BUMP); + bNode *bump_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_BUMP); bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height"); bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal"); - BLI_assert(bump_input_socket != NULL); - BLI_assert(bump_output_socket != NULL); + BLI_assert(bump_input_socket != nullptr); + BLI_assert(bump_output_socket != nullptr); /* Connect bump node to where displacement output was originally * connected to. */ @@ -803,12 +798,12 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod geo_node->tmp_flag = -2; bump_node->tmp_flag = -2; - ntreeUpdateTree(G.main, ntree); + BKE_ntree_update_main_tree(G.main, ntree, nullptr); /* Connect all free-standing Normal inputs and relink geometry/coordinate nodes. */ ntree_shader_link_builtin_normal(ntree, bump_node, bump_output_socket); /* We modified the tree, it needs to be updated now. */ - ntreeUpdateTree(G.main, ntree); + BKE_ntree_update_main_tree(G.main, ntree, nullptr); } static void node_tag_branch_as_derivative(bNode *node, int dx) @@ -868,12 +863,12 @@ static bool ntree_shader_implicit_closure_cast(bNodeTree *ntree) else if ((link->fromsock->type == SOCK_SHADER) && (link->tosock->type != SOCK_SHADER)) { /* Meh. Not directly visible to the user. But better than nothing. */ fprintf(stderr, "Shader Nodetree Error: Invalid implicit socket conversion\n"); - ntreeUpdateTree(G.main, ntree); + BKE_ntree_update_main_tree(G.main, ntree, nullptr); return false; } } if (modified) { - ntreeUpdateTree(G.main, ntree); + BKE_ntree_update_main_tree(G.main, ntree, nullptr); } return true; } @@ -1129,7 +1124,8 @@ static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node break; } - /* Manually add the link to the socket to avoid calling ntreeUpdateTree in the loop. */ + /* Manually add the link to the socket to avoid calling + * BKE_ntree_update_main_tree(G.main, oop, nullptr. */ fromsock->link = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock); BLI_assert(fromsock->link); } @@ -1145,23 +1141,23 @@ static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node nodeAddLink( ntree, thickness_link->fromnode, thickness_link->fromsock, output_node, thickness_output); } - ntreeUpdateTree(G.main, ntree); + BKE_ntree_update_main_tree(G.main, ntree, nullptr); MEM_freeN(nodes_copy); } -/* This one needs to work on a local tree. */ void ntreeGPUMaterialNodes(bNodeTree *localtree, GPUMaterial *mat) { bNodeTreeExec *exec; bNode *output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE); + ntree_shader_groups_remove_muted_links(localtree); ntree_shader_groups_expand_inputs(localtree); ntree_shader_groups_flatten(localtree); - if (output == NULL) { + if (output == nullptr) { /* Search again, now including flattened nodes. */ output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE); } @@ -1186,7 +1182,6 @@ void ntreeGPUMaterialNodes(bNodeTree *localtree, GPUMaterial *mat) nodeChainIterBackwards(localtree, node, ntree_shader_bump_branches, localtree, 0); } } - exec = ntreeShaderBeginExecTree(localtree); ntreeExecGPUNodes(exec, mat, output); LISTBASE_FOREACH (bNode *, node, &localtree->nodes) { @@ -1201,19 +1196,17 @@ bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key) { - bNodeTreeExec *exec; - bNode *node; - /* ensures only a single output node is enabled */ ntreeSetOutput(ntree); /* common base initialization */ - exec = ntree_exec_begin(context, ntree, parent_key); + bNodeTreeExec *exec = ntree_exec_begin(context, ntree, parent_key); /* allocate the thread stack listbase array */ - exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"); + exec->threadstack = static_cast<ListBase *>( + MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array")); - for (node = exec->nodetree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &exec->nodetree->nodes) { node->need_exec = 1; } @@ -1236,8 +1229,8 @@ bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree) exec = ntreeShaderBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE); - /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes, - * which only store the ntree pointer. Should be fixed at some point! + /* XXX: this should not be necessary, but is still used for compositor/shader/texture nodes, + * which only store the `ntree` pointer. Should be fixed at some point! */ ntree->execdata = exec; @@ -1246,12 +1239,9 @@ bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree) void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec) { - bNodeThreadStack *nts; - int a; - if (exec->threadstack) { - for (a = 0; a < BLENDER_MAX_THREADS; a++) { - for (nts = exec->threadstack[a].first; nts; nts = nts->next) { + for (int a = 0; a < BLENDER_MAX_THREADS; a++) { + LISTBASE_FOREACH (bNodeThreadStack *, nts, &exec->threadstack[a]) { if (nts->stack) { MEM_freeN(nts->stack); } @@ -1260,7 +1250,7 @@ void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec) } MEM_freeN(exec->threadstack); - exec->threadstack = NULL; + exec->threadstack = nullptr; } ntree_exec_end(exec); @@ -1274,6 +1264,6 @@ void ntreeShaderEndExecTree(bNodeTreeExec *exec) ntreeShaderEndExecTree_internal(exec); /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */ - ntree->execdata = NULL; + ntree->execdata = nullptr; } } diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.cc index 1804bbcd22a..8ea690a426f 100644 --- a/source/blender/nodes/shader/node_shader_util.c +++ b/source/blender/nodes/shader/node_shader_util.cc @@ -23,14 +23,16 @@ #include "DNA_node_types.h" -#include "node_shader_util.h" +#include "node_shader_util.hh" + +#include "NOD_socket_search_link.hh" #include "node_exec.h" bool sh_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree, const char **r_disabled_hint) { if (!STREQ(ntree->idname, "ShaderNodeTree")) { - *r_disabled_hint = "Not a shader node tree"; + *r_disabled_hint = TIP_("Not a shader node tree"); return false; } return true; @@ -40,32 +42,32 @@ static bool sh_fn_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree, const char **r_disabled_hint) { - if (!STREQ(ntree->idname, "ShaderNodeTree") && !STREQ(ntree->idname, "GeometryNodeTree")) { - *r_disabled_hint = "Not a shader or geometry node tree"; + if (!STR_ELEM(ntree->idname, "ShaderNodeTree", "GeometryNodeTree")) { + *r_disabled_hint = TIP_("Not a shader or geometry node tree"); return false; } return true; } -void sh_node_type_base( - struct bNodeType *ntype, int type, const char *name, short nclass, short flag) +void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass) { - node_type_base(ntype, type, name, nclass, flag); + node_type_base(ntype, type, name, nclass); ntype->poll = sh_node_poll_default; ntype->insert_link = node_insert_link_default; - ntype->update_internal_links = node_update_internal_links_default; + ntype->gather_link_search_ops = blender::nodes::search_link_ops_for_basic_node; } -void sh_fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag) +void sh_fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass) { - sh_node_type_base(ntype, type, name, nclass, flag); + sh_node_type_base(ntype, type, name, nclass); ntype->poll = sh_fn_poll_default; + ntype->gather_link_search_ops = blender::nodes::search_link_ops_for_basic_node; } /* ****** */ -void nodestack_get_vec(float *in, short type_in, bNodeStack *ns) +static void nodestack_get_vec(float *in, short type_in, bNodeStack *ns) { const float *from = ns->vec; @@ -108,11 +110,11 @@ void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns) { memset(gs, 0, sizeof(*gs)); - if (ns == NULL) { - /* node_get_stack() will generate NULL bNodeStack pointers + if (ns == nullptr) { + /* node_get_stack() will generate nullptr bNodeStack pointers * for unknown/unsupported types of sockets. */ zero_v4(gs->vec); - gs->link = NULL; + gs->link = nullptr; gs->type = GPU_NONE; gs->hasinput = false; gs->hasoutput = false; @@ -120,7 +122,7 @@ void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns) } else { nodestack_get_vec(gs->vec, type, ns); - gs->link = ns->data; + gs->link = (GPUNodeLink *)ns->data; if (type == SOCK_FLOAT) { gs->type = GPU_FLOAT; @@ -160,11 +162,9 @@ void node_data_from_gpu_stack(bNodeStack *ns, GPUNodeStack *gs) static void gpu_stack_from_data_list(GPUNodeStack *gs, ListBase *sockets, bNodeStack **ns) { - bNodeSocket *sock; int i; - - for (sock = sockets->first, i = 0; sock; sock = sock->next, i++) { - node_gpu_stack_from_data(&gs[i], sock->type, ns[i]); + LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, sockets, i) { + node_gpu_stack_from_data(&gs[i], socket->type, ns[i]); } gs[i].end = true; @@ -172,10 +172,8 @@ static void gpu_stack_from_data_list(GPUNodeStack *gs, ListBase *sockets, bNodeS static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs) { - bNodeSocket *sock; int i; - - for (sock = sockets->first, i = 0; sock; sock = sock->next, i++) { + LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, sockets, i) { node_data_from_gpu_stack(ns[i], &gs[i]); } } @@ -183,14 +181,14 @@ static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNode bNode *nodeGetActiveTexture(bNodeTree *ntree) { /* this is the node we texture paint and draw in textured draw */ - bNode *node, *tnode, *inactivenode = NULL, *activetexnode = NULL, *activegroup = NULL; + bNode *inactivenode = nullptr, *activetexnode = nullptr, *activegroup = nullptr; bool hasgroup = false; if (!ntree) { - return NULL; + return nullptr; } - for (node = ntree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & NODE_ACTIVE_TEXTURE) { activetexnode = node; /* if active we can return immediately */ @@ -213,7 +211,7 @@ bNode *nodeGetActiveTexture(bNodeTree *ntree) /* first, check active group for textures */ if (activegroup) { - tnode = nodeGetActiveTexture((bNodeTree *)activegroup->id); + bNode *tnode = nodeGetActiveTexture((bNodeTree *)activegroup->id); /* active node takes priority, so ignore any other possible nodes here */ if (tnode) { return tnode; @@ -226,9 +224,9 @@ bNode *nodeGetActiveTexture(bNodeTree *ntree) if (hasgroup) { /* node active texture node in this tree, look inside groups */ - for (node = ntree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->type == NODE_GROUP) { - tnode = nodeGetActiveTexture((bNodeTree *)node->id); + bNode *tnode = nodeGetActiveTexture((bNodeTree *)node->id); if (tnode && ((tnode->flag & NODE_ACTIVE_TEXTURE) || !inactivenode)) { return tnode; } @@ -258,7 +256,7 @@ void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node do_it = false; /* for groups, only execute outputs for edited group */ if (node->typeinfo->nclass == NODE_CLASS_OUTPUT) { - if ((output_node != NULL) && (node == output_node)) { + if ((output_node != nullptr) && (node == output_node)) { do_it = true; } } @@ -282,11 +280,11 @@ void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node void node_shader_gpu_bump_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link) { if (node->branch_tag == 1) { - /* Add one time the value fo derivative to the input vector. */ + /* Add one time the value for derivative to the input vector. */ GPU_link(mat, "dfdx_v3", *link, link); } else if (node->branch_tag == 2) { - /* Add one time the value fo derivative to the input vector. */ + /* Add one time the value for derivative to the input vector. */ GPU_link(mat, "dfdy_v3", *link, link); } else { @@ -308,7 +306,7 @@ void node_shader_gpu_tex_mapping(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *UNUSED(out)) { - NodeTexBase *base = node->storage; + NodeTexBase *base = (NodeTexBase *)node->storage; TexMapping *texmap = &base->tex_mapping; float domin = (texmap->flag & TEXMAP_CLIP_MIN) != 0; float domax = (texmap->flag & TEXMAP_CLIP_MAX) != 0; diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.hh index c647b86a19a..5a5b4f613f3 100644 --- a/source/blender/nodes/shader/node_shader_util.h +++ b/source/blender/nodes/shader/node_shader_util.hh @@ -23,29 +23,21 @@ #pragma once -#include <float.h> -#include <math.h> -#include <string.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_ID.h" -#include "DNA_color_types.h" -#include "DNA_customdata_types.h" -#include "DNA_image_types.h" -#include "DNA_material_types.h" -#include "DNA_node_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_texture_types.h" +#include <cfloat> +#include <cmath> +#include <cstring> #include "BLI_blenlib.h" +#include "BLI_color.hh" #include "BLI_math.h" #include "BLI_math_base_safe.h" +#include "BLI_math_vec_types.hh" #include "BLI_rand.h" #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLT_translation.h" + #include "BKE_colorband.h" #include "BKE_colortools.h" #include "BKE_global.h" @@ -55,53 +47,46 @@ #include "BKE_node.h" #include "BKE_texture.h" -#include "NOD_shader.h" -#include "node_util.h" - -#include "BLT_translation.h" - -#include "IMB_colormanagement.h" +#include "DNA_ID.h" +#include "DNA_color_types.h" +#include "DNA_customdata_types.h" +#include "DNA_image_types.h" +#include "DNA_material_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_texture_types.h" -#include "RE_pipeline.h" -#include "RE_texture.h" +#include "FN_multi_function_builder.hh" #include "GPU_material.h" #include "GPU_texture.h" #include "GPU_uniform_buffer.h" -#ifdef __cplusplus -# include "FN_multi_function_builder.hh" +#include "IMB_colormanagement.h" -# include "NOD_multi_function.hh" -# include "NOD_socket_declarations.hh" +#include "MEM_guardedalloc.h" -# include "BLI_color.hh" -# include "BLI_float3.hh" +#include "NOD_multi_function.hh" +#include "NOD_shader.h" +#include "NOD_socket_declarations.hh" +#include "node_util.h" -extern "C" { -#endif +#include "RE_pipeline.h" +#include "RE_texture.h" bool sh_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree, const char **r_disabled_hint); -void sh_node_type_base( - struct bNodeType *ntype, int type, const char *name, short nclass, short flag); -void sh_fn_node_type_base( - struct bNodeType *ntype, int type, const char *name, short nclass, short flag); +void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass); +void sh_fn_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass); /* ********* exec data struct, remains internal *********** */ -typedef struct ShaderCallData { - /* Empty for now, may be reused if we convert shader to texture nodes. */ - int dummy; -} ShaderCallData; - -typedef struct XYZ_to_RGB /* Transposed #imbuf_xyz_to_rgb, passed as 3x vec3. */ +struct XYZ_to_RGB /* Transposed #imbuf_xyz_to_rgb, passed as 3x vec3. */ { float r[3], g[3], b[3]; -} XYZ_to_RGB; - -void nodestack_get_vec(float *in, short type_in, bNodeStack *ns); +}; void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, struct bNodeStack *ns); void node_data_from_gpu_stack(struct bNodeStack *ns, struct GPUNodeStack *gs); @@ -120,7 +105,3 @@ void ntreeExecGPUNodes(struct bNodeTreeExec *exec, struct GPUMaterial *mat, struct bNode *output_node); void get_XYZ_to_RGB_for_gpu(XYZ_to_RGB *data); - -#ifdef __cplusplus -} -#endif diff --git a/source/blender/nodes/shader/nodes/node_shader_add_shader.c b/source/blender/nodes/shader/nodes/node_shader_add_shader.cc index 12c138ac9d5..73d5c12ce96 100644 --- a/source/blender/nodes/shader/nodes/node_shader_add_shader.c +++ b/source/blender/nodes/shader/nodes/node_shader_add_shader.cc @@ -17,20 +17,16 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_add_shader_cc { -static bNodeSocketTemplate sh_node_add_shader_in[] = { - {SOCK_SHADER, N_("Shader")}, - {SOCK_SHADER, N_("Shader")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_add_shader_out[] = { - {SOCK_SHADER, N_("Shader")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Shader>(N_("Shader")); + b.add_input<decl::Shader>(N_("Shader"), "Shader_001"); + b.add_output<decl::Shader>(N_("Shader")); +} static int node_shader_gpu_add_shader(GPUMaterial *mat, bNode *node, @@ -41,16 +37,18 @@ static int node_shader_gpu_add_shader(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_add_shader", in, out); } +} // namespace blender::nodes::node_shader_add_shader_cc + /* node type definition */ -void register_node_type_sh_add_shader(void) +void register_node_type_sh_add_shader() { + namespace file_ns = blender::nodes::node_shader_add_shader_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_ADD_SHADER, "Add Shader", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_add_shader_in, sh_node_add_shader_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_add_shader); + sh_node_type_base(&ntype, SH_NODE_ADD_SHADER, "Add Shader", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_add_shader); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.cc index abe80ebcefb..9c64594aab8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c +++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.cc @@ -17,22 +17,30 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +#include "UI_interface.h" +#include "UI_resources.h" -static bNodeSocketTemplate sh_node_ambient_occlusion_in[] = { - {SOCK_RGBA, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Distance"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_ambient_occlusion_cc { -static bNodeSocketTemplate sh_node_ambient_occlusion_out[] = { - {SOCK_RGBA, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("AO"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Distance")).default_value(1.0f).min(0.0f).max(1000.0f); + b.add_input<decl::Vector>(N_("Normal")).min(-1.0f).max(1.0f).hide_value(); + b.add_output<decl::Color>(N_("Color")); + b.add_output<decl::Float>(N_("AO")); +} + +static void node_shader_buts_ambient_occlusion(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "samples", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + uiItemR(layout, ptr, "inside", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + uiItemR(layout, ptr, "only_local", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); +} static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *node, @@ -64,16 +72,20 @@ static void node_shader_init_ambient_occlusion(bNodeTree *UNUSED(ntree), bNode * node->custom2 = 0; } +} // namespace blender::nodes::node_shader_ambient_occlusion_cc + /* node type definition */ -void register_node_type_sh_ambient_occlusion(void) +void register_node_type_sh_ambient_occlusion() { + namespace file_ns = blender::nodes::node_shader_ambient_occlusion_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, sh_node_ambient_occlusion_in, sh_node_ambient_occlusion_out); - node_type_init(&ntype, node_shader_init_ambient_occlusion); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_ambient_occlusion); + sh_node_type_base(&ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_ambient_occlusion; + node_type_init(&ntype, file_ns::node_shader_init_ambient_occlusion); + node_type_gpu(&ntype, file_ns::node_shader_gpu_ambient_occlusion); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.c b/source/blender/nodes/shader/nodes/node_shader_attribute.cc index 9b3122e38e0..cf1b49ba29c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_attribute.c +++ b/source/blender/nodes/shader/nodes/node_shader_attribute.cc @@ -17,21 +17,30 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +#include "UI_interface.h" +#include "UI_resources.h" -static bNodeSocketTemplate sh_node_attribute_out[] = { - {SOCK_RGBA, N_("Color")}, - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_FACTOR}, - {SOCK_FLOAT, N_("Alpha"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_FACTOR}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_attribute_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Color>(N_("Color")); + b.add_output<decl::Vector>(N_("Vector")); + b.add_output<decl::Float>(N_("Fac")); + b.add_output<decl::Float>(N_("Alpha")); +} + +static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "attribute_type", UI_ITEM_R_SPLIT_EMPTY_NAME, IFACE_("Type"), ICON_NONE); + uiItemR(layout, ptr, "attribute_name", UI_ITEM_R_SPLIT_EMPTY_NAME, IFACE_("Name"), ICON_NONE); +} static void node_shader_init_attribute(bNodeTree *UNUSED(ntree), bNode *node) { - NodeShaderAttribute *attr = MEM_callocN(sizeof(NodeShaderAttribute), "NodeShaderAttribute"); + NodeShaderAttribute *attr = MEM_cnew<NodeShaderAttribute>("NodeShaderAttribute"); node->storage = attr; } @@ -41,7 +50,7 @@ static int node_shader_gpu_attribute(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - NodeShaderAttribute *attr = node->storage; + NodeShaderAttribute *attr = static_cast<NodeShaderAttribute *>(node->storage); bool is_varying = attr->type == SHD_ATTRIBUTE_GEOMETRY; if (GPU_material_is_volume_shader(mat) && is_varying) { @@ -73,25 +82,30 @@ static int node_shader_gpu_attribute(GPUMaterial *mat, GPU_stack_link(mat, node, "node_attribute", in, out, cd_attr); - /* for each output. */ - for (int i = 0; sh_node_attribute_out[i].type != -1; i++) { + int i; + LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->outputs, i) { node_shader_gpu_bump_tex_coord(mat, node, &out[i].link); } return 1; } +} // namespace blender::nodes::node_shader_attribute_cc + /* node type definition */ -void register_node_type_sh_attribute(void) +void register_node_type_sh_attribute() { + namespace file_ns = blender::nodes::node_shader_attribute_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_ATTRIBUTE, "Attribute", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, sh_node_attribute_out); - node_type_init(&ntype, node_shader_init_attribute); + sh_node_type_base(&ntype, SH_NODE_ATTRIBUTE, "Attribute", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_attribute; + node_type_init(&ntype, file_ns::node_shader_init_attribute); node_type_storage( &ntype, "NodeShaderAttribute", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_attribute); + node_type_gpu(&ntype, file_ns::node_shader_gpu_attribute); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_background.c b/source/blender/nodes/shader/nodes/node_shader_background.cc index 4301a9f716f..3b9e71cf842 100644 --- a/source/blender/nodes/shader/nodes/node_shader_background.c +++ b/source/blender/nodes/shader/nodes/node_shader_background.cc @@ -17,21 +17,16 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_background_cc { -static bNodeSocketTemplate sh_node_background_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_background_out[] = { - {SOCK_SHADER, N_("Background")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Float>(N_("Strength")).default_value(1.0f).min(0.0f).max(1000000.0f); + b.add_output<decl::Shader>(N_("Background")); +} static int node_shader_gpu_background(GPUMaterial *mat, bNode *node, @@ -42,16 +37,18 @@ static int node_shader_gpu_background(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_background", in, out); } +} // namespace blender::nodes::node_shader_background_cc + /* node type definition */ -void register_node_type_sh_background(void) +void register_node_type_sh_background() { + namespace file_ns = blender::nodes::node_shader_background_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BACKGROUND, "Background", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_background_in, sh_node_background_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_background); + sh_node_type_base(&ntype, SH_NODE_BACKGROUND, "Background", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_background); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bevel.c b/source/blender/nodes/shader/nodes/node_shader_bevel.cc index d6bdda30e94..dfde18d8e2a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bevel.c +++ b/source/blender/nodes/shader/nodes/node_shader_bevel.cc @@ -17,20 +17,24 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +#include "UI_interface.h" +#include "UI_resources.h" -static bNodeSocketTemplate sh_node_bevel_in[] = { - {SOCK_FLOAT, N_("Radius"), 0.05f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_bevel_cc { -static bNodeSocketTemplate sh_node_bevel_out[] = { - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Radius")).default_value(0.05f).min(0.0f).max(1000.0f); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_output<decl::Vector>(N_("Normal")); +} + +static void node_shader_buts_bevel(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "samples", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); +} static void node_shader_init_bevel(bNodeTree *UNUSED(ntree), bNode *node) { @@ -50,16 +54,20 @@ static int gpu_shader_bevel(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_bevel", in, out); } +} // namespace blender::nodes::node_shader_bevel_cc + /* node type definition */ -void register_node_type_sh_bevel(void) +void register_node_type_sh_bevel() { + namespace file_ns = blender::nodes::node_shader_bevel_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BEVEL, "Bevel", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, sh_node_bevel_in, sh_node_bevel_out); - node_type_init(&ntype, node_shader_init_bevel); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, gpu_shader_bevel); + sh_node_type_base(&ntype, SH_NODE_BEVEL, "Bevel", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_bevel; + node_type_init(&ntype, file_ns::node_shader_init_bevel); + node_type_gpu(&ntype, file_ns::gpu_shader_bevel); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_blackbody.c b/source/blender/nodes/shader/nodes/node_shader_blackbody.cc index 95c35affc27..85e2ed08403 100644 --- a/source/blender/nodes/shader/nodes/node_shader_blackbody.c +++ b/source/blender/nodes/shader/nodes/node_shader_blackbody.cc @@ -17,18 +17,15 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** Blackbody ******************** */ -static bNodeSocketTemplate sh_node_blackbody_in[] = { - {SOCK_FLOAT, N_("Temperature"), 1500.0f, 0.0f, 0.0f, 0.0f, 800.0f, 12000.0f}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_blackbody_cc { -static bNodeSocketTemplate sh_node_blackbody_out[] = { - {SOCK_RGBA, N_("Color")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Temperature")).default_value(1500.0f).min(800.0f).max(12000.0f); + b.add_output<decl::Color>(N_("Color")); +} static int node_shader_gpu_blackbody(GPUMaterial *mat, bNode *node, @@ -37,7 +34,7 @@ static int node_shader_gpu_blackbody(GPUMaterial *mat, GPUNodeStack *out) { const int size = CM_TABLE + 1; - float *data = MEM_mallocN(sizeof(float) * size * 4, "blackbody texture"); + float *data = static_cast<float *>(MEM_mallocN(sizeof(float) * size * 4, "blackbody texture")); blackbody_temperature_to_rgb_table(data, size, 965.0f, 12000.0f); @@ -47,17 +44,19 @@ static int node_shader_gpu_blackbody(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_blackbody", in, out, ramp_texture, GPU_constant(&layer)); } +} // namespace blender::nodes::node_shader_blackbody_cc + /* node type definition */ -void register_node_type_sh_blackbody(void) +void register_node_type_sh_blackbody() { + namespace file_ns = blender::nodes::node_shader_blackbody_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BLACKBODY, "Blackbody", NODE_CLASS_CONVERTER, 0); + sh_node_type_base(&ntype, SH_NODE_BLACKBODY, "Blackbody", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::node_declare; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_socket_templates(&ntype, sh_node_blackbody_in, sh_node_blackbody_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_blackbody); + node_type_gpu(&ntype, file_ns::node_shader_gpu_blackbody); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_brightness.c b/source/blender/nodes/shader/nodes/node_shader_brightness.cc index 4f375c666de..66bfaba2785 100644 --- a/source/blender/nodes/shader/nodes/node_shader_brightness.c +++ b/source/blender/nodes/shader/nodes/node_shader_brightness.cc @@ -17,21 +17,17 @@ * All rights reserved. */ -#include "node_shader_util.h" +#include "node_shader_util.hh" -/* **************** Bright and contrast ******************** */ +namespace blender::nodes::node_shader_brightness_cc { -static bNodeSocketTemplate sh_node_brightcontrast_in[] = { - {SOCK_RGBA, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f}, - {SOCK_FLOAT, N_("Bright"), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, - {SOCK_FLOAT, N_("Contrast"), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_brightcontrast_out[] = { - {SOCK_RGBA, N_("Color")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Bright")).default_value(0.0f).min(-100.0f).max(100.0f); + b.add_input<decl::Float>(N_("Contrast")).default_value(0.0f).min(-100.0f).max(100.0f); + b.add_output<decl::Color>(N_("Color")); +} static int gpu_shader_brightcontrast(GPUMaterial *mat, bNode *node, @@ -42,15 +38,17 @@ static int gpu_shader_brightcontrast(GPUMaterial *mat, return GPU_stack_link(mat, node, "brightness_contrast", in, out); } -void register_node_type_sh_brightcontrast(void) +} // namespace blender::nodes::node_shader_brightness_cc + +void register_node_type_sh_brightcontrast() { + namespace file_ns = blender::nodes::node_shader_brightness_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, 0); - node_type_socket_templates(&ntype, sh_node_brightcontrast_in, sh_node_brightcontrast_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, gpu_shader_brightcontrast); + sh_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_brightcontrast); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c deleted file mode 100644 index 7c080337838..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_bsdf_anisotropic_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Anisotropy"), 0.5f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f}, - {SOCK_FLOAT, N_("Rotation"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_VECTOR, N_("Tangent"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_bsdf_anisotropic_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; - -static void node_shader_init_anisotropic(bNodeTree *UNUSED(ntree), bNode *node) -{ - node->custom1 = SHD_GLOSSY_GGX; -} - -static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - if (!in[4].link) { - GPU_link(mat, "world_normals_get", &in[4].link); - } - - GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY); - - float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; - - GPU_stack_link(mat, node, "node_bsdf_anisotropic", in, out); - - GPU_stack_eval_link( - mat, node, "node_bsdf_anisotropic_eval", in, out, GPU_constant(&use_multi_scatter)); - - return true; -} - -/* node type definition */ -void register_node_type_sh_bsdf_anisotropic(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_BSDF_ANISOTROPIC, "Anisotropic BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_bsdf_anisotropic_in, sh_node_bsdf_anisotropic_out); - node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, node_shader_init_anisotropic); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_bsdf_anisotropic); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc new file mode 100644 index 00000000000..3f0749ab2af --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc @@ -0,0 +1,96 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_bsdf_anisotropic_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Float>(N_("Roughness")) + .default_value(0.5f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Anisotropy")).default_value(0.5f).min(-1.0f).max(1.0f); + b.add_input<decl::Float>(N_("Rotation")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Vector>(N_("Tangent")).hide_value(); + b.add_output<decl::Shader>(N_("BSDF")); +} + +static void node_shader_buts_anisotropic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "distribution", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} + +static void node_shader_init_anisotropic(bNodeTree *UNUSED(ntree), bNode *node) +{ + node->custom1 = SHD_GLOSSY_GGX; +} + +static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + if (!in[4].link) { + GPU_link(mat, "world_normals_get", &in[4].link); + } + + GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY); + + float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; + + return GPU_stack_link(mat, + node, + "node_bsdf_anisotropic", + in, + out, + GPU_constant(&use_multi_scatter), + GPU_constant(&node->ssr_id)); +} + +} // namespace blender::nodes::node_shader_bsdf_anisotropic_cc + +/* node type definition */ +void register_node_type_sh_bsdf_anisotropic() +{ + namespace file_ns = blender::nodes::node_shader_bsdf_anisotropic_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_BSDF_ANISOTROPIC, "Anisotropic BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_anisotropic; + node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); + node_type_init(&ntype, file_ns::node_shader_init_anisotropic); + node_type_gpu(&ntype, file_ns::node_shader_gpu_bsdf_anisotropic); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.cc index 3aa3b70025e..5848ca76cdd 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.cc @@ -17,22 +17,21 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_bsdf_diffuse_cc { -static bNodeSocketTemplate sh_node_bsdf_diffuse_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_bsdf_diffuse_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Float>(N_("Roughness")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_output<decl::Shader>(N_("BSDF")); +} static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *node, @@ -46,21 +45,22 @@ static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE); - GPU_stack_link(mat, node, "node_bsdf_diffuse", in, out); - return GPU_stack_eval_link(mat, node, "node_bsdf_diffuse_eval", in, out); + return GPU_stack_link(mat, node, "node_bsdf_diffuse", in, out); } +} // namespace blender::nodes::node_shader_bsdf_diffuse_cc + /* node type definition */ -void register_node_type_sh_bsdf_diffuse(void) +void register_node_type_sh_bsdf_diffuse() { + namespace file_ns = blender::nodes::node_shader_bsdf_diffuse_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BSDF_DIFFUSE, "Diffuse BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_bsdf_diffuse_in, sh_node_bsdf_diffuse_out); + sh_node_type_base(&ntype, SH_NODE_BSDF_DIFFUSE, "Diffuse BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_bsdf_diffuse); + node_type_gpu(&ntype, file_ns::node_shader_gpu_bsdf_diffuse); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c deleted file mode 100644 index e164e32723e..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_bsdf_glass_in[] = { - {SOCK_RGBA, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_bsdf_glass_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; - -static void node_shader_init_glass(bNodeTree *UNUSED(ntree), bNode *node) -{ - node->custom1 = SHD_GLOSSY_BECKMANN; -} - -static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - if (!in[3].link) { - GPU_link(mat, "world_normals_get", &in[3].link); - } - - if (node->custom1 == SHD_GLOSSY_SHARP) { - GPU_link(mat, "set_value_zero", &in[1].link); - } - - GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY | GPU_MATFLAG_REFRACT); - - float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; - - GPUNodeLink *reflection_weight; - GPUNodeLink *refraction_weight; - - GPU_stack_link(mat, - node, - "node_bsdf_glass", - in, - out, - GPU_constant(&use_multi_scatter), - &reflection_weight, - &refraction_weight); - - return GPU_stack_eval_link(mat, - node, - "node_bsdf_glass_eval", - in, - out, - GPU_constant(&use_multi_scatter), - reflection_weight, - refraction_weight); -} - -/* node type definition */ -void register_node_type_sh_bsdf_glass(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_BSDF_GLASS, "Glass BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_bsdf_glass_in, sh_node_bsdf_glass_out); - node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, node_shader_init_glass); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_bsdf_glass); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc new file mode 100644 index 00000000000..47d4b87198b --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc @@ -0,0 +1,85 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_bsdf_glass_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Roughness")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("IOR")).default_value(1.45f).min(0.0f).max(1000.0f); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_output<decl::Shader>(N_("BSDF")); +} + +static void node_shader_init_glass(bNodeTree *UNUSED(ntree), bNode *node) +{ + node->custom1 = SHD_GLOSSY_BECKMANN; +} + +static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + if (!in[3].link) { + GPU_link(mat, "world_normals_get", &in[3].link); + } + + if (node->custom1 == SHD_GLOSSY_SHARP) { + GPU_link(mat, "set_value_zero", &in[1].link); + } + + GPU_material_flag_set(mat, (eGPUMatFlag)(GPU_MATFLAG_GLOSSY | GPU_MATFLAG_REFRACT)); + + float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; + + return GPU_stack_link(mat, + node, + "node_bsdf_glass", + in, + out, + GPU_constant(&use_multi_scatter), + GPU_constant(&node->ssr_id)); +} + +} // namespace blender::nodes::node_shader_bsdf_glass_cc + +/* node type definition */ +void register_node_type_sh_bsdf_glass() +{ + namespace file_ns = blender::nodes::node_shader_bsdf_glass_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_BSDF_GLASS, "Glass BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); + node_type_init(&ntype, file_ns::node_shader_init_glass); + node_type_gpu(&ntype, file_ns::node_shader_gpu_bsdf_glass); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc index e234dafb98e..03a3e634f56 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc @@ -17,22 +17,21 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_bsdf_glossy_cc { -static bNodeSocketTemplate sh_node_bsdf_glossy_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_bsdf_glossy_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Float>(N_("Roughness")) + .default_value(0.5f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_output<decl::Shader>(N_("BSDF")); +} static void node_shader_init_glossy(bNodeTree *UNUSED(ntree), bNode *node) { @@ -57,22 +56,29 @@ static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; - GPU_stack_link(mat, node, "node_bsdf_glossy", in, out); - return GPU_stack_eval_link( - mat, node, "node_bsdf_glossy_eval", in, out, GPU_constant(&use_multi_scatter)); + return GPU_stack_link(mat, + node, + "node_bsdf_glossy", + in, + out, + GPU_constant(&use_multi_scatter), + GPU_constant(&node->ssr_id)); } +} // namespace blender::nodes::node_shader_bsdf_glossy_cc + /* node type definition */ -void register_node_type_sh_bsdf_glossy(void) +void register_node_type_sh_bsdf_glossy() { + namespace file_ns = blender::nodes::node_shader_bsdf_glossy_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BSDF_GLOSSY, "Glossy BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_bsdf_glossy_in, sh_node_bsdf_glossy_out); + sh_node_type_base(&ntype, SH_NODE_BSDF_GLOSSY, "Glossy BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, node_shader_init_glossy); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_bsdf_glossy); + node_type_init(&ntype, file_ns::node_shader_init_glossy); + node_type_gpu(&ntype, file_ns::node_shader_gpu_bsdf_glossy); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.cc index 1f07cb1d202..3be2bd22f60 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.cc @@ -17,24 +17,39 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +#include "UI_interface.h" +#include "UI_resources.h" -static bNodeSocketTemplate sh_node_bsdf_hair_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Offset"), 0.0f, 0.0f, 0.0f, 0.0f, -M_PI_2, M_PI_2, PROP_ANGLE}, - {SOCK_FLOAT, N_("RoughnessU"), 0.1f, 0.1f, 0.1f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("RoughnessV"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_VECTOR, N_("Tangent"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_bsdf_hair_cc { -static bNodeSocketTemplate sh_node_bsdf_hair_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Float>(N_("Offset")) + .default_value(0.0f) + .min(-M_PI_2) + .max(M_PI_2) + .subtype(PROP_ANGLE); + b.add_input<decl::Float>(N_("RoughnessU")) + .default_value(0.1f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("RoughnessV")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Tangent")).hide_value(); + b.add_output<decl::Shader>(N_("BSDF")); +} + +static void node_shader_buts_hair(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "component", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} static int node_shader_gpu_bsdf_hair(GPUMaterial *mat, bNode *node, @@ -45,17 +60,20 @@ static int node_shader_gpu_bsdf_hair(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_bsdf_hair", in, out); } +} // namespace blender::nodes::node_shader_bsdf_hair_cc + /* node type definition */ -void register_node_type_sh_bsdf_hair(void) +void register_node_type_sh_bsdf_hair() { + namespace file_ns = blender::nodes::node_shader_bsdf_hair_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BSDF_HAIR, "Hair BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_bsdf_hair_in, sh_node_bsdf_hair_out); + sh_node_type_base(&ntype, SH_NODE_BSDF_HAIR, "Hair BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_hair; node_type_size(&ntype, 150, 60, 200); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_bsdf_hair); + node_type_gpu(&ntype, file_ns::node_shader_gpu_bsdf_hair); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c deleted file mode 100644 index d9bcbbcd7a4..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2018 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -/* Color, melanin and absorption coefficient default to approximately same brownish hair. */ -static bNodeSocketTemplate sh_node_bsdf_hair_principled_in[] = { - {SOCK_RGBA, N_("Color"), 0.017513f, 0.005763f, 0.002059f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Melanin"), 0.8f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Melanin Redness"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_RGBA, N_("Tint"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Absorption Coefficient"), 0.245531f, 0.52f, 1.365f, 0.0f, 0.0f, 1000.0f}, - {SOCK_FLOAT, N_("Roughness"), 0.3f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Radial Roughness"), 0.3f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Coat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("IOR"), 1.55f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_FLOAT, - N_("Offset"), - 2.0f * ((float)M_PI) / 180.0f, - 0.0f, - 0.0f, - 0.0f, - -M_PI_2, - M_PI_2, - PROP_ANGLE}, - {SOCK_FLOAT, N_("Random Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Random Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Random"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_bsdf_hair_principled_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; - -/* Initialize the custom Parametrization property to Color. */ -static void node_shader_init_hair_principled(bNodeTree *UNUSED(ntree), bNode *node) -{ - node->custom1 = SHD_PRINCIPLED_HAIR_REFLECTANCE; -} - -/* Triggers (in)visibility of some sockets when changing Parametrization. */ -static void node_shader_update_hair_principled(bNodeTree *UNUSED(ntree), bNode *node) -{ - bNodeSocket *sock; - int parametrization = node->custom1; - - for (sock = node->inputs.first; sock; sock = sock->next) { - if (STREQ(sock->name, "Color")) { - if (parametrization == SHD_PRINCIPLED_HAIR_REFLECTANCE) { - sock->flag &= ~SOCK_UNAVAIL; - } - else { - sock->flag |= SOCK_UNAVAIL; - } - } - else if (STREQ(sock->name, "Melanin")) { - if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION) { - sock->flag &= ~SOCK_UNAVAIL; - } - else { - sock->flag |= SOCK_UNAVAIL; - } - } - else if (STREQ(sock->name, "Melanin Redness")) { - if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION) { - sock->flag &= ~SOCK_UNAVAIL; - } - else { - sock->flag |= SOCK_UNAVAIL; - } - } - else if (STREQ(sock->name, "Tint")) { - if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION) { - sock->flag &= ~SOCK_UNAVAIL; - } - else { - sock->flag |= SOCK_UNAVAIL; - } - } - else if (STREQ(sock->name, "Absorption Coefficient")) { - if (parametrization == SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION) { - sock->flag &= ~SOCK_UNAVAIL; - } - else { - sock->flag |= SOCK_UNAVAIL; - } - } - else if (STREQ(sock->name, "Random Color")) { - if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION) { - sock->flag &= ~SOCK_UNAVAIL; - } - else { - sock->flag |= SOCK_UNAVAIL; - } - } - } -} - -/* node type definition */ -void register_node_type_sh_bsdf_hair_principled(void) -{ - static bNodeType ntype; - - sh_node_type_base( - &ntype, SH_NODE_BSDF_HAIR_PRINCIPLED, "Principled Hair BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates( - &ntype, sh_node_bsdf_hair_principled_in, sh_node_bsdf_hair_principled_out); - node_type_size_preset(&ntype, NODE_SIZE_LARGE); - node_type_init(&ntype, node_shader_init_hair_principled); - node_type_storage(&ntype, "", NULL, NULL); - node_type_update(&ntype, node_shader_update_hair_principled); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.cc new file mode 100644 index 00000000000..7062888b5fb --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.cc @@ -0,0 +1,145 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2018 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_bsdf_hair_principled_cc { + +/* Color, melanin and absorption coefficient default to approximately same brownish hair. */ +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.017513f, 0.005763f, 0.002059f, 1.0f}); + b.add_input<decl::Float>(N_("Melanin")) + .default_value(0.8f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Melanin Redness")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Color>(N_("Tint")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Vector>(N_("Absorption Coefficient")) + .default_value({0.245531f, 0.52f, 1.365f}) + .min(0.0f) + .max(1000.0f); + b.add_input<decl::Float>(N_("Roughness")) + .default_value(0.3f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Radial Roughness")) + .default_value(0.3f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Coat")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("IOR")).default_value(1.55f).min(0.0f).max(1000.0f).subtype( + PROP_FACTOR); + b.add_input<decl::Float>(N_("Offset")) + .default_value(2.0f * ((float)M_PI) / 180.0f) + .min(-M_PI_2) + .max(M_PI_2) + .subtype(PROP_ANGLE); + b.add_input<decl::Float>(N_("Random Color")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Random Roughness")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Random")).hide_value(); + b.add_output<decl::Shader>(N_("BSDF")); +} + +static void node_shader_buts_principled_hair(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "parametrization", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} + +/* Initialize the custom Parametrization property to Color. */ +static void node_shader_init_hair_principled(bNodeTree *UNUSED(ntree), bNode *node) +{ + node->custom1 = SHD_PRINCIPLED_HAIR_REFLECTANCE; +} + +/* Triggers (in)visibility of some sockets when changing Parametrization. */ +static void node_shader_update_hair_principled(bNodeTree *ntree, bNode *node) +{ + int parametrization = node->custom1; + + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + if (STREQ(sock->name, "Color")) { + nodeSetSocketAvailability(ntree, sock, parametrization == SHD_PRINCIPLED_HAIR_REFLECTANCE); + } + else if (STREQ(sock->name, "Melanin")) { + nodeSetSocketAvailability( + ntree, sock, parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION); + } + else if (STREQ(sock->name, "Melanin Redness")) { + nodeSetSocketAvailability( + ntree, sock, parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION); + } + else if (STREQ(sock->name, "Tint")) { + nodeSetSocketAvailability( + ntree, sock, parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION); + } + else if (STREQ(sock->name, "Absorption Coefficient")) { + nodeSetSocketAvailability( + ntree, sock, parametrization == SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION); + } + else if (STREQ(sock->name, "Random Color")) { + nodeSetSocketAvailability( + ntree, sock, parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION); + } + } +} + +} // namespace blender::nodes::node_shader_bsdf_hair_principled_cc + +/* node type definition */ +void register_node_type_sh_bsdf_hair_principled() +{ + namespace file_ns = blender::nodes::node_shader_bsdf_hair_principled_cc; + + static bNodeType ntype; + + sh_node_type_base( + &ntype, SH_NODE_BSDF_HAIR_PRINCIPLED, "Principled Hair BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_principled_hair; + node_type_size_preset(&ntype, NODE_SIZE_LARGE); + node_type_init(&ntype, file_ns::node_shader_init_hair_principled); + node_type_update(&ntype, file_ns::node_shader_update_hair_principled); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c deleted file mode 100644 index 5fbf66d5a68..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_bsdf_principled_in[] = { - {SOCK_RGBA, N_("Base Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Subsurface"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_VECTOR, - N_("Subsurface Radius"), - 1.0f, - 0.2f, - 0.1f, - 0.0f, - 0.0f, - 100.0f, - PROP_NONE, - SOCK_COMPACT}, - {SOCK_RGBA, N_("Subsurface Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Subsurface IOR"), 1.4f, 0.0f, 0.0f, 0.0f, 1.01f, 3.8f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Subsurface Anisotropy"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Metallic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Specular"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Specular Tint"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Anisotropic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Anisotropic Rotation"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Sheen"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Sheen Tint"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Clearcoat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Clearcoat Roughness"), 0.03f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_FLOAT, N_("Transmission"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Transmission Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_RGBA, N_("Emission"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Emission Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f}, - {SOCK_FLOAT, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_VECTOR, - N_("Clearcoat Normal"), - 0.0f, - 0.0f, - 0.0f, - 1.0f, - -1.0f, - 1.0f, - PROP_NONE, - SOCK_HIDE_VALUE}, - {SOCK_VECTOR, N_("Tangent"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_bsdf_principled_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; - -static void node_shader_init_principled(bNodeTree *UNUSED(ntree), bNode *node) -{ - node->custom1 = SHD_GLOSSY_GGX; - node->custom2 = SHD_SUBSURFACE_RANDOM_WALK; -} - -#define socket_not_zero(sock) (in[sock].link || (clamp_f(in[sock].vec[0], 0.0f, 1.0f) > 1e-5f)) -#define socket_not_one(sock) \ - (in[sock].link || (clamp_f(in[sock].vec[0], 0.0f, 1.0f) < 1.0f - 1e-5f)) - -static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - /* Normals */ - if (!in[22].link) { - GPU_link(mat, "world_normals_get", &in[22].link); - } - - /* Clearcoat Normals */ - if (!in[23].link) { - GPU_link(mat, "world_normals_get", &in[23].link); - } - -#if 0 /* Not used at the moment. */ - /* Tangents */ - if (!in[24].link) { - GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); - GPU_link(mat, "tangent_orco_z", orco, &in[24].link); - GPU_link(mat, "node_tangent", in[24].link, &in[24].link); - } -#endif - - bool use_diffuse = socket_not_one(6) && socket_not_one(17); - bool use_subsurf = socket_not_zero(1) && use_diffuse; - bool use_refract = socket_not_one(6) && socket_not_zero(17); - bool use_transparency = socket_not_one(21); - // bool use_clear = socket_not_zero(14); - - uint flag = GPU_MATFLAG_GLOSSY; - if (use_diffuse) { - flag |= GPU_MATFLAG_DIFFUSE; - } - if (use_refract) { - flag |= GPU_MATFLAG_REFRACT; - } - if (use_subsurf) { - flag |= GPU_MATFLAG_SUBSURFACE; - } - if (use_transparency) { - flag |= GPU_MATFLAG_TRANSPARENT; - } - - float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; - - GPU_material_flag_set(mat, flag); - - GPUNodeLink *diffuse_weight, *specular_weight, *glass_reflection_weight, - *glass_transmission_weight, *clearcoat_weight; - - GPU_stack_link(mat, - node, - "node_bsdf_principled", - in, - out, - GPU_constant(&use_multi_scatter), - &diffuse_weight, - &specular_weight, - &glass_reflection_weight, - &glass_transmission_weight, - &clearcoat_weight); - - return GPU_stack_eval_link(mat, - node, - "node_bsdf_principled_eval", - in, - out, - GPU_constant(&use_multi_scatter), - diffuse_weight, - specular_weight, - glass_reflection_weight, - glass_transmission_weight, - clearcoat_weight); -} - -static void node_shader_update_principled(bNodeTree *UNUSED(ntree), bNode *node) -{ - bNodeSocket *sock; - int distribution = node->custom1; - - for (sock = node->inputs.first; sock; sock = sock->next) { - if (STREQ(sock->name, "Transmission Roughness")) { - if (distribution == SHD_GLOSSY_GGX) { - sock->flag &= ~SOCK_UNAVAIL; - } - else { - sock->flag |= SOCK_UNAVAIL; - } - } - } -} - -/* node type definition */ -void register_node_type_sh_bsdf_principled(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_BSDF_PRINCIPLED, "Principled BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_bsdf_principled_in, sh_node_bsdf_principled_out); - node_type_size_preset(&ntype, NODE_SIZE_LARGE); - node_type_init(&ntype, node_shader_init_principled); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_bsdf_principled); - node_type_update(&ntype, node_shader_update_principled); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc new file mode 100644 index 00000000000..4c378d9bc09 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc @@ -0,0 +1,259 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_bsdf_principled_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Base Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Float>(N_("Subsurface")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Subsurface Radius")) + .default_value({1.0f, 0.2f, 0.1f}) + .min(0.0f) + .max(100.0f) + .compact(); + b.add_input<decl::Color>(N_("Subsurface Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Float>(N_("Subsurface IOR")) + .default_value(1.4f) + .min(1.01f) + .max(3.8f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Subsurface Anisotropy")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Metallic")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Specular")) + .default_value(0.5f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Specular Tint")) + .default_value(0.5f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Roughness")) + .default_value(0.5f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Anisotropic")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Anisotropic Rotation")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Sheen")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Sheen Tint")) + .default_value(0.5f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Clearcoat")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Clearcoat Roughness")) + .default_value(0.03f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("IOR")).default_value(1.45f).min(0.0f).max(1000.0f); + b.add_input<decl::Float>(N_("Transmission")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Transmission Roughness")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Color>(N_("Emission")).default_value({0.0f, 0.0f, 0.0f, 1.0f}); + b.add_input<decl::Float>(N_("Emission Strength")).default_value(1.0).min(0.0f).max(1000000.0f); + b.add_input<decl::Float>(N_("Alpha")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Vector>(N_("Clearcoat Normal")).hide_value(); + b.add_input<decl::Vector>(N_("Tangent")).hide_value(); + b.add_output<decl::Shader>(N_("BSDF")); +} + +static void node_shader_buts_principled(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "distribution", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + uiItemR(layout, ptr, "subsurface_method", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} + +static void node_shader_init_principled(bNodeTree *UNUSED(ntree), bNode *node) +{ + node->custom1 = SHD_GLOSSY_GGX; + node->custom2 = SHD_SUBSURFACE_RANDOM_WALK; +} + +#define socket_not_zero(sock) (in[sock].link || (clamp_f(in[sock].vec[0], 0.0f, 1.0f) > 1e-5f)) +#define socket_not_one(sock) \ + (in[sock].link || (clamp_f(in[sock].vec[0], 0.0f, 1.0f) < 1.0f - 1e-5f)) + +static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + GPUNodeLink *sss_scale; + + /* Normals */ + if (!in[22].link) { + GPU_link(mat, "world_normals_get", &in[22].link); + } + + /* Clearcoat Normals */ + if (!in[23].link) { + GPU_link(mat, "world_normals_get", &in[23].link); + } + +#if 0 /* Not used at the moment. */ + /* Tangents */ + if (!in[24].link) { + GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); + GPU_link(mat, "tangent_orco_z", orco, &in[24].link); + GPU_link(mat, + "node_tangent", + GPU_builtin(GPU_WORLD_NORMAL), + in[24].link, + GPU_builtin(GPU_OBJECT_MATRIX), + &in[24].link); + } +#endif + + bool use_diffuse = socket_not_one(6) && socket_not_one(17); + bool use_subsurf = socket_not_zero(1) && use_diffuse && node->sss_id > 0; + bool use_refract = socket_not_one(6) && socket_not_zero(17); + bool use_clear = socket_not_zero(14); + + /* SSS Profile */ + if (use_subsurf) { + bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->original->inputs, 2); + bNodeSocketValueRGBA *socket_data = (bNodeSocketValueRGBA *)socket->default_value; + /* For some reason it seems that the socket value is in ARGB format. */ + GPU_material_sss_profile_create(mat, &socket_data->value[1]); + } + + if (in[2].link) { + sss_scale = in[2].link; + } + else { + GPU_link(mat, "set_rgb_one", &sss_scale); + } + + uint flag = GPU_MATFLAG_GLOSSY; + if (use_diffuse) { + flag |= GPU_MATFLAG_DIFFUSE; + } + if (use_refract) { + flag |= GPU_MATFLAG_REFRACT; + } + if (use_subsurf) { + flag |= GPU_MATFLAG_SSS; + } + + float f_use_diffuse = use_diffuse ? 1.0f : 0.0f; + float f_use_clearcoat = use_clear ? 1.0f : 0.0f; + float f_use_refraction = use_refract ? 1.0f : 0.0f; + float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; + + GPU_material_flag_set(mat, (eGPUMatFlag)flag); + + return GPU_stack_link(mat, + node, + "node_bsdf_principled", + in, + out, + GPU_constant(&f_use_diffuse), + GPU_constant(&f_use_clearcoat), + GPU_constant(&f_use_refraction), + GPU_constant(&use_multi_scatter), + GPU_constant(&node->ssr_id), + GPU_constant(&node->sss_id), + sss_scale); +} + +static void node_shader_update_principled(bNodeTree *ntree, bNode *node) +{ + const int distribution = node->custom1; + const int sss_method = node->custom2; + + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + if (STREQ(sock->name, "Transmission Roughness")) { + nodeSetSocketAvailability(ntree, sock, distribution == SHD_GLOSSY_GGX); + } + + if (STR_ELEM(sock->name, "Subsurface IOR", "Subsurface Anisotropy")) { + nodeSetSocketAvailability(ntree, sock, sss_method != SHD_SUBSURFACE_BURLEY); + } + } +} + +} // namespace blender::nodes::node_shader_bsdf_principled_cc + +/* node type definition */ +void register_node_type_sh_bsdf_principled() +{ + namespace file_ns = blender::nodes::node_shader_bsdf_principled_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_BSDF_PRINCIPLED, "Principled BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_principled; + node_type_size_preset(&ntype, NODE_SIZE_LARGE); + node_type_init(&ntype, file_ns::node_shader_init_principled); + node_type_gpu(&ntype, file_ns::node_shader_gpu_bsdf_principled); + node_type_update(&ntype, file_ns::node_shader_update_principled); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc index f857708c9b6..0d588c82869 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc @@ -17,23 +17,22 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_bsdf_refraction_cc { -static bNodeSocketTemplate sh_node_bsdf_refraction_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_bsdf_refraction_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Roughness")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("IOR")).default_value(1.45f).min(0.0f).max(1000.0f); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_output<decl::Shader>(N_("BSDF")); +} static void node_shader_init_refraction(bNodeTree *UNUSED(ntree), bNode *node) { @@ -56,21 +55,23 @@ static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, GPU_material_flag_set(mat, GPU_MATFLAG_REFRACT); - GPU_stack_link(mat, node, "node_bsdf_refraction", in, out); - return GPU_stack_eval_link(mat, node, "node_bsdf_refraction_eval", in, out); + return GPU_stack_link(mat, node, "node_bsdf_refraction", in, out); } +} // namespace blender::nodes::node_shader_bsdf_refraction_cc + /* node type definition */ -void register_node_type_sh_bsdf_refraction(void) +void register_node_type_sh_bsdf_refraction() { + namespace file_ns = blender::nodes::node_shader_bsdf_refraction_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BSDF_REFRACTION, "Refraction BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_bsdf_refraction_in, sh_node_bsdf_refraction_out); + sh_node_type_base(&ntype, SH_NODE_BSDF_REFRACTION, "Refraction BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, node_shader_init_refraction); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_bsdf_refraction); + node_type_init(&ntype, file_ns::node_shader_init_refraction); + node_type_gpu(&ntype, file_ns::node_shader_gpu_bsdf_refraction); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.cc index e79c65d85d9..5093b896764 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.cc @@ -17,23 +17,34 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +#include "UI_interface.h" +#include "UI_resources.h" -static bNodeSocketTemplate sh_node_bsdf_toon_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Size"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Smooth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_bsdf_toon_cc { -static bNodeSocketTemplate sh_node_bsdf_toon_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Float>(N_("Size")) + .default_value(0.5f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Smooth")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_output<decl::Shader>(N_("BSDF")); +} + +static void node_shader_buts_toon(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "component", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} static int node_shader_gpu_bsdf_toon(GPUMaterial *mat, bNode *node, @@ -47,21 +58,23 @@ static int node_shader_gpu_bsdf_toon(GPUMaterial *mat, GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE); - GPU_stack_link(mat, node, "node_bsdf_toon", in, out); - return GPU_stack_eval_link(mat, node, "node_bsdf_toon_eval", in, out); + return GPU_stack_link(mat, node, "node_bsdf_toon", in, out); } +} // namespace blender::nodes::node_shader_bsdf_toon_cc + /* node type definition */ -void register_node_type_sh_bsdf_toon(void) +void register_node_type_sh_bsdf_toon() { + namespace file_ns = blender::nodes::node_shader_bsdf_toon_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BSDF_TOON, "Toon BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_bsdf_toon_in, sh_node_bsdf_toon_out); + sh_node_type_base(&ntype, SH_NODE_BSDF_TOON, "Toon BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_toon; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_bsdf_toon); + node_type_gpu(&ntype, file_ns::node_shader_gpu_bsdf_toon); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.cc index d6c308459f5..22891738299 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.cc @@ -17,21 +17,16 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_bsdf_translucent_cc { -static bNodeSocketTemplate sh_node_bsdf_translucent_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_bsdf_translucent_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_output<decl::Shader>(N_("BSDF")); +} static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *node, @@ -45,20 +40,21 @@ static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE); - GPU_stack_link(mat, node, "node_bsdf_translucent", in, out); - return GPU_stack_eval_link(mat, node, "node_bsdf_translucent_eval", in, out); + return GPU_stack_link(mat, node, "node_bsdf_translucent", in, out); } +} // namespace blender::nodes::node_shader_bsdf_translucent_cc + /* node type definition */ -void register_node_type_sh_bsdf_translucent(void) +void register_node_type_sh_bsdf_translucent() { + namespace file_ns = blender::nodes::node_shader_bsdf_translucent_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BSDF_TRANSLUCENT, "Translucent BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_bsdf_translucent_in, sh_node_bsdf_translucent_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_bsdf_translucent); + sh_node_type_base(&ntype, SH_NODE_BSDF_TRANSLUCENT, "Translucent BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_bsdf_translucent); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.cc index a1c3b9066c8..d764f4dd76b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.cc @@ -17,20 +17,15 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_bsdf_transparent_cc { -static bNodeSocketTemplate sh_node_bsdf_transparent_in[] = { - {SOCK_RGBA, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_bsdf_transparent_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_output<decl::Shader>(N_("BSDF")); +} static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, bNode *node, @@ -38,22 +33,21 @@ static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - if (in[0].link || !equals_v3v3(in[0].vec, (float[3]){0.0f, 0.0f, 0.0f})) { - GPU_material_flag_set(mat, GPU_MATFLAG_TRANSPARENT); - } return GPU_stack_link(mat, node, "node_bsdf_transparent", in, out); } +} // namespace blender::nodes::node_shader_bsdf_transparent_cc + /* node type definition */ -void register_node_type_sh_bsdf_transparent(void) +void register_node_type_sh_bsdf_transparent() { + namespace file_ns = blender::nodes::node_shader_bsdf_transparent_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BSDF_TRANSPARENT, "Transparent BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_bsdf_transparent_in, sh_node_bsdf_transparent_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_bsdf_transparent); + sh_node_type_base(&ntype, SH_NODE_BSDF_TRANSPARENT, "Transparent BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_bsdf_transparent); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.cc index 0a7828f5b9a..dd090236c08 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.cc @@ -17,22 +17,21 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_bsdf_velvet_cc { -static bNodeSocketTemplate sh_node_bsdf_velvet_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Sigma"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_bsdf_velvet_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Float>(N_("Sigma")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_output<decl::Shader>(N_("BSDF")); +} static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *node, @@ -46,20 +45,21 @@ static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE); - GPU_stack_link(mat, node, "node_bsdf_velvet", in, out); - return GPU_stack_link(mat, node, "node_bsdf_velvet_eval", in, out); + return GPU_stack_link(mat, node, "node_bsdf_velvet", in, out); } +} // namespace blender::nodes::node_shader_bsdf_velvet_cc + /* node type definition */ -void register_node_type_sh_bsdf_velvet(void) +void register_node_type_sh_bsdf_velvet() { + namespace file_ns = blender::nodes::node_shader_bsdf_velvet_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BSDF_VELVET, "Velvet BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_bsdf_velvet_in, sh_node_bsdf_velvet_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_bsdf_velvet); + sh_node_type_base(&ntype, SH_NODE_BSDF_VELVET, "Velvet BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_bsdf_velvet); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.cc index 5c46e1d3775..f0788c543c2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bump.c +++ b/source/blender/nodes/shader/nodes/node_shader_bump.cc @@ -21,22 +21,38 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include "node_shader_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" /* **************** BUMP ******************** */ -/* clang-format off */ -static bNodeSocketTemplate sh_node_bump_in[] = { - {SOCK_FLOAT, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Distance"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_FLOAT, N_("Height"), 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Height_dx"), 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_UNAVAIL}, - {SOCK_FLOAT, N_("Height_dy"), 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_UNAVAIL}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {-1, ""} -}; -/* clang-format on */ -static bNodeSocketTemplate sh_node_bump_out[] = {{SOCK_VECTOR, "Normal"}, {-1, ""}}; +namespace blender::nodes::node_shader_bump_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Strength")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Distance")).default_value(1.0f).min(0.0f).max(1000.0f); + b.add_input<decl::Float>(N_("Height")) + .default_value(1.0f) + .min(-1000.0f) + .max(1000.0f) + .hide_value(); + b.add_input<decl::Float>(N_("Height_dx")).default_value(1.0f).unavailable(); + b.add_input<decl::Float>(N_("Height_dy")).default_value(1.0f).unavailable(); + b.add_input<decl::Vector>(N_("Normal")).min(-1.0f).max(1.0f).hide_value(); + b.add_output<decl::Vector>(N_("Normal")); +} + +static void node_shader_buts_bump(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "invert", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, 0); +} static int gpu_shader_bump(GPUMaterial *mat, bNode *node, @@ -53,15 +69,19 @@ static int gpu_shader_bump(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_bump", in, out, GPU_constant(&invert)); } +} // namespace blender::nodes::node_shader_bump_cc + /* node type definition */ -void register_node_type_sh_bump(void) +void register_node_type_sh_bump() { + namespace file_ns = blender::nodes::node_shader_bump_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BUMP, "Bump", NODE_CLASS_OP_VECTOR, 0); - node_type_socket_templates(&ntype, sh_node_bump_in, sh_node_bump_out); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, gpu_shader_bump); + sh_node_type_base(&ntype, SH_NODE_BUMP, "Bump", NODE_CLASS_OP_VECTOR); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_bump; + node_type_gpu(&ntype, file_ns::gpu_shader_bump); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_camera.c b/source/blender/nodes/shader/nodes/node_shader_camera.cc index 9c47db4ea4e..90d2b55b0f7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_camera.c +++ b/source/blender/nodes/shader/nodes/node_shader_camera.cc @@ -21,15 +21,16 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include "node_shader_util.hh" -/* **************** CAMERA INFO ******************** */ -static bNodeSocketTemplate sh_node_camera_out[] = { - {SOCK_VECTOR, N_("View Vector")}, - {SOCK_FLOAT, N_("View Z Depth")}, - {SOCK_FLOAT, N_("View Distance")}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_camera_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Vector>(N_("View Vector")); + b.add_output<decl::Float>(N_("View Z Depth")); + b.add_output<decl::Float>(N_("View Distance")); +} static int gpu_shader_camera(GPUMaterial *mat, bNode *node, @@ -40,14 +41,17 @@ static int gpu_shader_camera(GPUMaterial *mat, return GPU_stack_link(mat, node, "camera", in, out); } -void register_node_type_sh_camera(void) +} // namespace blender::nodes::node_shader_camera_cc + +void register_node_type_sh_camera() { + namespace file_ns = blender::nodes::node_shader_camera_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_CAMERA, "Camera Data", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, sh_node_camera_out); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, gpu_shader_camera); + sh_node_type_base(&ntype, SH_NODE_CAMERA, "Camera Data", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_camera); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_clamp.cc b/source/blender/nodes/shader/nodes/node_shader_clamp.cc index e8d4239937f..cd0f1b3c44d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_clamp.cc +++ b/source/blender/nodes/shader/nodes/node_shader_clamp.cc @@ -21,20 +21,26 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include "node_shader_util.hh" -namespace blender::nodes { +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_clamp_cc { static void sh_node_clamp_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Float>("Value").min(0.0f).max(1.0f).default_value(1.0f); - b.add_input<decl::Float>("Min").default_value(0.0f).min(-10000.0f).max(10000.0f); - b.add_input<decl::Float>("Max").default_value(1.0f).min(-10000.0f).max(10000.0f); - b.add_output<decl::Float>("Result"); -}; + b.add_input<decl::Float>(N_("Value")).default_value(1.0f); + b.add_input<decl::Float>(N_("Min")).default_value(0.0f).min(-10000.0f).max(10000.0f); + b.add_input<decl::Float>(N_("Max")).default_value(1.0f).min(-10000.0f).max(10000.0f); + b.add_output<decl::Float>(N_("Result")); +} -} // namespace blender::nodes +static void node_shader_buts_clamp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "clamp_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} static void node_shader_init_clamp(bNodeTree *UNUSED(ntree), bNode *node) { @@ -75,15 +81,20 @@ static void sh_node_clamp_build_multi_function(blender::nodes::NodeMultiFunction } } -void register_node_type_sh_clamp(void) +} // namespace blender::nodes::node_shader_clamp_cc + +void register_node_type_sh_clamp() { + namespace file_ns = blender::nodes::node_shader_clamp_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_CLAMP, "Clamp", NODE_CLASS_CONVERTER, 0); - ntype.declare = blender::nodes::sh_node_clamp_declare; - node_type_init(&ntype, node_shader_init_clamp); - node_type_gpu(&ntype, gpu_shader_clamp); - ntype.build_multi_function = sh_node_clamp_build_multi_function; + sh_fn_node_type_base(&ntype, SH_NODE_CLAMP, "Clamp", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::sh_node_clamp_declare; + ntype.draw_buttons = file_ns::node_shader_buts_clamp; + node_type_init(&ntype, file_ns::node_shader_init_clamp); + node_type_gpu(&ntype, file_ns::gpu_shader_clamp); + ntype.build_multi_function = file_ns::sh_node_clamp_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc b/source/blender/nodes/shader/nodes/node_shader_color_ramp.cc index d4d08be5d49..d8c43e1d66b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc +++ b/source/blender/nodes/shader/nodes/node_shader_color_ramp.cc @@ -21,43 +21,20 @@ * \ingroup shdnodes */ -#include "IMB_colormanagement.h" - #include "DNA_texture_types.h" #include "BLI_color.hh" -#include "node_shader_util.h" +#include "node_shader_util.hh" -namespace blender::nodes { +namespace blender::nodes::node_shader_color_ramp_cc { static void sh_node_valtorgb_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Float>("Fac").default_value(0.5f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); - b.add_output<decl::Color>("Color"); - b.add_output<decl::Float>("Alpha"); -}; - -} // namespace blender::nodes - -static void node_shader_exec_valtorgb(void *UNUSED(data), - int UNUSED(thread), - bNode *node, - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - /* stack order in: fac */ - /* stack order out: col, alpha */ - - if (node->storage) { - float fac; - nodestack_get_vec(&fac, SOCK_FLOAT, in[0]); - - BKE_colorband_evaluate((ColorBand *)node->storage, fac, out[0]->vec); - out[1]->vec[0] = out[0]->vec[3]; - } + b.add_input<decl::Float>(N_("Fac")).default_value(0.5f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); + b.add_output<decl::Color>(N_("Color")); + b.add_output<decl::Float>(N_("Alpha")); } static void node_shader_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node) @@ -172,64 +149,21 @@ static void sh_node_valtorgb_build_multi_function( builder.construct_and_set_matching_fn<ColorBandFunction>(*color_band); } -void register_node_type_sh_valtorgb(void) -{ - static bNodeType ntype; +} // namespace blender::nodes::node_shader_color_ramp_cc - sh_fn_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTER, 0); - ntype.declare = blender::nodes::sh_node_valtorgb_declare; - node_type_init(&ntype, node_shader_init_valtorgb); - node_type_size_preset(&ntype, NODE_SIZE_LARGE); - node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, nullptr, nullptr, node_shader_exec_valtorgb); - node_type_gpu(&ntype, gpu_shader_valtorgb); - ntype.build_multi_function = sh_node_valtorgb_build_multi_function; - - nodeRegisterType(&ntype); -} - -namespace blender::nodes { - -static void sh_node_rgbtobw_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Color>("Color").default_value({0.5f, 0.5f, 0.5f, 1.0f}); - b.add_output<decl::Float>("Val"); -}; - -} // namespace blender::nodes - -static void node_shader_exec_rgbtobw(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - /* stack order out: bw */ - /* stack order in: col */ - float col[3]; - nodestack_get_vec(col, SOCK_VECTOR, in[0]); - - out[0]->vec[0] = IMB_colormanagement_get_luminance(col); -} - -static int gpu_shader_rgbtobw(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) +void register_node_type_sh_valtorgb() { - return GPU_stack_link(mat, node, "rgbtobw", in, out); -} + namespace file_ns = blender::nodes::node_shader_color_ramp_cc; -void register_node_type_sh_rgbtobw(void) -{ static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTER, 0); - ntype.declare = blender::nodes::sh_node_rgbtobw_declare; - node_type_exec(&ntype, nullptr, nullptr, node_shader_exec_rgbtobw); - node_type_gpu(&ntype, gpu_shader_rgbtobw); + sh_fn_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::sh_node_valtorgb_declare; + node_type_init(&ntype, file_ns::node_shader_init_valtorgb); + node_type_size_preset(&ntype, NODE_SIZE_LARGE); + node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage); + node_type_gpu(&ntype, file_ns::gpu_shader_valtorgb); + ntype.build_multi_function = file_ns::sh_node_valtorgb_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c deleted file mode 100644 index 4df5add7151..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_common.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2006 Blender Foundation. - * All rights reserved. - * Juho Vepsäläinen - */ - -/** \file - * \ingroup shdnodes - */ - -#include "DNA_node_types.h" - -#include "BLI_utildefines.h" - -#include "BKE_node.h" - -#include "NOD_common.h" -#include "node_common.h" -#include "node_exec.h" -#include "node_shader_util.h" - -#include "RNA_access.h" - -static void copy_stack(bNodeStack *to, bNodeStack *from) -{ - if (to != from) { - copy_v4_v4(to->vec, from->vec); - to->data = from->data; - to->datatype = from->datatype; - - /* tag as copy to prevent freeing */ - to->is_copy = 1; - } -} - -static void move_stack(bNodeStack *to, bNodeStack *from) -{ - if (to != from) { - copy_v4_v4(to->vec, from->vec); - to->data = from->data; - to->datatype = from->datatype; - to->is_copy = from->is_copy; - - from->data = NULL; - from->is_copy = 0; - } -} - -/**** GROUP ****/ - -static void *group_initexec(bNodeExecContext *context, bNode *node, bNodeInstanceKey key) -{ - bNodeTree *ngroup = (bNodeTree *)node->id; - bNodeTreeExec *exec; - - if (!ngroup) { - return NULL; - } - - /* initialize the internal node tree execution */ - exec = ntreeShaderBeginExecTree_internal(context, ngroup, key); - - return exec; -} - -static void group_freeexec(void *nodedata) -{ - bNodeTreeExec *gexec = (bNodeTreeExec *)nodedata; - - if (gexec) { - ntreeShaderEndExecTree_internal(gexec); - } -} - -/* Copy inputs to the internal stack. - */ -static void group_copy_inputs(bNode *gnode, bNodeStack **in, bNodeStack *gstack) -{ - bNodeTree *ngroup = (bNodeTree *)gnode->id; - bNode *node; - bNodeSocket *sock; - bNodeStack *ns; - int a; - - for (node = ngroup->nodes.first; node; node = node->next) { - if (node->type == NODE_GROUP_INPUT) { - for (sock = node->outputs.first, a = 0; sock; sock = sock->next, a++) { - ns = node_get_socket_stack(gstack, sock); - if (ns) { - copy_stack(ns, in[a]); - } - } - } - } -} - -/* Copy internal results to the external outputs. - */ -static void group_move_outputs(bNode *gnode, bNodeStack **out, bNodeStack *gstack) -{ - bNodeTree *ngroup = (bNodeTree *)gnode->id; - bNode *node; - bNodeSocket *sock; - bNodeStack *ns; - int a; - - for (node = ngroup->nodes.first; node; node = node->next) { - if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) { - for (sock = node->inputs.first, a = 0; sock; sock = sock->next, a++) { - ns = node_get_socket_stack(gstack, sock); - if (ns) { - move_stack(out[a], ns); - } - } - break; /* only one active output node */ - } - } -} - -static void group_execute(void *data, - int thread, - struct bNode *node, - bNodeExecData *execdata, - struct bNodeStack **in, - struct bNodeStack **out) -{ - bNodeTreeExec *exec = execdata->data; - bNodeThreadStack *nts; - - if (!exec) { - return; - } - - /* XXX same behavior as trunk: all nodes inside group are executed. - * it's stupid, but just makes it work. compo redesign will do this better. - */ - { - bNode *inode; - for (inode = exec->nodetree->nodes.first; inode; inode = inode->next) { - inode->need_exec = 1; - } - } - - nts = ntreeGetThreadStack(exec, thread); - - group_copy_inputs(node, in, nts->stack); - ntreeExecThreadNodes(exec, nts, data, thread); - group_move_outputs(node, out, nts->stack); - - ntreeReleaseThreadStack(nts); -} - -static void group_gpu_copy_inputs(bNode *gnode, GPUNodeStack *in, bNodeStack *gstack) -{ - bNodeTree *ngroup = (bNodeTree *)gnode->id; - bNode *node; - bNodeSocket *sock; - bNodeStack *ns; - int a; - - for (node = ngroup->nodes.first; node; node = node->next) { - if (node->type == NODE_GROUP_INPUT) { - for (sock = node->outputs.first, a = 0; sock; sock = sock->next, a++) { - ns = node_get_socket_stack(gstack, sock); - if (ns) { - /* convert the external gpu stack back to internal node stack data */ - node_data_from_gpu_stack(ns, &in[a]); - } - } - } - } -} - -/* Copy internal results to the external outputs. - */ -static void group_gpu_move_outputs(bNode *gnode, GPUNodeStack *out, bNodeStack *gstack) -{ - bNodeTree *ngroup = (bNodeTree *)gnode->id; - bNode *node; - bNodeSocket *sock; - bNodeStack *ns; - int a; - - for (node = ngroup->nodes.first; node; node = node->next) { - if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) { - for (sock = node->inputs.first, a = 0; sock; sock = sock->next, a++) { - ns = node_get_socket_stack(gstack, sock); - if (ns) { - /* convert the node stack data result back to gpu stack */ - node_gpu_stack_from_data(&out[a], sock->type, ns); - } - } - break; /* only one active output node */ - } - } -} - -static int gpu_group_execute( - GPUMaterial *mat, bNode *node, bNodeExecData *execdata, GPUNodeStack *in, GPUNodeStack *out) -{ - bNodeTreeExec *exec = execdata->data; - - if (!node->id) { - return 0; - } - - group_gpu_copy_inputs(node, in, exec->stack); - ntreeExecGPUNodes(exec, mat, NULL); - group_gpu_move_outputs(node, out, exec->stack); - - return 1; -} - -void register_node_type_sh_group(void) -{ - static bNodeType ntype; - - /* NOTE: cannot use #sh_node_type_base for node group, because it would map the node type - * to the shared #NODE_GROUP integer type id. */ - - node_type_base_custom(&ntype, "ShaderNodeGroup", "Group", NODE_CLASS_GROUP, NODE_CONST_OUTPUT); - ntype.type = NODE_GROUP; - ntype.poll = sh_node_poll_default; - ntype.poll_instance = node_group_poll_instance; - ntype.insert_link = node_insert_link_default; - ntype.update_internal_links = node_update_internal_links_default; - ntype.rna_ext.srna = RNA_struct_find("ShaderNodeGroup"); - BLI_assert(ntype.rna_ext.srna != NULL); - RNA_struct_blender_type_set(ntype.rna_ext.srna, &ntype); - - node_type_socket_templates(&ntype, NULL, NULL); - node_type_size(&ntype, 140, 60, 400); - node_type_label(&ntype, node_group_label); - node_type_group_update(&ntype, node_group_update); - node_type_exec(&ntype, group_initexec, group_freeexec, group_execute); - node_type_gpu(&ntype, gpu_group_execute); - - nodeRegisterType(&ntype); -} - -void register_node_type_sh_custom_group(bNodeType *ntype) -{ - /* These methods can be overridden but need a default implementation otherwise. */ - if (ntype->poll == NULL) { - ntype->poll = sh_node_poll_default; - } - if (ntype->insert_link == NULL) { - ntype->insert_link = node_insert_link_default; - } - if (ntype->update_internal_links == NULL) { - ntype->update_internal_links = node_update_internal_links_default; - } - - node_type_exec(ntype, group_initexec, group_freeexec, group_execute); - node_type_gpu(ntype, gpu_group_execute); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_common.cc b/source/blender/nodes/shader/nodes/node_shader_common.cc new file mode 100644 index 00000000000..3f0fff34533 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_common.cc @@ -0,0 +1,130 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + * Juho Vepsäläinen + */ + +/** \file + * \ingroup shdnodes + */ + +#include "DNA_node_types.h" + +#include "BLI_utildefines.h" + +#include "BKE_node.h" + +#include "NOD_common.h" +#include "node_common.h" +#include "node_exec.h" +#include "node_shader_util.hh" + +#include "RNA_access.h" + +/**** GROUP ****/ + +static void group_gpu_copy_inputs(bNode *gnode, GPUNodeStack *in, bNodeStack *gstack) +{ + bNodeTree *ngroup = (bNodeTree *)gnode->id; + + LISTBASE_FOREACH (bNode *, node, &ngroup->nodes) { + if (node->type == NODE_GROUP_INPUT) { + int a; + LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->outputs, a) { + bNodeStack *ns = node_get_socket_stack(gstack, sock); + if (ns) { + /* convert the external gpu stack back to internal node stack data */ + node_data_from_gpu_stack(ns, &in[a]); + } + } + } + } +} + +/* Copy internal results to the external outputs. + */ +static void group_gpu_move_outputs(bNode *gnode, GPUNodeStack *out, bNodeStack *gstack) +{ + bNodeTree *ngroup = (bNodeTree *)gnode->id; + + LISTBASE_FOREACH (bNode *, node, &ngroup->nodes) { + if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) { + int a; + LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->inputs, a) { + bNodeStack *ns = node_get_socket_stack(gstack, sock); + if (ns) { + /* convert the node stack data result back to gpu stack */ + node_gpu_stack_from_data(&out[a], sock->type, ns); + } + } + break; /* only one active output node */ + } + } +} + +static int gpu_group_execute( + GPUMaterial *mat, bNode *node, bNodeExecData *execdata, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeTreeExec *exec = static_cast<bNodeTreeExec *>(execdata->data); + + if (!node->id) { + return 0; + } + + group_gpu_copy_inputs(node, in, exec->stack); + ntreeExecGPUNodes(exec, mat, nullptr); + group_gpu_move_outputs(node, out, exec->stack); + + return 1; +} + +void register_node_type_sh_group() +{ + static bNodeType ntype; + + /* NOTE: cannot use #sh_node_type_base for node group, because it would map the node type + * to the shared #NODE_GROUP integer type id. */ + + node_type_base_custom(&ntype, "ShaderNodeGroup", "Group", NODE_CLASS_GROUP); + ntype.type = NODE_GROUP; + ntype.poll = sh_node_poll_default; + ntype.poll_instance = node_group_poll_instance; + ntype.insert_link = node_insert_link_default; + ntype.rna_ext.srna = RNA_struct_find("ShaderNodeGroup"); + BLI_assert(ntype.rna_ext.srna != nullptr); + RNA_struct_blender_type_set(ntype.rna_ext.srna, &ntype); + + node_type_size(&ntype, 140, 60, 400); + ntype.labelfunc = node_group_label; + node_type_group_update(&ntype, node_group_update); + node_type_gpu(&ntype, gpu_group_execute); + + nodeRegisterType(&ntype); +} + +void register_node_type_sh_custom_group(bNodeType *ntype) +{ + /* These methods can be overridden but need a default implementation otherwise. */ + if (ntype->poll == nullptr) { + ntype->poll = sh_node_poll_default; + } + if (ntype->insert_link == nullptr) { + ntype->insert_link = node_insert_link_default; + } + + node_type_gpu(ntype, gpu_group_execute); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.cc b/source/blender/nodes/shader/nodes/node_shader_curves.cc index 887cc84bb76..bce59a60033 100644 --- a/source/blender/nodes/shader/nodes/node_shader_curves.cc +++ b/source/blender/nodes/shader/nodes/node_shader_curves.cc @@ -21,33 +21,16 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include "node_shader_util.hh" -namespace blender::nodes { +namespace blender::nodes::node_shader_curves_cc { static void sh_node_curve_vec_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Float>("Fac").min(0.0f).max(1.0f).default_value(1.0f).subtype(PROP_FACTOR); - b.add_input<decl::Vector>("Vector").min(-1.0f).max(1.0f); - b.add_output<decl::Vector>("Vector"); -}; - -} // namespace blender::nodes - -static void node_shader_exec_curve_vec(void *UNUSED(data), - int UNUSED(thread), - bNode *node, - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - float vec[3]; - - /* stack order input: vec */ - /* stack order output: vec */ - nodestack_get_vec(vec, SOCK_VECTOR, in[1]); - BKE_curvemapping_evaluate3F((CurveMapping *)node->storage, out[0]->vec, vec); + b.add_input<decl::Float>(N_("Fac")).min(0.0f).max(1.0f).default_value(1.0f).subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Vector")).min(-1.0f).max(1.0f); + b.add_output<decl::Vector>(N_("Vector")); } static void node_shader_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node) @@ -152,53 +135,35 @@ static void sh_node_curve_vec_build_multi_function( builder.construct_and_set_matching_fn<CurveVecFunction>(*cumap); } -void register_node_type_sh_curve_vec(void) +} // namespace blender::nodes::node_shader_curves_cc + +void register_node_type_sh_curve_vec() { + namespace file_ns = blender::nodes::node_shader_curves_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, 0); - ntype.declare = blender::nodes::sh_node_curve_vec_declare; - node_type_init(&ntype, node_shader_init_curve_vec); + sh_fn_node_type_base(&ntype, SH_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR); + ntype.declare = file_ns::sh_node_curve_vec_declare; + node_type_init(&ntype, file_ns::node_shader_init_curve_vec); node_type_size_preset(&ntype, NODE_SIZE_LARGE); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); - node_type_exec(&ntype, node_initexec_curves, nullptr, node_shader_exec_curve_vec); - node_type_gpu(&ntype, gpu_shader_curve_vec); - ntype.build_multi_function = sh_node_curve_vec_build_multi_function; + node_type_gpu(&ntype, file_ns::gpu_shader_curve_vec); + ntype.build_multi_function = file_ns::sh_node_curve_vec_build_multi_function; nodeRegisterType(&ntype); } /* **************** CURVE RGB ******************** */ -namespace blender::nodes { +namespace blender::nodes::node_shader_curves_cc { static void sh_node_curve_rgb_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Float>("Fac").min(0.0f).max(1.0f).default_value(1.0f).subtype(PROP_FACTOR); - b.add_input<decl::Color>("Color").default_value({1.0f, 1.0f, 1.0f, 1.0f}); - b.add_output<decl::Color>("Color"); -}; - -} // namespace blender::nodes - -static void node_shader_exec_curve_rgb(void *UNUSED(data), - int UNUSED(thread), - bNode *node, - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - float vec[3]; - float fac; - - /* stack order input: vec */ - /* stack order output: vec */ - nodestack_get_vec(&fac, SOCK_FLOAT, in[0]); - nodestack_get_vec(vec, SOCK_VECTOR, in[1]); - BKE_curvemapping_evaluateRGBF((CurveMapping *)node->storage, out[0]->vec, vec); - if (fac != 1.0f) { - interp_v3_v3v3(out[0]->vec, vec, out[0]->vec, fac); - } + b.is_function_node(); + b.add_input<decl::Float>(N_("Fac")).min(0.0f).max(1.0f).default_value(1.0f).subtype(PROP_FACTOR); + b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_output<decl::Color>(N_("Color")); } static void node_shader_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node) @@ -328,18 +293,148 @@ static void sh_node_curve_rgb_build_multi_function( builder.construct_and_set_matching_fn<CurveRGBFunction>(*cumap); } -void register_node_type_sh_curve_rgb(void) +} // namespace blender::nodes::node_shader_curves_cc + +void register_node_type_sh_curve_rgb() +{ + namespace file_ns = blender::nodes::node_shader_curves_cc; + + static bNodeType ntype; + + sh_fn_node_type_base(&ntype, SH_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR); + ntype.declare = file_ns::sh_node_curve_rgb_declare; + node_type_init(&ntype, file_ns::node_shader_init_curve_rgb); + node_type_size_preset(&ntype, NODE_SIZE_LARGE); + node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); + node_type_gpu(&ntype, file_ns::gpu_shader_curve_rgb); + ntype.build_multi_function = file_ns::sh_node_curve_rgb_build_multi_function; + + nodeRegisterType(&ntype); +} + +/* **************** CURVE FLOAT ******************** */ + +namespace blender::nodes::node_shader_curves_cc { + +static void sh_node_curve_float_declare(NodeDeclarationBuilder &b) +{ + b.is_function_node(); + b.add_input<decl::Float>(N_("Factor")) + .min(0.0f) + .max(1.0f) + .default_value(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Value")).default_value(1.0f).is_default_link_socket(); + b.add_output<decl::Float>(N_("Value")); +} + +static void node_shader_init_curve_float(bNodeTree *UNUSED(ntree), bNode *node) +{ + node->storage = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); +} + +static int gpu_shader_curve_float(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + float *array, layer; + int size; + + CurveMapping *cumap = (CurveMapping *)node->storage; + + BKE_curvemapping_table_F(cumap, &array, &size); + GPUNodeLink *tex = GPU_color_band(mat, size, array, &layer); + + float ext_xyz[4]; + float range_x; + + const CurveMap *cm = &cumap->cm[0]; + ext_xyz[0] = cm->mintable; + ext_xyz[2] = cm->maxtable; + range_x = 1.0f / max_ff(1e-8f, cm->maxtable - cm->mintable); + /* Compute extrapolation gradients. */ + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) != 0) { + ext_xyz[1] = (cm->ext_in[0] != 0.0f) ? (cm->ext_in[1] / (cm->ext_in[0] * range_x)) : 1e8f; + ext_xyz[3] = (cm->ext_out[0] != 0.0f) ? (cm->ext_out[1] / (cm->ext_out[0] * range_x)) : 1e8f; + } + else { + ext_xyz[1] = 0.0f; + ext_xyz[3] = 0.0f; + } + return GPU_stack_link(mat, + node, + "curve_float", + in, + out, + tex, + GPU_constant(&layer), + GPU_uniform(&range_x), + GPU_uniform(ext_xyz)); +} + +class CurveFloatFunction : public blender::fn::MultiFunction { + private: + const CurveMapping &cumap_; + + public: + CurveFloatFunction(const CurveMapping &cumap) : cumap_(cumap) + { + static blender::fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static blender::fn::MFSignature create_signature() + { + blender::fn::MFSignatureBuilder signature{"Curve Float"}; + signature.single_input<float>("Factor"); + signature.single_input<float>("Value"); + signature.single_output<float>("Value"); + return signature.build(); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + const blender::VArray<float> &fac = params.readonly_single_input<float>(0, "Factor"); + const blender::VArray<float> &val_in = params.readonly_single_input<float>(1, "Value"); + blender::MutableSpan<float> val_out = params.uninitialized_single_output<float>(2, "Value"); + + for (int64_t i : mask) { + val_out[i] = BKE_curvemapping_evaluateF(&cumap_, 0, val_in[i]); + if (fac[i] != 1.0f) { + val_out[i] = (1.0f - fac[i]) * val_in[i] + fac[i] * val_out[i]; + } + } + } +}; + +static void sh_node_curve_float_build_multi_function( + blender::nodes::NodeMultiFunctionBuilder &builder) +{ + bNode &bnode = builder.node(); + CurveMapping *cumap = (CurveMapping *)bnode.storage; + BKE_curvemapping_init(cumap); + builder.construct_and_set_matching_fn<CurveFloatFunction>(*cumap); +} + +} // namespace blender::nodes::node_shader_curves_cc + +void register_node_type_sh_curve_float() { + namespace file_ns = blender::nodes::node_shader_curves_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, 0); - ntype.declare = blender::nodes::sh_node_curve_rgb_declare; - node_type_init(&ntype, node_shader_init_curve_rgb); + sh_fn_node_type_base(&ntype, SH_NODE_CURVE_FLOAT, "Float Curve", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::sh_node_curve_float_declare; + node_type_init(&ntype, file_ns::node_shader_init_curve_float); node_type_size_preset(&ntype, NODE_SIZE_LARGE); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); - node_type_exec(&ntype, node_initexec_curves, nullptr, node_shader_exec_curve_rgb); - node_type_gpu(&ntype, gpu_shader_curve_rgb); - ntype.build_multi_function = sh_node_curve_rgb_build_multi_function; + node_type_gpu(&ntype, file_ns::gpu_shader_curve_float); + ntype.build_multi_function = file_ns::sh_node_curve_float_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_displacement.c b/source/blender/nodes/shader/nodes/node_shader_displacement.cc index c88083d109f..47af2447440 100644 --- a/source/blender/nodes/shader/nodes/node_shader_displacement.c +++ b/source/blender/nodes/shader/nodes/node_shader_displacement.cc @@ -17,22 +17,18 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_displacement_cc { -static bNodeSocketTemplate sh_node_displacement_in[] = { - {SOCK_FLOAT, N_("Height"), 0.00f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_FLOAT, N_("Midlevel"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_FLOAT, N_("Scale"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_displacement_out[] = { - {SOCK_VECTOR, N_("Displacement"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Height")).default_value(0.0f).min(0.0f).max(1000.0f); + b.add_input<decl::Float>(N_("Midlevel")).default_value(0.0f).min(0.0f).max(1000.0f); + b.add_input<decl::Float>(N_("Scale")).default_value(1.0f).min(0.0f).max(1000.0f); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_output<decl::Vector>(N_("Displacement")); +} static void node_shader_init_displacement(bNodeTree *UNUSED(ntree), bNode *node) { @@ -63,16 +59,19 @@ static int gpu_shader_displacement(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_displacement_world", in, out); } +} // namespace blender::nodes::node_shader_displacement_cc + /* node type definition */ -void register_node_type_sh_displacement(void) +void register_node_type_sh_displacement() { + namespace file_ns = blender::nodes::node_shader_displacement_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_DISPLACEMENT, "Displacement", NODE_CLASS_OP_VECTOR, 0); - node_type_socket_templates(&ntype, sh_node_displacement_in, sh_node_displacement_out); - node_type_storage(&ntype, "", NULL, NULL); - node_type_init(&ntype, node_shader_init_displacement); - node_type_gpu(&ntype, gpu_shader_displacement); + sh_node_type_base(&ntype, SH_NODE_DISPLACEMENT, "Displacement", NODE_CLASS_OP_VECTOR); + ntype.declare = file_ns::node_declare; + node_type_init(&ntype, file_ns::node_shader_init_displacement); + node_type_gpu(&ntype, file_ns::gpu_shader_displacement); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c deleted file mode 100644 index 191a8b2a376..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_eevee_specular_in[] = { - {SOCK_RGBA, N_("Base Color"), 0.8f, 0.8f, 0.8f, 1.0f}, - {SOCK_RGBA, N_("Specular"), 0.03f, 0.03f, 0.03f, 1.0f}, - {SOCK_FLOAT, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_RGBA, N_("Emissive Color"), 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Transparency"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Clear Coat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Clear Coat Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_VECTOR, - N_("Clear Coat Normal"), - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - PROP_NONE, - SOCK_HIDE_VALUE}, - {SOCK_FLOAT, - N_("Ambient Occlusion"), - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - PROP_NONE, - SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_eevee_specular_out[] = { - {SOCK_SHADER, N_("BSDF")}, - {-1, ""}, -}; - -static int node_shader_gpu_eevee_specular(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - static float one = 1.0f; - - /* Normals */ - if (!in[5].link) { - GPU_link(mat, "world_normals_get", &in[5].link); - } - - /* Clearcoat Normals */ - if (!in[8].link) { - GPU_link(mat, "world_normals_get", &in[8].link); - } - - /* Occlusion */ - if (!in[9].link) { - GPU_link(mat, "set_value", GPU_constant(&one), &in[9].link); - } - - GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY); - - GPU_stack_link(mat, node, "node_eevee_specular", in, out); - return GPU_stack_eval_link(mat, node, "node_eevee_specular_eval", in, out); -} - -/* node type definition */ -void register_node_type_sh_eevee_specular(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_EEVEE_SPECULAR, "Specular BSDF", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_eevee_specular_in, sh_node_eevee_specular_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_eevee_specular); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc new file mode 100644 index 00000000000..e4c80725c8e --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc @@ -0,0 +1,97 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_eevee_specular_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Base Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Color>(N_("Specular")).default_value({0.03f, 0.03f, 0.03f, 1.0f}); + b.add_input<decl::Float>(N_("Roughness")) + .default_value(0.2f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Color>(N_("Emissive Color")).default_value({0.0f, 0.0f, 0.0f, 1.0f}); + b.add_input<decl::Float>(N_("Transparency")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Clear Coat")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Clear Coat Roughness")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Clear Coat Normal")).hide_value(); + b.add_input<decl::Float>(N_("Ambient Occlusion")).hide_value(); + b.add_output<decl::Shader>(N_("BSDF")); +} + +static int node_shader_gpu_eevee_specular(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + static float one = 1.0f; + + /* Normals */ + if (!in[5].link) { + GPU_link(mat, "world_normals_get", &in[5].link); + } + + /* Clearcoat Normals */ + if (!in[8].link) { + GPU_link(mat, "world_normals_get", &in[8].link); + } + + /* Occlusion */ + if (!in[9].link) { + GPU_link(mat, "set_value", GPU_constant(&one), &in[9].link); + } + + GPU_material_flag_set(mat, static_cast<eGPUMatFlag>(GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY)); + + return GPU_stack_link(mat, node, "node_eevee_specular", in, out, GPU_constant(&node->ssr_id)); +} + +} // namespace blender::nodes::node_shader_eevee_specular_cc + +/* node type definition */ +void register_node_type_sh_eevee_specular() +{ + namespace file_ns = blender::nodes::node_shader_eevee_specular_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_EEVEE_SPECULAR, "Specular BSDF", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_eevee_specular); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_emission.c b/source/blender/nodes/shader/nodes/node_shader_emission.cc index 64bef6adb46..ea36763578f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_emission.c +++ b/source/blender/nodes/shader/nodes/node_shader_emission.cc @@ -17,21 +17,16 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_emission_cc { -static bNodeSocketTemplate sh_node_emission_in[] = { - {SOCK_RGBA, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_emission_out[] = { - {SOCK_SHADER, N_("Emission")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Strength")).default_value(1.0f).min(0.0f).max(1000000.0f); + b.add_output<decl::Shader>(N_("Emission")); +} static int node_shader_gpu_emission(GPUMaterial *mat, bNode *node, @@ -39,20 +34,21 @@ static int node_shader_gpu_emission(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - GPU_material_flag_set(mat, GPU_MATFLAG_EMISSION); - return GPU_stack_link(mat, node, "node_emission", in, out); + return GPU_stack_link(mat, node, "node_emission", in, out, GPU_builtin(GPU_VIEW_NORMAL)); } +} // namespace blender::nodes::node_shader_emission_cc + /* node type definition */ -void register_node_type_sh_emission(void) +void register_node_type_sh_emission() { + namespace file_ns = blender::nodes::node_shader_emission_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_EMISSION, "Emission", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_emission_in, sh_node_emission_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_emission); + sh_node_type_base(&ntype, SH_NODE_EMISSION, "Emission", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_emission); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_fresnel.c b/source/blender/nodes/shader/nodes/node_shader_fresnel.cc index 9b25af912ef..19eb79e2138 100644 --- a/source/blender/nodes/shader/nodes/node_shader_fresnel.c +++ b/source/blender/nodes/shader/nodes/node_shader_fresnel.cc @@ -17,19 +17,16 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** Fresnel ******************** */ -static bNodeSocketTemplate sh_node_fresnel_in[] = { - {SOCK_FLOAT, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_fresnel_cc { -static bNodeSocketTemplate sh_node_fresnel_out[] = { - {SOCK_FLOAT, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("IOR")).default_value(1.45f).min(0.0f).max(1000.0f); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_output<decl::Float>(N_("Fac")); +} static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *node, @@ -44,26 +41,18 @@ static int node_shader_gpu_fresnel(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_fresnel", in, out); } -static void node_shader_exec_fresnel(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **UNUSED(in), - bNodeStack **UNUSED(out)) -{ -} +} // namespace blender::nodes::node_shader_fresnel_cc /* node type definition */ -void register_node_type_sh_fresnel(void) +void register_node_type_sh_fresnel() { + namespace file_ns = blender::nodes::node_shader_fresnel_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_FRESNEL, "Fresnel", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, sh_node_fresnel_in, sh_node_fresnel_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_fresnel); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_fresnel); + sh_node_type_base(&ntype, SH_NODE_FRESNEL, "Fresnel", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_fresnel); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c deleted file mode 100644 index b48838e5f56..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_gamma.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2006 Blender Foundation. - * All rights reserved. - */ - -#include "node_shader_util.h" - -/* **************** Gamma Tools ******************** */ - -static bNodeSocketTemplate sh_node_gamma_in[] = { - {SOCK_RGBA, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f}, - {SOCK_FLOAT, N_("Gamma"), 1.0f, 0.0f, 0.0f, 0.0f, 0.001f, 10.0f, PROP_UNSIGNED}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_gamma_out[] = { - {SOCK_RGBA, N_("Color")}, - {-1, ""}, -}; - -static void node_shader_exec_gamma(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - float col[3]; - float gamma; - nodestack_get_vec(col, SOCK_VECTOR, in[0]); - nodestack_get_vec(&gamma, SOCK_FLOAT, in[1]); - - out[0]->vec[0] = col[0] > 0.0f ? powf(col[0], gamma) : col[0]; - out[0]->vec[1] = col[1] > 0.0f ? powf(col[1], gamma) : col[1]; - out[0]->vec[2] = col[2] > 0.0f ? powf(col[2], gamma) : col[2]; -} - -static int node_shader_gpu_gamma(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - return GPU_stack_link(mat, node, "node_gamma", in, out); -} - -void register_node_type_sh_gamma(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, 0); - node_type_socket_templates(&ntype, sh_node_gamma_in, sh_node_gamma_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_gamma); - node_type_gpu(&ntype, node_shader_gpu_gamma); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.cc b/source/blender/nodes/shader/nodes/node_shader_gamma.cc new file mode 100644 index 00000000000..98a287b08da --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_gamma.cc @@ -0,0 +1,57 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_gamma_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Gamma")) + .default_value(1.0f) + .min(0.001f) + .max(10.0f) + .subtype(PROP_UNSIGNED); + b.add_output<decl::Color>(N_("Color")); +} + +static int node_shader_gpu_gamma(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + return GPU_stack_link(mat, node, "node_gamma", in, out); +} + +} // namespace blender::nodes::node_shader_gamma_cc + +void register_node_type_sh_gamma() +{ + namespace file_ns = blender::nodes::node_shader_gamma_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_gamma); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.cc index 633f071ab86..35eef95adb5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_geometry.c +++ b/source/blender/nodes/shader/nodes/node_shader_geometry.cc @@ -17,22 +17,22 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_geometry_cc { -static bNodeSocketTemplate sh_node_geometry_out[] = { - {SOCK_VECTOR, N_("Position"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Tangent"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("True Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Incoming"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Parametric"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Backfacing"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Pointiness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Random Per Island"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Vector>(N_("Position")); + b.add_output<decl::Vector>(N_("Normal")); + b.add_output<decl::Vector>(N_("Tangent")); + b.add_output<decl::Vector>(N_("True Normal")); + b.add_output<decl::Vector>(N_("Incoming")); + b.add_output<decl::Vector>(N_("Parametric")); + b.add_output<decl::Float>(N_("Backfacing")); + b.add_output<decl::Float>(N_("Pointiness")); + b.add_output<decl::Float>(N_("Random Per Island")); +} static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *node, @@ -52,8 +52,8 @@ static int node_shader_gpu_geometry(GPUMaterial *mat, const bool success = GPU_stack_link(mat, node, "node_geometry", in, out, orco_link); - /* for each output */ - for (int i = 0; sh_node_geometry_out[i].type != -1; i++) { + int i; + LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->outputs, i) { node_shader_gpu_bump_tex_coord(mat, node, &out[i].link); /* Normalize some vectors after dFdx/dFdy offsets. * This is the case for interpolated, non linear functions. @@ -67,23 +67,25 @@ static int node_shader_gpu_geometry(GPUMaterial *mat, out[i].link, out[i].link, &out[i].link, - NULL); + nullptr); } } return success; } +} // namespace blender::nodes::node_shader_geometry_cc + /* node type definition */ -void register_node_type_sh_geometry(void) +void register_node_type_sh_geometry() { + namespace file_ns = blender::nodes::node_shader_geometry_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_NEW_GEOMETRY, "Geometry", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, sh_node_geometry_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_geometry); + sh_node_type_base(&ntype, SH_NODE_NEW_GEOMETRY, "Geometry", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_geometry); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_hair_info.c b/source/blender/nodes/shader/nodes/node_shader_hair_info.cc index c721fb9c77a..12c29c40b1d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_hair_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_hair_info.cc @@ -17,18 +17,19 @@ * All rights reserved. */ -#include "../node_shader_util.h" - -static bNodeSocketTemplate outputs[] = { - {SOCK_FLOAT, N_("Is Strand"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Intercept"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Length"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Thickness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Tangent Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - // { SOCK_FLOAT, 0, N_("Fade"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Random")}, - {-1, ""}, -}; +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_hair_info_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Float>(N_("Is Strand")); + b.add_output<decl::Float>(N_("Intercept")); + b.add_output<decl::Float>(N_("Length")); + b.add_output<decl::Float>(N_("Thickness")); + b.add_output<decl::Vector>(N_("Tangent Normal")); + b.add_output<decl::Float>(N_("Random")); +} static int node_shader_gpu_hair_info(GPUMaterial *mat, bNode *node, @@ -43,16 +44,18 @@ static int node_shader_gpu_hair_info(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_hair_info", in, out, length_link); } +} // namespace blender::nodes::node_shader_hair_info_cc + /* node type definition */ -void register_node_type_sh_hair_info(void) +void register_node_type_sh_hair_info() { + namespace file_ns = blender::nodes::node_shader_hair_info_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_HAIR_INFO, "Hair Info", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, outputs); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_hair_info); + sh_node_type_base(&ntype, SH_NODE_HAIR_INFO, "Hair Info", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_hair_info); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_holdout.c b/source/blender/nodes/shader/nodes/node_shader_holdout.cc index eb087183a0b..4f6f8a639de 100644 --- a/source/blender/nodes/shader/nodes/node_shader_holdout.c +++ b/source/blender/nodes/shader/nodes/node_shader_holdout.cc @@ -17,19 +17,14 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_holdout_cc { -static bNodeSocketTemplate sh_node_holdout_in[] = { - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_holdout_out[] = { - {SOCK_SHADER, N_("Holdout")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Shader>(N_("Holdout")); +} static int gpu_shader_rgb(GPUMaterial *mat, bNode *node, @@ -37,20 +32,21 @@ static int gpu_shader_rgb(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - GPU_material_flag_set(mat, GPU_MATFLAG_HOLDOUT); return GPU_stack_link(mat, node, "node_holdout", in, out); } +} // namespace blender::nodes::node_shader_holdout_cc + /* node type definition */ -void register_node_type_sh_holdout(void) +void register_node_type_sh_holdout() { + namespace file_ns = blender::nodes::node_shader_holdout_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_HOLDOUT, "Holdout", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_holdout_in, sh_node_holdout_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, gpu_shader_rgb); + sh_node_type_base(&ntype, SH_NODE_HOLDOUT, "Holdout", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_rgb); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c deleted file mode 100644 index 50eb5bf32c9..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2006 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup shdnodes - */ - -#include "node_shader_util.h" - -/* **************** Hue Saturation ******************** */ -static bNodeSocketTemplate sh_node_hue_sat_in[] = { - {SOCK_FLOAT, N_("Hue"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE}, - {SOCK_FLOAT, N_("Saturation"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_NONE}, - {SOCK_FLOAT, N_("Value"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_NONE}, - {SOCK_FLOAT, N_("Fac"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f}, - {-1, ""}, -}; -static bNodeSocketTemplate sh_node_hue_sat_out[] = { - {SOCK_RGBA, N_("Color")}, - {-1, ""}, -}; - -/* NOTE: it would be possible to use CMP version for both nodes. */ -static void do_hue_sat_fac( - bNode *UNUSED(node), float *out, float hue, float sat, float val, const float in[4], float fac) -{ - if (fac != 0.0f && (hue != 0.5f || sat != 1.0f || val != 1.0f)) { - float col[3], hsv[3], mfac = 1.0f - fac; - - rgb_to_hsv(in[0], in[1], in[2], hsv, hsv + 1, hsv + 2); - hsv[0] = fmodf(hsv[0] + hue + 0.5f, 1.0f); - hsv[1] = clamp_f(hsv[1] * sat, 0.0f, 1.0f); - hsv[2] *= val; - hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col + 1, col + 2); - - out[0] = mfac * in[0] + fac * col[0]; - out[1] = mfac * in[1] + fac * col[1]; - out[2] = mfac * in[2] + fac * col[2]; - } - else { - copy_v4_v4(out, in); - } -} - -static void node_shader_exec_hue_sat(void *UNUSED(data), - int UNUSED(thread), - bNode *node, - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - float hue, sat, val, fac; - float col[4]; - nodestack_get_vec(&hue, SOCK_FLOAT, in[0]); - nodestack_get_vec(&sat, SOCK_FLOAT, in[1]); - nodestack_get_vec(&val, SOCK_FLOAT, in[2]); - nodestack_get_vec(&fac, SOCK_FLOAT, in[3]); - nodestack_get_vec(col, SOCK_RGBA, in[4]); - do_hue_sat_fac(node, out[0]->vec, hue, sat, val, col, fac); -} - -static int gpu_shader_hue_sat(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - return GPU_stack_link(mat, node, "hue_sat", in, out); -} - -void register_node_type_sh_hue_sat(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, 0); - node_type_socket_templates(&ntype, sh_node_hue_sat_in, sh_node_hue_sat_out); - node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_hue_sat); - node_type_gpu(&ntype, gpu_shader_hue_sat); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.cc b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.cc new file mode 100644 index 00000000000..94b9a61c602 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.cc @@ -0,0 +1,61 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup shdnodes + */ + +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_hueSatVal_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Hue")).default_value(0.5f).min(0.0f).max(1.0f); + b.add_input<decl::Float>(N_("Saturation")).default_value(1.0f).min(0.0f).max(2.0f); + b.add_input<decl::Float>(N_("Value")).default_value(1.0f).min(0.0f).max(2.0f); + b.add_input<decl::Float>(N_("Fac")).default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_output<decl::Color>(N_("Color")); +} + +static int gpu_shader_hue_sat(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + return GPU_stack_link(mat, node, "hue_sat", in, out); +} + +} // namespace blender::nodes::node_shader_hueSatVal_cc + +void register_node_type_sh_hue_sat() +{ + namespace file_ns = blender::nodes::node_shader_hueSatVal_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR); + ntype.declare = file_ns::node_declare; + node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); + node_type_gpu(&ntype, file_ns::gpu_shader_hue_sat); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_ies_light.c b/source/blender/nodes/shader/nodes/node_shader_ies_light.c deleted file mode 100644 index 9cc5fd46181..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_ies_light.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2018 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** IES Light ******************** */ - -static bNodeSocketTemplate sh_node_tex_ies_in[] = { - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f, PROP_NONE}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_tex_ies_out[] = { - {SOCK_FLOAT, N_("Fac")}, - {-1, ""}, -}; - -static void node_shader_init_tex_ies(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeShaderTexIES *tex = MEM_callocN(sizeof(NodeShaderTexIES), "NodeShaderIESLight"); - node->storage = tex; -} - -/* node type definition */ -void register_node_type_sh_tex_ies(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_TEX_IES, "IES Texture", NODE_CLASS_TEXTURE, 0); - node_type_socket_templates(&ntype, sh_node_tex_ies_in, sh_node_tex_ies_out); - node_type_init(&ntype, node_shader_init_tex_ies); - node_type_storage( - &ntype, "NodeShaderTexIES", node_free_standard_storage, node_copy_standard_storage); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_ies_light.cc b/source/blender/nodes/shader/nodes/node_shader_ies_light.cc new file mode 100644 index 00000000000..82f0a3045c9 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_ies_light.cc @@ -0,0 +1,74 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2018 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_ies_light_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Vector>(N_("Vector")).hide_value(); + b.add_input<decl::Float>(N_("Strength")).default_value(1.0f).min(0.0f).max(1000000.0f); + b.add_output<decl::Float>(N_("Fac")); +} + +static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *row; + + row = uiLayoutRow(layout, false); + uiItemR(row, ptr, "mode", UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); + + row = uiLayoutRow(layout, true); + + if (RNA_enum_get(ptr, "mode") == NODE_IES_INTERNAL) { + uiItemR(row, ptr, "ies", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + } + else { + uiItemR(row, ptr, "filepath", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + } +} + +static void node_shader_init_tex_ies(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeShaderTexIES *tex = MEM_cnew<NodeShaderTexIES>("NodeShaderIESLight"); + node->storage = tex; +} + +} // namespace blender::nodes::node_shader_ies_light_cc + +/* node type definition */ +void register_node_type_sh_tex_ies() +{ + namespace file_ns = blender::nodes::node_shader_ies_light_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_TEX_IES, "IES Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_ies; + node_type_init(&ntype, file_ns::node_shader_init_tex_ies); + node_type_storage( + &ntype, "NodeShaderTexIES", node_free_standard_storage, node_copy_standard_storage); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_invert.c b/source/blender/nodes/shader/nodes/node_shader_invert.c deleted file mode 100644 index 0d6709a1968..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_invert.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup shdnodes - */ - -#include "node_shader_util.h" - -/* **************** INVERT ******************** */ -static bNodeSocketTemplate sh_node_invert_in[] = { - {SOCK_FLOAT, N_("Fac"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}}; - -static bNodeSocketTemplate sh_node_invert_out[] = {{SOCK_RGBA, N_("Color")}, {-1, ""}}; - -static void node_shader_exec_invert(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - float col[3], icol[3], fac; - - nodestack_get_vec(&fac, SOCK_FLOAT, in[0]); - nodestack_get_vec(col, SOCK_VECTOR, in[1]); - - icol[0] = 1.0f - col[0]; - icol[1] = 1.0f - col[1]; - icol[2] = 1.0f - col[2]; - - /* if fac, blend result against original input */ - if (fac < 1.0f) { - interp_v3_v3v3(out[0]->vec, col, icol, fac); - } - else { - copy_v3_v3(out[0]->vec, icol); - } -} - -static int gpu_shader_invert(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - return GPU_stack_link(mat, node, "invert", in, out); -} - -void register_node_type_sh_invert(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, 0); - node_type_socket_templates(&ntype, sh_node_invert_in, sh_node_invert_out); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_invert); - node_type_gpu(&ntype, gpu_shader_invert); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_invert.cc b/source/blender/nodes/shader/nodes/node_shader_invert.cc new file mode 100644 index 00000000000..3b5f4cb1d38 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_invert.cc @@ -0,0 +1,57 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup shdnodes + */ + +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_invert_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Fac")).default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); + b.add_input<decl::Color>(N_("Color")).default_value({0.0f, 0.0f, 0.0f, 1.0f}); + b.add_output<decl::Color>(N_("Color")); +} + +static int gpu_shader_invert(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + return GPU_stack_link(mat, node, "invert", in, out); +} + +} // namespace blender::nodes::node_shader_invert_cc + +void register_node_type_sh_invert() +{ + namespace file_ns = blender::nodes::node_shader_invert_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_invert); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c b/source/blender/nodes/shader/nodes/node_shader_layer_weight.cc index 599a44c2ec3..0294a0bde07 100644 --- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c +++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.cc @@ -17,21 +17,17 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** Layer Weight ******************** */ +namespace blender::nodes::node_shader_layer_weight_cc { -static bNodeSocketTemplate sh_node_layer_weight_in[] = { - {SOCK_FLOAT, N_("Blend"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_layer_weight_out[] = { - {SOCK_FLOAT, N_("Fresnel"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Facing"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Blend")).default_value(0.5f).min(0.0f).max(1.0f); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_output<decl::Float>(N_("Fresnel")); + b.add_output<decl::Float>(N_("Facing")); +} static int node_shader_gpu_layer_weight(GPUMaterial *mat, bNode *node, @@ -46,26 +42,18 @@ static int node_shader_gpu_layer_weight(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_layer_weight", in, out); } -static void node_shader_exec_layer_weight(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **UNUSED(in), - bNodeStack **UNUSED(out)) -{ -} +} // namespace blender::nodes::node_shader_layer_weight_cc /* node type definition */ -void register_node_type_sh_layer_weight(void) +void register_node_type_sh_layer_weight() { + namespace file_ns = blender::nodes::node_shader_layer_weight_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_LAYER_WEIGHT, "Layer Weight", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, sh_node_layer_weight_in, sh_node_layer_weight_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_layer_weight); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_layer_weight); + sh_node_type_base(&ntype, SH_NODE_LAYER_WEIGHT, "Layer Weight", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_layer_weight); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c b/source/blender/nodes/shader/nodes/node_shader_light_falloff.cc index 22172221f77..50eea2b3643 100644 --- a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c +++ b/source/blender/nodes/shader/nodes/node_shader_light_falloff.cc @@ -17,24 +17,18 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** INPUT ********************* */ +namespace blender::nodes::node_shader_light_falloff_cc { -static bNodeSocketTemplate sh_node_light_falloff_in[] = { - {SOCK_FLOAT, N_("Strength"), 100.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f}, - {SOCK_FLOAT, N_("Smooth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {-1, ""}, -}; - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_light_falloff_out[] = { - {SOCK_FLOAT, N_("Quadratic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Linear"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Constant"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Strength")).default_value(100.0f).min(0.0f).max(1000000.0f); + b.add_input<decl::Float>(N_("Smooth")).default_value(0.0f).min(0.0f).max(1000.0f); + b.add_output<decl::Float>(N_("Quadratic")); + b.add_output<decl::Float>(N_("Linear")); + b.add_output<decl::Float>(N_("Constant")); +} static int node_shader_gpu_light_falloff(GPUMaterial *mat, bNode *node, @@ -45,17 +39,19 @@ static int node_shader_gpu_light_falloff(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_light_falloff", in, out); } +} // namespace blender::nodes::node_shader_light_falloff_cc + /* node type definition */ -void register_node_type_sh_light_falloff(void) +void register_node_type_sh_light_falloff() { + namespace file_ns = blender::nodes::node_shader_light_falloff_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_LIGHT_FALLOFF, "Light Falloff", NODE_CLASS_OP_COLOR, 0); - node_type_socket_templates(&ntype, sh_node_light_falloff_in, sh_node_light_falloff_out); + sh_node_type_base(&ntype, SH_NODE_LIGHT_FALLOFF, "Light Falloff", NODE_CLASS_OP_COLOR); + ntype.declare = file_ns::node_declare; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_light_falloff); + node_type_gpu(&ntype, file_ns::node_shader_gpu_light_falloff); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_light_path.c b/source/blender/nodes/shader/nodes/node_shader_light_path.c deleted file mode 100644 index 45ad2133ee8..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_light_path.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_light_path_out[] = { - {SOCK_FLOAT, N_("Is Camera Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Is Shadow Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Is Diffuse Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Is Glossy Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Is Singular Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Is Reflection Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Is Transmission Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Ray Length"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Ray Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Diffuse Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Glossy Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Transparent Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Transmission Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; - -static int node_shader_gpu_light_path(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - return GPU_stack_link(mat, node, "node_light_path", in, out); -} - -/* node type definition */ -void register_node_type_sh_light_path(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_LIGHT_PATH, "Light Path", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, sh_node_light_path_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_light_path); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_light_path.cc b/source/blender/nodes/shader/nodes/node_shader_light_path.cc new file mode 100644 index 00000000000..6fbd5751886 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_light_path.cc @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_light_path_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Float>(N_("Is Camera Ray")); + b.add_output<decl::Float>(N_("Is Shadow Ray")); + b.add_output<decl::Float>(N_("Is Diffuse Ray")); + b.add_output<decl::Float>(N_("Is Glossy Ray")); + b.add_output<decl::Float>(N_("Is Singular Ray")); + b.add_output<decl::Float>(N_("Is Reflection Ray")); + b.add_output<decl::Float>(N_("Is Transmission Ray")); + b.add_output<decl::Float>(N_("Ray Length")); + b.add_output<decl::Float>(N_("Ray Depth")); + b.add_output<decl::Float>(N_("Diffuse Depth")); + b.add_output<decl::Float>(N_("Glossy Depth")); + b.add_output<decl::Float>(N_("Transparent Depth")); + b.add_output<decl::Float>(N_("Transmission Depth")); +} + +static int node_shader_gpu_light_path(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + return GPU_stack_link(mat, node, "node_light_path", in, out); +} + +} // namespace blender::nodes::node_shader_light_path_cc + +/* node type definition */ +void register_node_type_sh_light_path() +{ + namespace file_ns = blender::nodes::node_shader_light_path_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_LIGHT_PATH, "Light Path", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_light_path); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_map_range.cc b/source/blender/nodes/shader/nodes/node_shader_map_range.cc index 5ea194ddc83..bc7ca661a77 100644 --- a/source/blender/nodes/shader/nodes/node_shader_map_range.cc +++ b/source/blender/nodes/shader/nodes/node_shader_map_range.cc @@ -21,49 +21,173 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include <algorithm> + +#include "node_shader_util.hh" #include "BLI_math_base_safe.h" -namespace blender::nodes { +#include "NOD_socket_search_link.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_map_range_cc { + +NODE_STORAGE_FUNCS(NodeMapRange) static void sh_node_map_range_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Float>("Value").min(-10000.0f).max(10000.0f).default_value(1.0f); - b.add_input<decl::Float>("From Min").min(-10000.0f).max(10000.0f); - b.add_input<decl::Float>("From Max").min(-10000.0f).max(10000.0f).default_value(1.0f); - b.add_input<decl::Float>("To Min").min(-10000.0f).max(10000.0f); - b.add_input<decl::Float>("To Max").min(-10000.0f).max(10000.0f).default_value(1.0f); - b.add_input<decl::Float>("Steps").min(-10000.0f).max(10000.0f).default_value(4.0f); - b.add_output<decl::Float>("Result"); -}; + b.add_input<decl::Float>(N_("Value")).min(-10000.0f).max(10000.0f).default_value(1.0f); + b.add_input<decl::Float>(N_("From Min")).min(-10000.0f).max(10000.0f); + b.add_input<decl::Float>(N_("From Max")).min(-10000.0f).max(10000.0f).default_value(1.0f); + b.add_input<decl::Float>(N_("To Min")).min(-10000.0f).max(10000.0f); + b.add_input<decl::Float>(N_("To Max")).min(-10000.0f).max(10000.0f).default_value(1.0f); + b.add_input<decl::Float>(N_("Steps")).min(-10000.0f).max(10000.0f).default_value(4.0f); + b.add_input<decl::Vector>(N_("Vector")).min(0.0f).max(1.0f).hide_value(); + b.add_input<decl::Vector>(N_("From Min"), "From_Min_FLOAT3"); + b.add_input<decl::Vector>(N_("From Max"), "From_Max_FLOAT3").default_value(float3(1.0f)); + b.add_input<decl::Vector>(N_("To Min"), "To_Min_FLOAT3"); + b.add_input<decl::Vector>(N_("To Max"), "To_Max_FLOAT3").default_value(float3(1.0f)); + b.add_input<decl::Vector>(N_("Steps"), "Steps_FLOAT3").default_value(float3(4.0f)); + b.add_output<decl::Float>(N_("Result")); + b.add_output<decl::Vector>(N_("Vector")); +} -} // namespace blender::nodes +static void node_shader_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + uiItemR(layout, ptr, "interpolation_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + if (!ELEM(RNA_enum_get(ptr, "interpolation_type"), + NODE_MAP_RANGE_SMOOTHSTEP, + NODE_MAP_RANGE_SMOOTHERSTEP)) { + uiItemR(layout, ptr, "clamp", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + } +} -static void node_shader_update_map_range(bNodeTree *UNUSED(ntree), bNode *node) +static void node_shader_update_map_range(bNodeTree *ntree, bNode *node) { - bNodeSocket *sockSteps = nodeFindSocket(node, SOCK_IN, "Steps"); - nodeSetSocketAvailability(sockSteps, node->custom2 == NODE_MAP_RANGE_STEPPED); + const NodeMapRange &storage = node_storage(*node); + const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type); + const int type = (data_type == CD_PROP_FLOAT) ? SOCK_FLOAT : SOCK_VECTOR; + + LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { + nodeSetSocketAvailability(ntree, socket, socket->type == type); + } + + LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) { + nodeSetSocketAvailability(ntree, socket, socket->type == type); + } + + if (storage.interpolation_type != NODE_MAP_RANGE_STEPPED) { + if (type == SOCK_FLOAT) { + bNodeSocket *sockSteps = (bNodeSocket *)BLI_findlink(&node->inputs, 5); + nodeSetSocketAvailability(ntree, sockSteps, false); + } + else { + bNodeSocket *sockSteps = (bNodeSocket *)BLI_findlink(&node->inputs, 11); + nodeSetSocketAvailability(ntree, sockSteps, false); + } + } } static void node_shader_init_map_range(bNodeTree *UNUSED(ntree), bNode *node) { + NodeMapRange *data = MEM_cnew<NodeMapRange>(__func__); + data->clamp = 1; + data->data_type = CD_PROP_FLOAT; + data->interpolation_type = NODE_MAP_RANGE_LINEAR; node->custom1 = true; /* use_clamp */ node->custom2 = NODE_MAP_RANGE_LINEAR; /* interpolation */ + node->storage = data; } -static const char *gpu_shader_get_name(int mode) +class SocketSearchOp { + public: + std::string socket_name; + CustomDataType data_type; + int interpolation_type = NODE_MAP_RANGE_LINEAR; + + void operator()(LinkSearchOpParams ¶ms) + { + bNode &node = params.add_node("ShaderNodeMapRange"); + node_storage(node).data_type = data_type; + node_storage(node).interpolation_type = interpolation_type; + params.update_and_connect_available_socket(node, socket_name); + } +}; + +static std::optional<CustomDataType> node_type_from_other_socket(const bNodeSocket &socket) +{ + switch (socket.type) { + case SOCK_FLOAT: + case SOCK_BOOLEAN: + case SOCK_INT: + return CD_PROP_FLOAT; + case SOCK_VECTOR: + case SOCK_RGBA: + return CD_PROP_FLOAT3; + default: + return {}; + } +} + +static void node_map_range_gather_link_searches(GatherLinkSearchOpParams ¶ms) { - switch (mode) { - case NODE_MAP_RANGE_LINEAR: - return "map_range_linear"; - case NODE_MAP_RANGE_STEPPED: - return "map_range_stepped"; - case NODE_MAP_RANGE_SMOOTHSTEP: - return "map_range_smoothstep"; - case NODE_MAP_RANGE_SMOOTHERSTEP: - return "map_range_smootherstep"; + const std::optional<CustomDataType> type = node_type_from_other_socket(params.other_socket()); + if (!type) { + return; + } + + if (params.in_out() == SOCK_IN) { + if (*type == CD_PROP_FLOAT3) { + params.add_item(IFACE_("Vector"), SocketSearchOp{"Vector", *type}, 0); + } + else { + params.add_item(IFACE_("Value"), SocketSearchOp{"Value", *type}, 0); + } + params.add_item(IFACE_("From Min"), SocketSearchOp{"From Min", *type}, -1); + params.add_item(IFACE_("From Max"), SocketSearchOp{"From Max", *type}, -1); + params.add_item(IFACE_("To Min"), SocketSearchOp{"To Min", *type}, -2); + params.add_item(IFACE_("To Max"), SocketSearchOp{"To Max", *type}, -2); + params.add_item(IFACE_("Steps"), SocketSearchOp{"Steps", *type, NODE_MAP_RANGE_STEPPED}, -3); + } + else { + if (*type == CD_PROP_FLOAT3) { + params.add_item(IFACE_("Vector"), SocketSearchOp{"Vector", *type}); + } + else { + params.add_item(IFACE_("Result"), SocketSearchOp{"Result", *type}); + } + } +} + +static const char *gpu_shader_get_name(int mode, bool use_vector) +{ + if (use_vector) { + switch (mode) { + case NODE_MAP_RANGE_LINEAR: + return "vector_map_range_linear"; + case NODE_MAP_RANGE_STEPPED: + return "vector_map_range_stepped"; + case NODE_MAP_RANGE_SMOOTHSTEP: + return "vector_map_range_smoothstep"; + case NODE_MAP_RANGE_SMOOTHERSTEP: + return "vector_map_range_smootherstep"; + } + } + else { + switch (mode) { + case NODE_MAP_RANGE_LINEAR: + return "map_range_linear"; + case NODE_MAP_RANGE_STEPPED: + return "map_range_stepped"; + case NODE_MAP_RANGE_SMOOTHSTEP: + return "map_range_smoothstep"; + case NODE_MAP_RANGE_SMOOTHERSTEP: + return "map_range_smootherstep"; + } } return nullptr; @@ -75,22 +199,205 @@ static int gpu_shader_map_range(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - const char *name = gpu_shader_get_name(node->custom2); - + const NodeMapRange &storage = node_storage(*node); + bool use_vector = (storage.data_type == CD_PROP_FLOAT3); + const char *name = gpu_shader_get_name(storage.interpolation_type, use_vector); + float clamp = storage.clamp ? 1.0f : 0.0f; int ret = 0; if (name != nullptr) { - ret = GPU_stack_link(mat, node, name, in, out); + ret = GPU_stack_link(mat, node, name, in, out, GPU_constant(&clamp)); } else { - ret = GPU_stack_link(mat, node, "map_range_linear", in, out); + ret = GPU_stack_link(mat, node, "map_range_linear", in, out, GPU_constant(&clamp)); } - if (ret && node->custom1 && - !ELEM(node->custom2, NODE_MAP_RANGE_SMOOTHSTEP, NODE_MAP_RANGE_SMOOTHERSTEP)) { + if (ret && storage.clamp && !use_vector && + !ELEM(storage.interpolation_type, NODE_MAP_RANGE_SMOOTHSTEP, NODE_MAP_RANGE_SMOOTHERSTEP)) { GPU_link(mat, "clamp_range", out[0].link, in[3].link, in[4].link, &out[0].link); } return ret; } +static inline float clamp_range(const float value, const float min, const float max) +{ + return (min > max) ? std::clamp(value, max, min) : std::clamp(value, min, max); +} + +static float3 clamp_range(const float3 value, const float3 min, const float3 max) +{ + return float3(clamp_range(value.x, min.x, max.x), + clamp_range(value.y, min.y, max.y), + clamp_range(value.z, min.z, max.z)); +} + +static void map_range_vector_signature(blender::fn::MFSignatureBuilder *signature, bool use_steps) +{ + signature->single_input<float3>("Vector"); + signature->single_input<float3>("From Min"); + signature->single_input<float3>("From Max"); + signature->single_input<float3>("To Min"); + signature->single_input<float3>("To Max"); + if (use_steps) { + signature->single_input<float3>("Steps"); + } + signature->single_output<float3>("Vector"); +} + +class MapRangeVectorFunction : public blender::fn::MultiFunction { + private: + bool clamp_; + + public: + MapRangeVectorFunction(bool clamp) : clamp_(clamp) + { + static blender::fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static blender::fn::MFSignature create_signature() + { + blender::fn::MFSignatureBuilder signature{"Vector Map Range"}; + map_range_vector_signature(&signature, false); + return signature.build(); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + const blender::VArray<float3> &values = params.readonly_single_input<float3>(0, "Vector"); + const blender::VArray<float3> &from_min = params.readonly_single_input<float3>(1, "From Min"); + const blender::VArray<float3> &from_max = params.readonly_single_input<float3>(2, "From Max"); + const blender::VArray<float3> &to_min = params.readonly_single_input<float3>(3, "To Min"); + const blender::VArray<float3> &to_max = params.readonly_single_input<float3>(4, "To Max"); + blender::MutableSpan<float3> results = params.uninitialized_single_output<float3>(5, "Vector"); + + for (int64_t i : mask) { + float3 factor = math::safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]); + results[i] = factor * (to_max[i] - to_min[i]) + to_min[i]; + } + + if (clamp_) { + for (int64_t i : mask) { + results[i] = clamp_range(results[i], to_min[i], to_max[i]); + } + } + } +}; + +class MapRangeSteppedVectorFunction : public blender::fn::MultiFunction { + private: + bool clamp_; + + public: + MapRangeSteppedVectorFunction(bool clamp) : clamp_(clamp) + { + static blender::fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static blender::fn::MFSignature create_signature() + { + blender::fn::MFSignatureBuilder signature{"Vector Map Range Stepped"}; + map_range_vector_signature(&signature, true); + return signature.build(); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + const blender::VArray<float3> &values = params.readonly_single_input<float3>(0, "Vector"); + const blender::VArray<float3> &from_min = params.readonly_single_input<float3>(1, "From Min"); + const blender::VArray<float3> &from_max = params.readonly_single_input<float3>(2, "From Max"); + const blender::VArray<float3> &to_min = params.readonly_single_input<float3>(3, "To Min"); + const blender::VArray<float3> &to_max = params.readonly_single_input<float3>(4, "To Max"); + const blender::VArray<float3> &steps = params.readonly_single_input<float3>(5, "Steps"); + blender::MutableSpan<float3> results = params.uninitialized_single_output<float3>(6, "Vector"); + + for (int64_t i : mask) { + float3 factor = math::safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]); + factor = math::safe_divide(math::floor(factor * (steps[i] + 1.0f)), steps[i]); + results[i] = factor * (to_max[i] - to_min[i]) + to_min[i]; + } + + if (clamp_) { + for (int64_t i : mask) { + results[i] = clamp_range(results[i], to_min[i], to_max[i]); + } + } + } +}; + +class MapRangeSmoothstepVectorFunction : public blender::fn::MultiFunction { + public: + MapRangeSmoothstepVectorFunction() + { + static blender::fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static blender::fn::MFSignature create_signature() + { + blender::fn::MFSignatureBuilder signature{"Vector Map Range Smoothstep"}; + map_range_vector_signature(&signature, false); + return signature.build(); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + const blender::VArray<float3> &values = params.readonly_single_input<float3>(0, "Vector"); + const blender::VArray<float3> &from_min = params.readonly_single_input<float3>(1, "From Min"); + const blender::VArray<float3> &from_max = params.readonly_single_input<float3>(2, "From Max"); + const blender::VArray<float3> &to_min = params.readonly_single_input<float3>(3, "To Min"); + const blender::VArray<float3> &to_max = params.readonly_single_input<float3>(4, "To Max"); + blender::MutableSpan<float3> results = params.uninitialized_single_output<float3>(5, "Vector"); + + for (int64_t i : mask) { + float3 factor = math::safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]); + clamp_v3(factor, 0.0f, 1.0f); + factor = (float3(3.0f) - 2.0f * factor) * (factor * factor); + results[i] = factor * (to_max[i] - to_min[i]) + to_min[i]; + } + } +}; + +class MapRangeSmootherstepVectorFunction : public blender::fn::MultiFunction { + public: + MapRangeSmootherstepVectorFunction() + { + static blender::fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static blender::fn::MFSignature create_signature() + { + blender::fn::MFSignatureBuilder signature{"Vector Map Range Smoothstep"}; + map_range_vector_signature(&signature, false); + return signature.build(); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + const blender::VArray<float3> &values = params.readonly_single_input<float3>(0, "Vector"); + const blender::VArray<float3> &from_min = params.readonly_single_input<float3>(1, "From Min"); + const blender::VArray<float3> &from_max = params.readonly_single_input<float3>(2, "From Max"); + const blender::VArray<float3> &to_min = params.readonly_single_input<float3>(3, "To Min"); + const blender::VArray<float3> &to_max = params.readonly_single_input<float3>(4, "To Max"); + blender::MutableSpan<float3> results = params.uninitialized_single_output<float3>(5, "Vector"); + + for (int64_t i : mask) { + float3 factor = math::safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]); + clamp_v3(factor, 0.0f, 1.0f); + factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f); + results[i] = factor * (to_max[i] - to_min[i]) + to_min[i]; + } + } +}; + static void map_range_signature(blender::fn::MFSignatureBuilder *signature, bool use_steps) { signature->single_input<float>("Value"); @@ -140,8 +447,7 @@ class MapRangeFunction : public blender::fn::MultiFunction { if (clamp_) { for (int64_t i : mask) { - results[i] = (to_min[i] > to_max[i]) ? clamp_f(results[i], to_max[i], to_min[i]) : - clamp_f(results[i], to_min[i], to_max[i]); + results[i] = clamp_range(results[i], to_min[i], to_max[i]); } } } @@ -185,8 +491,7 @@ class MapRangeSteppedFunction : public blender::fn::MultiFunction { if (clamp_) { for (int64_t i : mask) { - results[i] = (to_min[i] > to_max[i]) ? clamp_f(results[i], to_max[i], to_min[i]) : - clamp_f(results[i], to_min[i], to_max[i]); + results[i] = clamp_range(results[i], to_min[i], to_max[i]); } } } @@ -265,58 +570,107 @@ class MapRangeSmootherstepFunction : public blender::fn::MultiFunction { static void sh_node_map_range_build_multi_function( blender::nodes::NodeMultiFunctionBuilder &builder) { - bNode &bnode = builder.node(); - bool clamp = bnode.custom1 != 0; - int interpolation_type = bnode.custom2; - - switch (interpolation_type) { - case NODE_MAP_RANGE_LINEAR: { - if (clamp) { - static MapRangeFunction fn_with_clamp{true}; - builder.set_matching_fn(fn_with_clamp); - } - else { - static MapRangeFunction fn_without_clamp{false}; - builder.set_matching_fn(fn_without_clamp); + const NodeMapRange &storage = node_storage(builder.node()); + bool clamp = storage.clamp != 0; + int interpolation_type = storage.interpolation_type; + + switch (storage.data_type) { + case CD_PROP_FLOAT3: + switch (interpolation_type) { + case NODE_MAP_RANGE_LINEAR: { + if (clamp) { + static MapRangeVectorFunction fn_with_clamp{true}; + builder.set_matching_fn(fn_with_clamp); + } + else { + static MapRangeVectorFunction fn_without_clamp{false}; + builder.set_matching_fn(fn_without_clamp); + } + break; + } + case NODE_MAP_RANGE_STEPPED: { + if (clamp) { + static MapRangeSteppedVectorFunction fn_stepped_with_clamp{true}; + builder.set_matching_fn(fn_stepped_with_clamp); + } + else { + static MapRangeSteppedVectorFunction fn_stepped_without_clamp{false}; + builder.set_matching_fn(fn_stepped_without_clamp); + } + break; + } + case NODE_MAP_RANGE_SMOOTHSTEP: { + static MapRangeSmoothstepVectorFunction smoothstep; + builder.set_matching_fn(smoothstep); + break; + } + case NODE_MAP_RANGE_SMOOTHERSTEP: { + static MapRangeSmootherstepVectorFunction smootherstep; + builder.set_matching_fn(smootherstep); + break; + } + default: + break; } break; - } - case NODE_MAP_RANGE_STEPPED: { - if (clamp) { - static MapRangeSteppedFunction fn_stepped_with_clamp{true}; - builder.set_matching_fn(fn_stepped_with_clamp); - } - else { - static MapRangeSteppedFunction fn_stepped_without_clamp{false}; - builder.set_matching_fn(fn_stepped_without_clamp); + case CD_PROP_FLOAT: + switch (interpolation_type) { + case NODE_MAP_RANGE_LINEAR: { + if (clamp) { + static MapRangeFunction fn_with_clamp{true}; + builder.set_matching_fn(fn_with_clamp); + } + else { + static MapRangeFunction fn_without_clamp{false}; + builder.set_matching_fn(fn_without_clamp); + } + break; + } + case NODE_MAP_RANGE_STEPPED: { + if (clamp) { + static MapRangeSteppedFunction fn_stepped_with_clamp{true}; + builder.set_matching_fn(fn_stepped_with_clamp); + } + else { + static MapRangeSteppedFunction fn_stepped_without_clamp{false}; + builder.set_matching_fn(fn_stepped_without_clamp); + } + break; + } + case NODE_MAP_RANGE_SMOOTHSTEP: { + static MapRangeSmoothstepFunction smoothstep; + builder.set_matching_fn(smoothstep); + break; + } + case NODE_MAP_RANGE_SMOOTHERSTEP: { + static MapRangeSmootherstepFunction smootherstep; + builder.set_matching_fn(smootherstep); + break; + } + default: + break; } break; - } - case NODE_MAP_RANGE_SMOOTHSTEP: { - static MapRangeSmoothstepFunction smoothstep; - builder.set_matching_fn(smoothstep); - break; - } - case NODE_MAP_RANGE_SMOOTHERSTEP: { - static MapRangeSmootherstepFunction smootherstep; - builder.set_matching_fn(smootherstep); - break; - } - default: - break; } } -void register_node_type_sh_map_range(void) +} // namespace blender::nodes::node_shader_map_range_cc + +void register_node_type_sh_map_range() { - static bNodeType ntype; + namespace file_ns = blender::nodes::node_shader_map_range_cc; - sh_fn_node_type_base(&ntype, SH_NODE_MAP_RANGE, "Map Range", NODE_CLASS_CONVERTER, 0); - ntype.declare = blender::nodes::sh_node_map_range_declare; - node_type_init(&ntype, node_shader_init_map_range); - node_type_update(&ntype, node_shader_update_map_range); - node_type_gpu(&ntype, gpu_shader_map_range); - ntype.build_multi_function = sh_node_map_range_build_multi_function; + static bNodeType ntype; + sh_fn_node_type_base(&ntype, SH_NODE_MAP_RANGE, "Map Range", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::sh_node_map_range_declare; + ntype.draw_buttons = file_ns::node_shader_buts_map_range; + node_type_init(&ntype, file_ns::node_shader_init_map_range); + node_type_storage( + &ntype, "NodeMapRange", node_free_standard_storage, node_copy_standard_storage); + node_type_update(&ntype, file_ns::node_shader_update_map_range); + node_type_gpu(&ntype, file_ns::gpu_shader_map_range); + ntype.build_multi_function = file_ns::sh_node_map_range_build_multi_function; + ntype.gather_link_search_ops = file_ns::node_map_range_gather_link_searches; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c deleted file mode 100644 index 774e7fed029..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_mapping.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup shdnodes - */ - -#include "node_shader_util.h" - -/* **************** MAPPING ******************** */ -static bNodeSocketTemplate sh_node_mapping_in[] = { - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_NONE}, - {SOCK_VECTOR, N_("Location"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_TRANSLATION}, - {SOCK_VECTOR, N_("Rotation"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_EULER}, - {SOCK_VECTOR, N_("Scale"), 1.0f, 1.0f, 1.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_XYZ}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_mapping_out[] = { - {SOCK_VECTOR, N_("Vector")}, - {-1, ""}, -}; - -static int gpu_shader_mapping(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - static const char *names[] = { - [NODE_MAPPING_TYPE_POINT] = "mapping_point", - [NODE_MAPPING_TYPE_TEXTURE] = "mapping_texture", - [NODE_MAPPING_TYPE_VECTOR] = "mapping_vector", - [NODE_MAPPING_TYPE_NORMAL] = "mapping_normal", - }; - - if (node->custom1 < ARRAY_SIZE(names) && names[node->custom1]) { - return GPU_stack_link(mat, node, names[node->custom1], in, out); - } - - return 0; -} - -static void node_shader_update_mapping(bNodeTree *UNUSED(ntree), bNode *node) -{ - bNodeSocket *sock = nodeFindSocket(node, SOCK_IN, "Location"); - nodeSetSocketAvailability( - sock, ELEM(node->custom1, NODE_MAPPING_TYPE_POINT, NODE_MAPPING_TYPE_TEXTURE)); -} - -void register_node_type_sh_mapping(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_MAPPING, "Mapping", NODE_CLASS_OP_VECTOR, 0); - node_type_socket_templates(&ntype, sh_node_mapping_in, sh_node_mapping_out); - node_type_gpu(&ntype, gpu_shader_mapping); - node_type_update(&ntype, node_shader_update_mapping); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.cc b/source/blender/nodes/shader/nodes/node_shader_mapping.cc new file mode 100644 index 00000000000..19c3a26796e --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_mapping.cc @@ -0,0 +1,110 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup shdnodes + */ + +#include "node_shader_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_mapping_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Vector>(N_("Vector")) + .default_value({0.0f, 0.0f, 0.0f}) + .min(-FLT_MAX) + .max(FLT_MAX); + b.add_input<decl::Vector>(N_("Location")) + .default_value({0.0f, 0.0f, 0.0f}) + .min(-FLT_MAX) + .max(FLT_MAX) + .subtype(PROP_TRANSLATION); + b.add_input<decl::Vector>(N_("Rotation")) + .default_value({0.0f, 0.0f, 0.0f}) + .min(-FLT_MAX) + .max(FLT_MAX) + .subtype(PROP_EULER); + b.add_input<decl::Vector>(N_("Scale")) + .default_value({1.0f, 1.0f, 1.0f}) + .min(-FLT_MAX) + .max(FLT_MAX) + .subtype(PROP_XYZ); + b.add_output<decl::Vector>(N_("Vector")); +} + +static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "vector_type", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); +} + +static const char *gpu_shader_get_name(int mode) +{ + switch (mode) { + case NODE_MAPPING_TYPE_POINT: + return "mapping_point"; + case NODE_MAPPING_TYPE_TEXTURE: + return "mapping_texture"; + case NODE_MAPPING_TYPE_VECTOR: + return "mapping_vector"; + case NODE_MAPPING_TYPE_NORMAL: + return "mapping_normal"; + } + return nullptr; +} + +static int gpu_shader_mapping(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + if (gpu_shader_get_name(node->custom1)) { + return GPU_stack_link(mat, node, gpu_shader_get_name(node->custom1), in, out); + } + + return 0; +} + +static void node_shader_update_mapping(bNodeTree *ntree, bNode *node) +{ + bNodeSocket *sock = nodeFindSocket(node, SOCK_IN, "Location"); + nodeSetSocketAvailability( + ntree, sock, ELEM(node->custom1, NODE_MAPPING_TYPE_POINT, NODE_MAPPING_TYPE_TEXTURE)); +} + +} // namespace blender::nodes::node_shader_mapping_cc + +void register_node_type_sh_mapping() +{ + namespace file_ns = blender::nodes::node_shader_mapping_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_MAPPING, "Mapping", NODE_CLASS_OP_VECTOR); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_mapping; + node_type_gpu(&ntype, file_ns::gpu_shader_mapping); + node_type_update(&ntype, file_ns::node_shader_update_mapping); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_math.cc b/source/blender/nodes/shader/nodes/node_shader_math.cc index 96d1be49c04..50585405cbf 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.cc +++ b/source/blender/nodes/shader/nodes/node_shader_math.cc @@ -21,24 +21,67 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include "node_shader_util.hh" #include "NOD_math_functions.hh" +#include "NOD_socket_search_link.hh" + +#include "RNA_enum_types.h" /* **************** SCALAR MATH ******************** */ -namespace blender::nodes { +namespace blender::nodes::node_shader_math_cc { static void sh_node_math_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Float>("Value").default_value(0.5f).min(-10000.0f).max(10000.0f); - b.add_input<decl::Float>("Value", "Value_001").default_value(0.5f).min(-10000.0f).max(10000.0f); - b.add_input<decl::Float>("Value", "Value_002").default_value(0.5f).min(-10000.0f).max(10000.0f); - b.add_output<decl::Float>("Value"); + b.add_input<decl::Float>(N_("Value")).default_value(0.5f).min(-10000.0f).max(10000.0f); + b.add_input<decl::Float>(N_("Value"), "Value_001") + .default_value(0.5f) + .min(-10000.0f) + .max(10000.0f); + b.add_input<decl::Float>(N_("Value"), "Value_002") + .default_value(0.5f) + .min(-10000.0f) + .max(10000.0f); + b.add_output<decl::Float>(N_("Value")); +} + +class SocketSearchOp { + public: + std::string socket_name; + NodeMathOperation mode = NODE_MATH_ADD; + void operator()(LinkSearchOpParams ¶ms) + { + bNode &node = params.add_node("ShaderNodeMath"); + node.custom1 = mode; + params.update_and_connect_available_socket(node, socket_name); + } }; -} // namespace blender::nodes +static void sh_node_math_gather_link_searches(GatherLinkSearchOpParams ¶ms) +{ + if (!params.node_tree().typeinfo->validate_link( + static_cast<eNodeSocketDatatype>(params.other_socket().type), SOCK_FLOAT)) { + return; + } + + const bool is_geometry_node_tree = params.node_tree().type == NTREE_GEOMETRY; + const int weight = ELEM(params.other_socket().type, SOCK_FLOAT, SOCK_BOOLEAN, SOCK_INT) ? 0 : -1; + + for (const EnumPropertyItem *item = rna_enum_node_math_items; item->identifier != nullptr; + item++) { + if (item->name != nullptr && item->identifier[0] != '\0') { + const int gn_weight = + (is_geometry_node_tree && + ELEM(item->value, NODE_MATH_COMPARE, NODE_MATH_GREATER_THAN, NODE_MATH_LESS_THAN)) ? + -1 : + weight; + params.add_item( + IFACE_(item->name), SocketSearchOp{"Value", (NodeMathOperation)item->value}, gn_weight); + } + } +} static const char *gpu_shader_get_name(int mode) { @@ -82,7 +125,8 @@ static const blender::fn::MultiFunction *get_base_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl_to_fl( mode, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SO<float, float> fn{info.title_case_name, function}; + static blender::fn::CustomMF_SI_SO<float, float> fn{info.title_case_name.c_str(), + function}; base_fn = &fn; }); if (base_fn != nullptr) { @@ -91,7 +135,7 @@ static const blender::fn::MultiFunction *get_base_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl_fl_to_fl( mode, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{info.title_case_name, + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{info.title_case_name.c_str(), function}; base_fn = &fn; }); @@ -102,7 +146,7 @@ static const blender::fn::MultiFunction *get_base_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl_fl_fl_to_fl( mode, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { static blender::fn::CustomMF_SI_SI_SI_SO<float, float, float, float> fn{ - info.title_case_name, function}; + info.title_case_name.c_str(), function}; base_fn = &fn; }); if (base_fn != nullptr) { @@ -154,16 +198,21 @@ static void sh_node_math_build_multi_function(blender::nodes::NodeMultiFunctionB } } -void register_node_type_sh_math(void) +} // namespace blender::nodes::node_shader_math_cc + +void register_node_type_sh_math() { + namespace file_ns = blender::nodes::node_shader_math_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTER, 0); - ntype.declare = blender::nodes::sh_node_math_declare; - node_type_label(&ntype, node_math_label); - node_type_gpu(&ntype, gpu_shader_math); + sh_fn_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::sh_node_math_declare; + ntype.labelfunc = node_math_label; + node_type_gpu(&ntype, file_ns::gpu_shader_math); node_type_update(&ntype, node_math_update); - ntype.build_multi_function = sh_node_math_build_multi_function; + ntype.build_multi_function = file_ns::sh_node_math_build_multi_function; + ntype.gather_link_search_ops = file_ns::sh_node_math_gather_link_searches; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.cc b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc index d4d02e80ada..9678e86d289 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc @@ -21,45 +21,17 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include "node_shader_util.hh" -namespace blender::nodes { +namespace blender::nodes::node_shader_mix_rgb_cc { static void sh_node_mix_rgb_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Float>("Fac").default_value(0.5f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); - b.add_input<decl::Color>("Color1").default_value({0.5f, 0.5f, 0.5f, 1.0f}); - b.add_input<decl::Color>("Color2").default_value({0.5f, 0.5f, 0.5f, 1.0f}); - b.add_output<decl::Color>("Color"); -}; - -} // namespace blender::nodes - -static void node_shader_exec_mix_rgb(void *UNUSED(data), - int UNUSED(thread), - bNode *node, - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - /* stack order in: fac, col1, col2 */ - /* stack order out: col */ - float col[3]; - float fac; - float vec[3]; - - nodestack_get_vec(&fac, SOCK_FLOAT, in[0]); - CLAMP(fac, 0.0f, 1.0f); - - nodestack_get_vec(col, SOCK_VECTOR, in[1]); - nodestack_get_vec(vec, SOCK_VECTOR, in[2]); - - ramp_blend(node->custom1, col, fac, vec); - if (node->custom2 & SHD_MIXRGB_CLAMP) { - CLAMP3(col, 0.0f, 1.0f); - } - copy_v3_v3(out[0]->vec, col); + b.add_input<decl::Float>(N_("Fac")).default_value(0.5f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); + b.add_input<decl::Color>(N_("Color1")).default_value({0.5f, 0.5f, 0.5f, 1.0f}); + b.add_input<decl::Color>(N_("Color2")).default_value({0.5f, 0.5f, 0.5f, 1.0f}); + b.add_output<decl::Color>(N_("Color")); } static const char *gpu_shader_get_name(int mode) @@ -183,16 +155,19 @@ static void sh_node_mix_rgb_build_multi_function(blender::nodes::NodeMultiFuncti builder.construct_and_set_matching_fn<MixRGBFunction>(clamp, mix_type); } -void register_node_type_sh_mix_rgb(void) +} // namespace blender::nodes::node_shader_mix_rgb_cc + +void register_node_type_sh_mix_rgb() { + namespace file_ns = blender::nodes::node_shader_mix_rgb_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, 0); - ntype.declare = blender::nodes::sh_node_mix_rgb_declare; - node_type_label(&ntype, node_blend_label); - node_type_exec(&ntype, nullptr, nullptr, node_shader_exec_mix_rgb); - node_type_gpu(&ntype, gpu_shader_mix_rgb); - ntype.build_multi_function = sh_node_mix_rgb_build_multi_function; + sh_fn_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR); + ntype.declare = file_ns::sh_node_mix_rgb_declare; + ntype.labelfunc = node_blend_label; + node_type_gpu(&ntype, file_ns::gpu_shader_mix_rgb); + ntype.build_multi_function = file_ns::sh_node_mix_rgb_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mix_shader.c b/source/blender/nodes/shader/nodes/node_shader_mix_shader.cc index 33cbf34543c..d9aa906e451 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mix_shader.c +++ b/source/blender/nodes/shader/nodes/node_shader_mix_shader.cc @@ -17,21 +17,17 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_mix_shader_cc { -static bNodeSocketTemplate sh_node_mix_shader_in[] = { - {SOCK_FLOAT, N_("Fac"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_SHADER, N_("Shader")}, - {SOCK_SHADER, N_("Shader")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_mix_shader_out[] = { - {SOCK_SHADER, N_("Shader")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Fac")).default_value(0.5f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); + b.add_input<decl::Shader>(N_("Shader")); + b.add_input<decl::Shader>(N_("Shader"), "Shader_001"); + b.add_output<decl::Shader>(N_("Shader")); +} static int node_shader_gpu_mix_shader(GPUMaterial *mat, bNode *node, @@ -42,16 +38,18 @@ static int node_shader_gpu_mix_shader(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_mix_shader", in, out); } +} // namespace blender::nodes::node_shader_mix_shader_cc + /* node type definition */ -void register_node_type_sh_mix_shader(void) +void register_node_type_sh_mix_shader() { + namespace file_ns = blender::nodes::node_shader_mix_shader_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_MIX_SHADER, "Mix Shader", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_mix_shader_in, sh_node_mix_shader_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_mix_shader); + sh_node_type_base(&ntype, SH_NODE_MIX_SHADER, "Mix Shader", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_mix_shader); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.cc index 83d5abcba67..e677f36e425 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal.cc @@ -21,37 +21,23 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include "node_shader_util.hh" -/* **************** NORMAL ******************** */ -static bNodeSocketTemplate sh_node_normal_in[] = { - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_normal_cc { -static bNodeSocketTemplate sh_node_normal_out[] = { - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION}, - {SOCK_FLOAT, N_("Dot")}, - {-1, ""}, -}; - -/* generates normal, does dot product */ -static void node_shader_exec_normal(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) +static void node_declare(NodeDeclarationBuilder &b) { - float vec[3]; - - /* stack order input: normal */ - /* stack order output: normal, value */ - - nodestack_get_vec(vec, SOCK_VECTOR, in[0]); - - /* render normals point inside... the widget points outside */ - out[1]->vec[0] = -dot_v3v3(vec, out[0]->vec); + b.add_input<decl::Vector>(N_("Normal")) + .default_value({0.0f, 0.0f, 1.0f}) + .min(-1.0f) + .max(1.0f) + .subtype(PROP_DIRECTION); + b.add_output<decl::Vector>(N_("Normal")) + .default_value({0.0f, 0.0f, 1.0f}) + .min(-1.0f) + .max(1.0f) + .subtype(PROP_DIRECTION); + b.add_output<decl::Float>(N_("Dot")); } static int gpu_shader_normal(GPUMaterial *mat, @@ -64,14 +50,17 @@ static int gpu_shader_normal(GPUMaterial *mat, return GPU_stack_link(mat, node, "normal_new_shading", in, out, vec); } -void register_node_type_sh_normal(void) +} // namespace blender::nodes::node_shader_normal_cc + +void register_node_type_sh_normal() { + namespace file_ns = blender::nodes::node_shader_normal_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, 0); - node_type_socket_templates(&ntype, sh_node_normal_in, sh_node_normal_out); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_normal); - node_type_gpu(&ntype, gpu_shader_normal); + sh_node_type_base(&ntype, SH_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_normal); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.cc index 6c4f2070035..9eadb6ce014 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.cc @@ -17,34 +17,43 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +#include "BKE_context.h" -static bNodeSocketTemplate sh_node_normal_map_in[] = { - {SOCK_FLOAT, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f}, - {SOCK_RGBA, N_("Color"), 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +#include "UI_interface.h" +#include "UI_resources.h" -static bNodeSocketTemplate sh_node_normal_map_out[] = { - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_normal_map_cc { -static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node) +static void node_declare(NodeDeclarationBuilder &b) { - NodeShaderNormalMap *attr = MEM_callocN(sizeof(NodeShaderNormalMap), "NodeShaderNormalMap"); - node->storage = attr; + b.add_input<decl::Float>(N_("Strength")).default_value(1.0f).min(0.0f).max(10.0f); + b.add_input<decl::Color>(N_("Color")).default_value({0.5f, 0.5f, 1.0f, 1.0f}); + b.add_output<decl::Vector>(N_("Normal")); +} + +static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiItemR(layout, ptr, "space", UI_ITEM_R_SPLIT_EMPTY_NAME, "", 0); + + if (RNA_enum_get(ptr, "space") == SHD_SPACE_TANGENT) { + PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); + + if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { + PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); + uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); + } + else { + uiItemR(layout, ptr, "uv_map", UI_ITEM_R_SPLIT_EMPTY_NAME, "", 0); + } + } } -static void node_shader_exec_normal_map(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **UNUSED(in), - bNodeStack **UNUSED(out)) +static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node) { + NodeShaderNormalMap *attr = MEM_cnew<NodeShaderNormalMap>("NodeShaderNormalMap"); + node->storage = attr; } static int gpu_shader_normal_map(GPUMaterial *mat, @@ -53,15 +62,16 @@ static int gpu_shader_normal_map(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - NodeShaderNormalMap *nm = node->storage; + NodeShaderNormalMap *nm = static_cast<NodeShaderNormalMap *>(node->storage); GPUNodeLink *strength; if (in[0].link) { strength = in[0].link; } else if (node->original) { - bNodeSocket *socket = BLI_findlink(&node->original->inputs, 0); - bNodeSocketValueFloat *socket_data = socket->default_value; + bNodeSocket *socket = static_cast<bNodeSocket *>(BLI_findlink(&node->original->inputs, 0)); + bNodeSocketValueFloat *socket_data = static_cast<bNodeSocketValueFloat *>( + socket->default_value); strength = GPU_uniform(&socket_data->value); } else { @@ -73,8 +83,8 @@ static int gpu_shader_normal_map(GPUMaterial *mat, newnormal = in[1].link; } else if (node->original) { - bNodeSocket *socket = BLI_findlink(&node->original->inputs, 1); - bNodeSocketValueRGBA *socket_data = socket->default_value; + bNodeSocket *socket = static_cast<bNodeSocket *>(BLI_findlink(&node->original->inputs, 1)); + bNodeSocketValueRGBA *socket_data = static_cast<bNodeSocketValueRGBA *>(socket->default_value); newnormal = GPU_uniform(socket_data->value); } else { @@ -111,19 +121,23 @@ static int gpu_shader_normal_map(GPUMaterial *mat, return true; } +} // namespace blender::nodes::node_shader_normal_map_cc + /* node type definition */ -void register_node_type_sh_normal_map(void) +void register_node_type_sh_normal_map() { + namespace file_ns = blender::nodes::node_shader_normal_map_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_NORMAL_MAP, "Normal Map", NODE_CLASS_OP_VECTOR, 0); - node_type_socket_templates(&ntype, sh_node_normal_map_in, sh_node_normal_map_out); + sh_node_type_base(&ntype, SH_NODE_NORMAL_MAP, "Normal Map", NODE_CLASS_OP_VECTOR); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_normal_map; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, node_shader_init_normal_map); + node_type_init(&ntype, file_ns::node_shader_init_normal_map); node_type_storage( &ntype, "NodeShaderNormalMap", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, gpu_shader_normal_map); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_normal_map); + node_type_gpu(&ntype, file_ns::gpu_shader_normal_map); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.cc index f3eb5dcc26d..75c9c8f9206 100644 --- a/source/blender/nodes/shader/nodes/node_shader_object_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_object_info.cc @@ -17,18 +17,18 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_object_info_cc { -static bNodeSocketTemplate sh_node_object_info_out[] = { - {SOCK_VECTOR, N_("Location"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Object Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Material Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Random"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Vector>(N_("Location")); + b.add_output<decl::Color>(N_("Color")); + b.add_output<decl::Float>(N_("Object Index")); + b.add_output<decl::Float>(N_("Material Index")); + b.add_output<decl::Float>(N_("Random")); +} static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *node, @@ -42,13 +42,17 @@ static int node_shader_gpu_object_info(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_object_info", in, out, GPU_constant(&index)); } -void register_node_type_sh_object_info(void) +} // namespace blender::nodes::node_shader_object_info_cc + +void register_node_type_sh_object_info() { + namespace file_ns = blender::nodes::node_shader_object_info_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, sh_node_object_info_out); - node_type_gpu(&ntype, node_shader_gpu_object_info); + sh_node_type_base(&ntype, SH_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_object_info); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_output_aov.c b/source/blender/nodes/shader/nodes/node_shader_output_aov.cc index 18c8edfe41c..b5177014f3a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_aov.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_aov.cc @@ -17,21 +17,29 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" #include "BLI_hash.h" -/* **************** OUTPUT ******************** */ +#include "UI_interface.h" +#include "UI_resources.h" -static bNodeSocketTemplate sh_node_output_aov_in[] = { - {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_output_aov_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.0f, 0.0f, 0.0f, 1.0f}); + b.add_input<decl::Float>(N_("Value")).default_value(0.0f).min(0.0f).max(1.0f); +} + +static void node_shader_buts_output_aov(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "name", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); +} static void node_shader_init_output_aov(bNodeTree *UNUSED(ntree), bNode *node) { - NodeShaderOutputAOV *aov = MEM_callocN(sizeof(NodeShaderOutputAOV), "NodeShaderOutputAOV"); + NodeShaderOutputAOV *aov = MEM_cnew<NodeShaderOutputAOV>("NodeShaderOutputAOV"); node->storage = aov; } @@ -49,20 +57,24 @@ static int node_shader_gpu_output_aov(GPUMaterial *mat, return true; } +} // namespace blender::nodes::node_shader_output_aov_cc + /* node type definition */ -void register_node_type_sh_output_aov(void) +void register_node_type_sh_output_aov() { + namespace file_ns = blender::nodes::node_shader_output_aov_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_OUTPUT_AOV, "AOV Output", NODE_CLASS_OUTPUT, 0); - node_type_socket_templates(&ntype, sh_node_output_aov_in, NULL); - node_type_init(&ntype, node_shader_init_output_aov); + sh_node_type_base(&ntype, SH_NODE_OUTPUT_AOV, "AOV Output", NODE_CLASS_OUTPUT); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_output_aov; + node_type_init(&ntype, file_ns::node_shader_init_output_aov); node_type_storage( &ntype, "NodeShaderOutputAOV", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_output_aov); + node_type_gpu(&ntype, file_ns::node_shader_gpu_output_aov); - /* Do not allow muting output node. */ - node_type_internal_links(&ntype, NULL); + ntype.no_muting = true; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_output_light.c b/source/blender/nodes/shader/nodes/node_shader_output_light.cc index 722202bafdc..0c8288f801b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_light.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_light.cc @@ -17,27 +17,27 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_output_light_cc { -static bNodeSocketTemplate sh_node_output_light_in[] = { - {SOCK_SHADER, N_("Surface"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Shader>(N_("Surface")); +} + +} // namespace blender::nodes::node_shader_output_light_cc /* node type definition */ -void register_node_type_sh_output_light(void) +void register_node_type_sh_output_light() { - static bNodeType ntype; + namespace file_ns = blender::nodes::node_shader_output_light_cc; - sh_node_type_base(&ntype, SH_NODE_OUTPUT_LIGHT, "Light Output", NODE_CLASS_OUTPUT, 0); - node_type_socket_templates(&ntype, sh_node_output_light_in, NULL); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); + static bNodeType ntype; - /* Do not allow muting output node. */ - node_type_internal_links(&ntype, NULL); + sh_node_type_base(&ntype, SH_NODE_OUTPUT_LIGHT, "Light Output", NODE_CLASS_OUTPUT); + ntype.declare = file_ns::node_declare; + ntype.no_muting = true; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_output_linestyle.c b/source/blender/nodes/shader/nodes/node_shader_output_linestyle.c deleted file mode 100644 index 5b4ebf21f5f..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_output_linestyle.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_output_linestyle_in[] = { - {SOCK_RGBA, N_("Color"), 1.0f, 0.0f, 1.0f, 1.0f}, - {SOCK_FLOAT, N_("Color Fac"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Alpha Fac"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {-1, ""}, -}; - -/* node type definition */ -void register_node_type_sh_output_linestyle(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_OUTPUT_LINESTYLE, "Line Style Output", NODE_CLASS_OUTPUT, 0); - node_type_socket_templates(&ntype, sh_node_output_linestyle_in, NULL); - node_type_init(&ntype, NULL); - - /* Do not allow muting output node. */ - node_type_internal_links(&ntype, NULL); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_output_linestyle.cc b/source/blender/nodes/shader/nodes/node_shader_output_linestyle.cc new file mode 100644 index 00000000000..9b6c3292e75 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_output_linestyle.cc @@ -0,0 +1,72 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_output_linestyle_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 0.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Color Fac")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Alpha")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Alpha Fac")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); +} + +static void node_buts_output_linestyle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *row, *col; + + col = uiLayoutColumn(layout, false); + row = uiLayoutRow(col, true); + uiItemR(row, ptr, "blend_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + uiItemR(col, ptr, "use_clamp", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); +} + +} // namespace blender::nodes::node_shader_output_linestyle_cc + +/* node type definition */ +void register_node_type_sh_output_linestyle() +{ + namespace file_ns = blender::nodes::node_shader_output_linestyle_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_OUTPUT_LINESTYLE, "Line Style Output", NODE_CLASS_OUTPUT); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_buts_output_linestyle; + ntype.no_muting = true; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.c b/source/blender/nodes/shader/nodes/node_shader_output_material.c deleted file mode 100644 index 5b6d2914ccf..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_output_material.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -#include "BKE_scene.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_output_material_in[] = { - {SOCK_SHADER, N_("Surface")}, - {SOCK_SHADER, N_("Volume")}, - {SOCK_VECTOR, - N_("Displacement"), - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - PROP_NONE, - SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Thickness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {-1, ""}, -}; - -static int node_shader_gpu_output_material(GPUMaterial *mat, - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *UNUSED(out)) -{ - GPUNodeLink *outlink_surface, *outlink_volume, *outlink_displacement, *outlink_thickness; - /* Passthrough node in order to do the right socket conversions (important for displacement). */ - if (in[0].link) { - GPU_link(mat, "node_output_material_surface", in[0].link, &outlink_surface); - GPU_material_output_surface(mat, outlink_surface); - } - if (in[1].link) { - GPU_link(mat, "node_output_material_volume", in[1].link, &outlink_volume); - GPU_material_output_volume(mat, outlink_volume); - } - if (in[2].link) { - GPU_link(mat, "node_output_material_displacement", in[2].link, &outlink_displacement); - GPU_material_output_displacement(mat, outlink_displacement); - } - if (in[3].link) { - GPU_link(mat, "node_output_material_thickness", in[3].link, &outlink_thickness); - GPU_material_output_thickness(mat, outlink_thickness); - } - return true; -} - -/* node type definition */ -void register_node_type_sh_output_material(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_OUTPUT_MATERIAL, "Material Output", NODE_CLASS_OUTPUT, 0); - node_type_socket_templates(&ntype, sh_node_output_material_in, NULL); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_output_material); - - /* Do not allow muting output node. */ - node_type_internal_links(&ntype, NULL); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.cc b/source/blender/nodes/shader/nodes/node_shader_output_material.cc new file mode 100644 index 00000000000..5fc95b92e3f --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_output_material.cc @@ -0,0 +1,83 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +#include "BKE_scene.h" + +namespace blender::nodes::node_shader_output_material_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Shader>(N_("Surface")); + b.add_input<decl::Shader>(N_("Volume")); + b.add_input<decl::Vector>(N_("Displacement")).hide_value(); +} + +static int node_shader_gpu_output_material(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + GPUNodeLink *outlink, *alpha_threshold_link, *shadow_threshold_link; + Material *ma = GPU_material_get_material(mat); + + static float no_alpha_threshold = -1.0f; + if (ma) { + alpha_threshold_link = GPU_uniform((ma->blend_method == MA_BM_CLIP) ? &ma->alpha_threshold : + &no_alpha_threshold); + shadow_threshold_link = GPU_uniform((ma->blend_shadow == MA_BS_CLIP) ? &ma->alpha_threshold : + &no_alpha_threshold); + } + else { + alpha_threshold_link = GPU_uniform(&no_alpha_threshold); + shadow_threshold_link = GPU_uniform(&no_alpha_threshold); + } + + GPU_stack_link(mat, + node, + "node_output_material", + in, + out, + alpha_threshold_link, + shadow_threshold_link, + &outlink); + GPU_material_output_link(mat, outlink); + + return true; +} + +} // namespace blender::nodes::node_shader_output_material_cc + +/* node type definition */ +void register_node_type_sh_output_material() +{ + namespace file_ns = blender::nodes::node_shader_output_material_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_OUTPUT_MATERIAL, "Material Output", NODE_CLASS_OUTPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_output_material); + + ntype.no_muting = true; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_output_world.c b/source/blender/nodes/shader/nodes/node_shader_output_world.cc index eaecfc266a3..a3509fd3ff4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_world.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_world.cc @@ -17,15 +17,15 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_output_world_cc { -static bNodeSocketTemplate sh_node_output_world_in[] = { - {SOCK_SHADER, N_("Surface"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_SHADER, N_("Volume"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Shader>(N_("Surface")); + b.add_input<decl::Shader>(N_("Volume")); +} static int node_shader_gpu_output_world(GPUMaterial *mat, bNode *UNUSED(node), @@ -45,19 +45,20 @@ static int node_shader_gpu_output_world(GPUMaterial *mat, return true; } +} // namespace blender::nodes::node_shader_output_world_cc + /* node type definition */ -void register_node_type_sh_output_world(void) +void register_node_type_sh_output_world() { + namespace file_ns = blender::nodes::node_shader_output_world_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_OUTPUT_WORLD, "World Output", NODE_CLASS_OUTPUT, 0); - node_type_socket_templates(&ntype, sh_node_output_world_in, NULL); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_output_world); + sh_node_type_base(&ntype, SH_NODE_OUTPUT_WORLD, "World Output", NODE_CLASS_OUTPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_output_world); - /* Do not allow muting output node. */ - node_type_internal_links(&ntype, NULL); + ntype.no_muting = true; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_particle_info.c b/source/blender/nodes/shader/nodes/node_shader_particle_info.cc index 75966843294..5792282fa0f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_particle_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_particle_info.cc @@ -17,30 +17,25 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" + #include "RE_texture.h" -static bNodeSocketTemplate outputs[] = { - {SOCK_FLOAT, "Index"}, - {SOCK_FLOAT, "Random"}, - {SOCK_FLOAT, "Age"}, - {SOCK_FLOAT, "Lifetime"}, - {SOCK_VECTOR, "Location"}, +namespace blender::nodes::node_shader_particle_info_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Float>(N_("Index")); + b.add_output<decl::Float>(N_("Random")); + b.add_output<decl::Float>(N_("Age")); + b.add_output<decl::Float>(N_("Lifetime")); + b.add_output<decl::Vector>(N_("Location")); #if 0 /* quaternion sockets not yet supported */ - {SOCK_QUATERNION, "Rotation"}, + b.add_output<decl::Quaternion>(N_("Rotation")); #endif - {SOCK_FLOAT, "Size"}, - {SOCK_VECTOR, "Velocity"}, - {SOCK_VECTOR, "Angular Velocity"}, - {-1, ""}, -}; -static void node_shader_exec_particle_info(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **UNUSED(in), - bNodeStack **UNUSED(out)) -{ + b.add_output<decl::Float>(N_("Size")); + b.add_output<decl::Vector>(N_("Velocity")); + b.add_output<decl::Vector>(N_("Angular Velocity")); } static int gpu_shader_particle_info(GPUMaterial *mat, @@ -54,15 +49,18 @@ static int gpu_shader_particle_info(GPUMaterial *mat, return GPU_stack_link(mat, node, "particle_info", in, out); } +} // namespace blender::nodes::node_shader_particle_info_cc + /* node type definition */ -void register_node_type_sh_particle_info(void) +void register_node_type_sh_particle_info() { + namespace file_ns = blender::nodes::node_shader_particle_info_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_PARTICLE_INFO, "Particle Info", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, outputs); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_particle_info); - node_type_gpu(&ntype, gpu_shader_particle_info); + sh_node_type_base(&ntype, SH_NODE_PARTICLE_INFO, "Particle Info", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_particle_info); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_point_info.cc b/source/blender/nodes/shader/nodes/node_shader_point_info.cc new file mode 100644 index 00000000000..adc58ca065a --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_point_info.cc @@ -0,0 +1,54 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_point_info_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Vector>(N_("Position")); + b.add_output<decl::Float>(N_("Radius")); + b.add_output<decl::Float>(N_("Random")); +} + +static int node_shader_gpu_point_info(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + return GPU_stack_link(mat, node, "node_point_info", in, out); +} + +} // namespace blender::nodes::node_shader_point_info_cc + +/* node type definition */ +void register_node_type_sh_point_info() +{ + namespace file_ns = blender::nodes::node_shader_point_info_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_POINT_INFO, "Point Info", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_point_info); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_rgb.c b/source/blender/nodes/shader/nodes/node_shader_rgb.cc index 0bdef9a2a17..f3b83b72232 100644 --- a/source/blender/nodes/shader/nodes/node_shader_rgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_rgb.cc @@ -21,13 +21,14 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include "node_shader_util.hh" -/* **************** RGB ******************** */ -static bNodeSocketTemplate sh_node_rgb_out[] = { - {SOCK_RGBA, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_rgb_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Color>(N_("Color")).default_value({0.5f, 0.5f, 0.5f, 1.0f}); +} static int gpu_shader_rgb(GPUMaterial *mat, bNode *node, @@ -39,13 +40,17 @@ static int gpu_shader_rgb(GPUMaterial *mat, return GPU_stack_link(mat, node, "set_rgba", in, out, link); } -void register_node_type_sh_rgb(void) +} // namespace blender::nodes::node_shader_rgb_cc + +void register_node_type_sh_rgb() { + namespace file_ns = blender::nodes::node_shader_rgb_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_RGB, "RGB", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, sh_node_rgb_out); - node_type_gpu(&ntype, gpu_shader_rgb); + sh_node_type_base(&ntype, SH_NODE_RGB, "RGB", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_rgb); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_rgb_to_bw.cc b/source/blender/nodes/shader/nodes/node_shader_rgb_to_bw.cc new file mode 100644 index 00000000000..13ba056d9ee --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_rgb_to_bw.cc @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup shdnodes + */ + +#include "IMB_colormanagement.h" + +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_rgb_to_bw_cc { + +static void sh_node_rgbtobw_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.5f, 0.5f, 0.5f, 1.0f}); + b.add_output<decl::Float>(N_("Val")); +} + +static int gpu_shader_rgbtobw(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + return GPU_stack_link(mat, node, "rgbtobw", in, out); +} + +} // namespace blender::nodes::node_shader_rgb_to_bw_cc + +void register_node_type_sh_rgbtobw() +{ + namespace file_ns = blender::nodes::node_shader_rgb_to_bw_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::sh_node_rgbtobw_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_rgbtobw); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_script.c b/source/blender/nodes/shader/nodes/node_shader_script.c deleted file mode 100644 index 42ab272de0e..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_script.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup shdnodes - */ - -#include "node_shader_util.h" - -/* **************** Script ******************** */ - -static void init(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeShaderScript *nss = MEM_callocN(sizeof(NodeShaderScript), "shader script node"); - node->storage = nss; -} - -static void node_free_script(bNode *node) -{ - NodeShaderScript *nss = node->storage; - - if (nss) { - if (nss->bytecode) { - MEM_freeN(nss->bytecode); - } - - MEM_freeN(nss); - } -} - -static void node_copy_script(bNodeTree *UNUSED(dest_ntree), - bNode *dest_node, - const bNode *src_node) -{ - NodeShaderScript *src_nss = src_node->storage; - NodeShaderScript *dest_nss = MEM_dupallocN(src_nss); - - if (src_nss->bytecode) { - dest_nss->bytecode = MEM_dupallocN(src_nss->bytecode); - } - - dest_node->storage = dest_nss; -} - -void register_node_type_sh_script(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_SCRIPT, "Script", NODE_CLASS_SCRIPT, 0); - node_type_init(&ntype, init); - node_type_storage(&ntype, "NodeShaderScript", node_free_script, node_copy_script); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_script.cc b/source/blender/nodes/shader/nodes/node_shader_script.cc new file mode 100644 index 00000000000..e6af90fa588 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_script.cc @@ -0,0 +1,112 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup shdnodes + */ + +#include "node_shader_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_script_cc { + +static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *row; + + row = uiLayoutRow(layout, false); + uiItemR(row, ptr, "mode", UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_EXPAND, nullptr, ICON_NONE); + + row = uiLayoutRow(layout, true); + + if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_INTERNAL) { + uiItemR(row, ptr, "script", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + } + else { + uiItemR(row, ptr, "filepath", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + } + + uiItemO(row, "", ICON_FILE_REFRESH, "node.shader_script_update"); +} + +static void node_shader_buts_script_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiItemS(layout); + + node_shader_buts_script(layout, C, ptr); + +#if 0 /* not implemented yet */ + if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL) { + uiItemR(layout, ptr, "use_auto_update", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + } +#endif +} + +static void init(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeShaderScript *nss = MEM_cnew<NodeShaderScript>("shader script node"); + node->storage = nss; +} + +static void node_free_script(bNode *node) +{ + NodeShaderScript *nss = static_cast<NodeShaderScript *>(node->storage); + + if (nss) { + if (nss->bytecode) { + MEM_freeN(nss->bytecode); + } + + MEM_freeN(nss); + } +} + +static void node_copy_script(bNodeTree *UNUSED(dest_ntree), + bNode *dest_node, + const bNode *src_node) +{ + NodeShaderScript *src_nss = static_cast<NodeShaderScript *>(src_node->storage); + NodeShaderScript *dest_nss = static_cast<NodeShaderScript *>(MEM_dupallocN(src_nss)); + + if (src_nss->bytecode) { + dest_nss->bytecode = static_cast<char *>(MEM_dupallocN(src_nss->bytecode)); + } + + dest_node->storage = dest_nss; +} + +} // namespace blender::nodes::node_shader_script_cc + +void register_node_type_sh_script() +{ + namespace file_ns = blender::nodes::node_shader_script_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_SCRIPT, "Script", NODE_CLASS_SCRIPT); + ntype.draw_buttons = file_ns::node_shader_buts_script; + ntype.draw_buttons_ex = file_ns::node_shader_buts_script_ex; + node_type_init(&ntype, file_ns::init); + node_type_storage( + &ntype, "NodeShaderScript", file_ns::node_free_script, file_ns::node_copy_script); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c deleted file mode 100644 index dfecb830b35..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2013 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup shdnodes - */ - -#include "node_shader_util.h" - -/* **************** SEPARATE HSV ******************** */ -static bNodeSocketTemplate sh_node_sephsv_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f}, - {-1, ""}, -}; -static bNodeSocketTemplate sh_node_sephsv_out[] = { - {SOCK_FLOAT, N_("H")}, - {SOCK_FLOAT, N_("S")}, - {SOCK_FLOAT, N_("V")}, - {-1, ""}, -}; - -static void node_shader_exec_sephsv(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - float col[3]; - nodestack_get_vec(col, SOCK_VECTOR, in[0]); - - rgb_to_hsv(col[0], col[1], col[2], &out[0]->vec[0], &out[1]->vec[0], &out[2]->vec[0]); -} - -static int gpu_shader_sephsv(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - return GPU_stack_link(mat, node, "separate_hsv", in, out); -} - -void register_node_type_sh_sephsv(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_SEPHSV, "Separate HSV", NODE_CLASS_CONVERTER, 0); - node_type_socket_templates(&ntype, sh_node_sephsv_in, sh_node_sephsv_out); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_sephsv); - node_type_gpu(&ntype, gpu_shader_sephsv); - - nodeRegisterType(&ntype); -} - -/* **************** COMBINE HSV ******************** */ -static bNodeSocketTemplate sh_node_combhsv_in[] = { - {SOCK_FLOAT, N_("H"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, - {SOCK_FLOAT, N_("S"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, - {SOCK_FLOAT, N_("V"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, - {-1, ""}, -}; -static bNodeSocketTemplate sh_node_combhsv_out[] = { - {SOCK_RGBA, N_("Color")}, - {-1, ""}, -}; - -static void node_shader_exec_combhsv(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - float h, s, v; - nodestack_get_vec(&h, SOCK_FLOAT, in[0]); - nodestack_get_vec(&s, SOCK_FLOAT, in[1]); - nodestack_get_vec(&v, SOCK_FLOAT, in[2]); - - hsv_to_rgb(h, s, v, &out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2]); -} - -static int gpu_shader_combhsv(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - return GPU_stack_link(mat, node, "combine_hsv", in, out); -} - -void register_node_type_sh_combhsv(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_COMBHSV, "Combine HSV", NODE_CLASS_CONVERTER, 0); - node_type_socket_templates(&ntype, sh_node_combhsv_in, sh_node_combhsv_out); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_combhsv); - node_type_gpu(&ntype, gpu_shader_combhsv); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcomb_hsv.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_hsv.cc new file mode 100644 index 00000000000..700e4ce3667 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_hsv.cc @@ -0,0 +1,96 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup shdnodes + */ + +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_sepcomb_hsv_cc { + +/* **************** SEPARATE HSV ******************** */ + +static void node_declare_sephsv(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0}); + b.add_output<decl::Float>(N_("H")); + b.add_output<decl::Float>(N_("S")); + b.add_output<decl::Float>(N_("V")); +} + +static int gpu_shader_sephsv(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + return GPU_stack_link(mat, node, "separate_hsv", in, out); +} + +} // namespace blender::nodes::node_shader_sepcomb_hsv_cc + +void register_node_type_sh_sephsv() +{ + namespace file_ns = blender::nodes::node_shader_sepcomb_hsv_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_SEPHSV, "Separate HSV", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::node_declare_sephsv; + node_type_gpu(&ntype, file_ns::gpu_shader_sephsv); + + nodeRegisterType(&ntype); +} + +namespace blender::nodes::node_shader_sepcomb_hsv_cc { + +/* **************** COMBINE HSV ******************** */ + +static void node_declare_combhsv(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("H")).default_value(0.0f).min(0.0f).max(1.0f).subtype(PROP_UNSIGNED); + b.add_input<decl::Float>(N_("S")).default_value(0.0f).min(0.0f).max(1.0f).subtype(PROP_UNSIGNED); + b.add_input<decl::Float>(N_("V")).default_value(0.0f).min(0.0f).max(1.0f).subtype(PROP_UNSIGNED); + b.add_output<decl::Color>(N_("Color")); +} + +static int gpu_shader_combhsv(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + return GPU_stack_link(mat, node, "combine_hsv", in, out); +} + +} // namespace blender::nodes::node_shader_sepcomb_hsv_cc + +void register_node_type_sh_combhsv() +{ + namespace file_ns = blender::nodes::node_shader_sepcomb_hsv_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_COMBHSV, "Combine HSV", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::node_declare_combhsv; + node_type_gpu(&ntype, file_ns::gpu_shader_combhsv); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc index 24c5dcf7ba3..d4be0bd14dc 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc +++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc @@ -21,34 +21,17 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include "node_shader_util.hh" -namespace blender::nodes { +namespace blender::nodes::node_shader_sepcomb_rgb_cc { static void sh_node_seprgb_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Color>("Image").default_value({0.8f, 0.8f, 0.8f, 1.0f}); - b.add_output<decl::Float>("R"); - b.add_output<decl::Float>("G"); - b.add_output<decl::Float>("B"); -}; - -} // namespace blender::nodes - -static void node_shader_exec_seprgb(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - float col[3]; - nodestack_get_vec(col, SOCK_VECTOR, in[0]); - - out[0]->vec[0] = col[0]; - out[1]->vec[0] = col[1]; - out[2]->vec[0] = col[2]; + b.add_input<decl::Color>(N_("Image")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_output<decl::Float>(N_("R")); + b.add_output<decl::Float>(N_("G")); + b.add_output<decl::Float>(N_("B")); } static int gpu_shader_seprgb(GPUMaterial *mat, @@ -103,47 +86,31 @@ static void sh_node_seprgb_build_multi_function(blender::nodes::NodeMultiFunctio builder.set_matching_fn(fn); } -void register_node_type_sh_seprgb(void) +} // namespace blender::nodes::node_shader_sepcomb_rgb_cc + +void register_node_type_sh_seprgb() { + namespace file_ns = blender::nodes::node_shader_sepcomb_rgb_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTER, 0); - ntype.declare = blender::nodes::sh_node_seprgb_declare; - node_type_exec(&ntype, nullptr, nullptr, node_shader_exec_seprgb); - node_type_gpu(&ntype, gpu_shader_seprgb); - ntype.build_multi_function = sh_node_seprgb_build_multi_function; + sh_fn_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::sh_node_seprgb_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_seprgb); + ntype.build_multi_function = file_ns::sh_node_seprgb_build_multi_function; nodeRegisterType(&ntype); } -namespace blender::nodes { +namespace blender::nodes::node_shader_sepcomb_rgb_cc { static void sh_node_combrgb_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Float>("R").min(0.0f).max(1.0f); - b.add_input<decl::Float>("G").min(0.0f).max(1.0f); - b.add_input<decl::Float>("B").min(0.0f).max(1.0f); - b.add_output<decl::Color>("Image"); -}; - -} // namespace blender::nodes - -static void node_shader_exec_combrgb(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - float r, g, b; - nodestack_get_vec(&r, SOCK_FLOAT, in[0]); - nodestack_get_vec(&g, SOCK_FLOAT, in[1]); - nodestack_get_vec(&b, SOCK_FLOAT, in[2]); - - out[0]->vec[0] = r; - out[0]->vec[1] = g; - out[0]->vec[2] = b; + b.add_input<decl::Float>(N_("R")).min(0.0f).max(1.0f); + b.add_input<decl::Float>(N_("G")).min(0.0f).max(1.0f); + b.add_input<decl::Float>(N_("B")).min(0.0f).max(1.0f); + b.add_output<decl::Color>(N_("Image")); } static int gpu_shader_combrgb(GPUMaterial *mat, @@ -163,15 +130,18 @@ static void sh_node_combrgb_build_multi_function(blender::nodes::NodeMultiFuncti builder.set_matching_fn(fn); } -void register_node_type_sh_combrgb(void) +} // namespace blender::nodes::node_shader_sepcomb_rgb_cc + +void register_node_type_sh_combrgb() { + namespace file_ns = blender::nodes::node_shader_sepcomb_rgb_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTER, 0); - ntype.declare = blender::nodes::sh_node_combrgb_declare; - node_type_exec(&ntype, nullptr, nullptr, node_shader_exec_combrgb); - node_type_gpu(&ntype, gpu_shader_combrgb); - ntype.build_multi_function = sh_node_combrgb_build_multi_function; + sh_fn_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::sh_node_combrgb_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_combrgb); + ntype.build_multi_function = file_ns::sh_node_combrgb_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc index 8ca8fc19521..f8064eb192a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc +++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc @@ -21,20 +21,18 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include "node_shader_util.hh" -namespace blender::nodes { +namespace blender::nodes::node_shader_sepcomb_xyz_cc { static void sh_node_sepxyz_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>("Vector").min(-10000.0f).max(10000.0f); - b.add_output<decl::Float>("X"); - b.add_output<decl::Float>("Y"); - b.add_output<decl::Float>("Z"); -}; - -} // namespace blender::nodes + b.add_input<decl::Vector>(N_("Vector")).min(-10000.0f).max(10000.0f); + b.add_output<decl::Float>(N_("X")); + b.add_output<decl::Float>(N_("Y")); + b.add_output<decl::Float>(N_("Z")); +} static int gpu_shader_sepxyz(GPUMaterial *mat, bNode *node, @@ -88,30 +86,32 @@ static void sh_node_sepxyz_build_multi_function(blender::nodes::NodeMultiFunctio builder.set_matching_fn(separate_fn); } -void register_node_type_sh_sepxyz(void) +} // namespace blender::nodes::node_shader_sepcomb_xyz_cc + +void register_node_type_sh_sepxyz() { + namespace file_ns = blender::nodes::node_shader_sepcomb_xyz_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_SEPXYZ, "Separate XYZ", NODE_CLASS_CONVERTER, 0); - ntype.declare = blender::nodes::sh_node_sepxyz_declare; - node_type_gpu(&ntype, gpu_shader_sepxyz); - ntype.build_multi_function = sh_node_sepxyz_build_multi_function; + sh_fn_node_type_base(&ntype, SH_NODE_SEPXYZ, "Separate XYZ", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::sh_node_sepxyz_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_sepxyz); + ntype.build_multi_function = file_ns::sh_node_sepxyz_build_multi_function; nodeRegisterType(&ntype); } -namespace blender::nodes { +namespace blender::nodes::node_shader_sepcomb_xyz_cc { static void sh_node_combxyz_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Float>("X").min(-10000.0f).max(10000.0f); - b.add_input<decl::Float>("Y").min(-10000.0f).max(10000.0f); - b.add_input<decl::Float>("Z").min(-10000.0f).max(10000.0f); - b.add_output<decl::Vector>("Vector"); -}; - -} // namespace blender::nodes + b.add_input<decl::Float>(N_("X")).min(-10000.0f).max(10000.0f); + b.add_input<decl::Float>(N_("Y")).min(-10000.0f).max(10000.0f); + b.add_input<decl::Float>(N_("Z")).min(-10000.0f).max(10000.0f); + b.add_output<decl::Vector>(N_("Vector")); +} static int gpu_shader_combxyz(GPUMaterial *mat, bNode *node, @@ -129,14 +129,18 @@ static void sh_node_combxyz_build_multi_function(blender::nodes::NodeMultiFuncti builder.set_matching_fn(fn); } -void register_node_type_sh_combxyz(void) +} // namespace blender::nodes::node_shader_sepcomb_xyz_cc + +void register_node_type_sh_combxyz() { + namespace file_ns = blender::nodes::node_shader_sepcomb_xyz_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_COMBXYZ, "Combine XYZ", NODE_CLASS_CONVERTER, 0); - ntype.declare = blender::nodes::sh_node_combxyz_declare; - node_type_gpu(&ntype, gpu_shader_combxyz); - ntype.build_multi_function = sh_node_combxyz_build_multi_function; + sh_fn_node_type_base(&ntype, SH_NODE_COMBXYZ, "Combine XYZ", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::sh_node_combxyz_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_combxyz); + ntype.build_multi_function = file_ns::sh_node_combxyz_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c b/source/blender/nodes/shader/nodes/node_shader_shader_to_rgb.cc index 4e8f47c087a..d601f45b49f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_shader_to_rgb.cc @@ -17,20 +17,16 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_shader_to_rgb_cc { -static bNodeSocketTemplate sh_node_shadertorgb_in[] = { - {SOCK_SHADER, N_("Shader")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_shadertorgb_out[] = { - {SOCK_RGBA, N_("Color")}, - {SOCK_FLOAT, N_("Alpha")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Shader>(N_("Shader")); + b.add_output<decl::Color>(N_("Color")); + b.add_output<decl::Float>(N_("Alpha")); +} static int node_shader_gpu_shadertorgb(GPUMaterial *mat, bNode *node, @@ -43,16 +39,18 @@ static int node_shader_gpu_shadertorgb(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_shader_to_rgba", in, out); } +} // namespace blender::nodes::node_shader_shader_to_rgb_cc + /* node type definition */ -void register_node_type_sh_shadertorgb(void) +void register_node_type_sh_shadertorgb() { + namespace file_ns = blender::nodes::node_shader_shader_to_rgb_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_SHADERTORGB, "Shader to RGB", NODE_CLASS_CONVERTER, 0); - node_type_socket_templates(&ntype, sh_node_shadertorgb_in, sh_node_shadertorgb_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_shadertorgb); + sh_node_type_base(&ntype, SH_NODE_SHADERTORGB, "Shader to RGB", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_shadertorgb); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_squeeze.c b/source/blender/nodes/shader/nodes/node_shader_squeeze.c deleted file mode 100644 index ca7bdf41df9..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_squeeze.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup shdnodes - */ - -#include "node_shader_util.h" - -/* **************** VALUE SQUEEZE ******************** */ -static bNodeSocketTemplate sh_node_squeeze_in[] = { - {SOCK_FLOAT, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, - {SOCK_FLOAT, N_("Width"), 1.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, - {SOCK_FLOAT, N_("Center"), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, - {-1, ""}}; - -static bNodeSocketTemplate sh_node_squeeze_out[] = {{SOCK_FLOAT, N_("Value")}, {-1, ""}}; - -static void node_shader_exec_squeeze(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - float vec[3]; - - nodestack_get_vec(vec, SOCK_FLOAT, in[0]); - nodestack_get_vec(vec + 1, SOCK_FLOAT, in[1]); - nodestack_get_vec(vec + 2, SOCK_FLOAT, in[2]); - - out[0]->vec[0] = 1.0f / (1.0f + powf(M_E, -((vec[0] - vec[2]) * vec[1]))); -} - -static int gpu_shader_squeeze(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - return GPU_stack_link(mat, node, "squeeze", in, out); -} - -void register_node_type_sh_squeeze(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_SQUEEZE, "Squeeze Value", NODE_CLASS_CONVERTER, 0); - node_type_socket_templates(&ntype, sh_node_squeeze_in, sh_node_squeeze_out); - node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_squeeze); - node_type_gpu(&ntype, gpu_shader_squeeze); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_squeeze.cc b/source/blender/nodes/shader/nodes/node_shader_squeeze.cc new file mode 100644 index 00000000000..83965160019 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_squeeze.cc @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup shdnodes + */ + +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_squeeze_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Value")).default_value(0.0f).min(-100.0f).max(100.0f); + b.add_input<decl::Float>(N_("Width")).default_value(1.0f).min(-100.0f).max(100.0f); + b.add_input<decl::Float>(N_("Center")).default_value(0.0f).min(-100.0f).max(100.0f); + b.add_output<decl::Float>(N_("Value")); +} + +static int gpu_shader_squeeze(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + return GPU_stack_link(mat, node, "squeeze", in, out); +} + +} // namespace blender::nodes::node_shader_squeeze_cc + +void register_node_type_sh_squeeze() +{ + namespace file_ns = blender::nodes::node_shader_squeeze_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_SQUEEZE, "Squeeze Value", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_squeeze); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c deleted file mode 100644 index 159e986e19e..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_subsurface_scattering_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Scale"), 1.0, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_VECTOR, N_("Radius"), 1.0f, 0.2f, 0.1f, 0.0f, 0.0f, 100.0f, PROP_NONE, SOCK_COMPACT}, - {SOCK_FLOAT, N_("IOR"), 1.4f, 0.0f, 0.0f, 0.0f, 1.01f, 3.8f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Anisotropy"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_subsurface_scattering_out[] = { - {SOCK_SHADER, N_("BSSRDF")}, - {-1, ""}, -}; - -static void node_shader_init_subsurface_scattering(bNodeTree *UNUSED(ntree), bNode *node) -{ - node->custom1 = SHD_SUBSURFACE_RANDOM_WALK; - node->custom2 = true; -} - -static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - if (!in[5].link) { - GPU_link(mat, "world_normals_get", &in[5].link); - } - - GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_SUBSURFACE); - GPU_stack_link(mat, node, "node_subsurface_scattering", in, out); - return GPU_stack_eval_link(mat, node, "node_subsurface_scattering_eval", in, out); -} - -/* node type definition */ -void register_node_type_sh_subsurface_scattering(void) -{ - static bNodeType ntype; - - sh_node_type_base( - &ntype, SH_NODE_SUBSURFACE_SCATTERING, "Subsurface Scattering", NODE_CLASS_SHADER, 0); - node_type_socket_templates( - &ntype, sh_node_subsurface_scattering_in, sh_node_subsurface_scattering_out); - node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, node_shader_init_subsurface_scattering); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_subsurface_scattering); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc new file mode 100644 index 00000000000..f60db81b4a9 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc @@ -0,0 +1,113 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_subsurface_scattering_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Float>(N_("Scale")).default_value(1.0f).min(0.0f).max(1000.0f); + b.add_input<decl::Vector>(N_("Radius")) + .default_value({1.0f, 0.2f, 0.1f}) + .min(0.0f) + .max(100.0f) + .compact(); + b.add_input<decl::Float>(N_("IOR")).default_value(1.4f).min(1.01f).max(3.8f).subtype( + PROP_FACTOR); + b.add_input<decl::Float>(N_("Anisotropy")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_output<decl::Shader>(N_("BSSRDF")); +} + +static void node_shader_buts_subsurface(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "falloff", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} + +static void node_shader_init_subsurface_scattering(bNodeTree *UNUSED(ntree), bNode *node) +{ + node->custom1 = SHD_SUBSURFACE_RANDOM_WALK; + node->custom2 = true; +} + +static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + if (!in[5].link) { + GPU_link(mat, "world_normals_get", &in[5].link); + } + + if (node->sss_id > 0) { + bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->original->inputs, 2); + bNodeSocketValueRGBA *socket_data = (bNodeSocketValueRGBA *)socket->default_value; + /* For some reason it seems that the socket value is in ARGB format. */ + GPU_material_sss_profile_create(mat, &socket_data->value[1]); + + /* sss_id is 0 only the node is not connected to any output. + * In this case flagging the material would trigger a bug (see T68736). */ + GPU_material_flag_set(mat, (eGPUMatFlag)(GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_SSS)); + } + + return GPU_stack_link( + mat, node, "node_subsurface_scattering", in, out, GPU_constant(&node->sss_id)); +} + +static void node_shader_update_subsurface_scattering(bNodeTree *ntree, bNode *node) +{ + const int sss_method = node->custom1; + + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + if (STR_ELEM(sock->name, "IOR", "Anisotropy")) { + nodeSetSocketAvailability(ntree, sock, sss_method != SHD_SUBSURFACE_BURLEY); + } + } +} + +} // namespace blender::nodes::node_shader_subsurface_scattering_cc + +/* node type definition */ +void register_node_type_sh_subsurface_scattering() +{ + namespace file_ns = blender::nodes::node_shader_subsurface_scattering_cc; + + static bNodeType ntype; + + sh_node_type_base( + &ntype, SH_NODE_SUBSURFACE_SCATTERING, "Subsurface Scattering", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_subsurface; + node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); + node_type_init(&ntype, file_ns::node_shader_init_subsurface_scattering); + node_type_gpu(&ntype, file_ns::node_shader_gpu_subsurface_scattering); + node_type_update(&ntype, file_ns::node_shader_update_subsurface_scattering); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.cc index 7ec332bd34a..58625cacf9c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tangent.c +++ b/source/blender/nodes/shader/nodes/node_shader_tangent.cc @@ -17,18 +17,49 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +#include "BKE_context.h" -static bNodeSocketTemplate sh_node_tangent_out[] = { - {SOCK_VECTOR, N_("Tangent"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_tangent_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Vector>(N_("Tangent")); +} + +static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiLayout *split, *row; + + split = uiLayoutSplit(layout, 0.0f, false); + + uiItemR(split, ptr, "direction_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", 0); + + row = uiLayoutRow(split, false); + + if (RNA_enum_get(ptr, "direction_type") == SHD_TANGENT_UVMAP) { + PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); + + if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { + PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); + uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); + } + else { + uiItemR(row, ptr, "uv_map", UI_ITEM_R_SPLIT_EMPTY_NAME, "", 0); + } + } + else { + uiItemR(row, ptr, "axis", UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_EXPAND, nullptr, 0); + } +} static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node) { - NodeShaderTangent *attr = MEM_callocN(sizeof(NodeShaderTangent), "NodeShaderTangent"); + NodeShaderTangent *attr = MEM_cnew<NodeShaderTangent>("NodeShaderTangent"); attr->axis = SHD_TANGENT_AXIS_Z; node->storage = attr; } @@ -39,7 +70,7 @@ static int node_shader_gpu_tangent(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - NodeShaderTangent *attr = node->storage; + NodeShaderTangent *attr = static_cast<NodeShaderTangent *>(node->storage); if (attr->direction_type == SHD_TANGENT_UVMAP) { return GPU_stack_link( @@ -61,16 +92,21 @@ static int node_shader_gpu_tangent(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_tangent", in, out, orco); } +} // namespace blender::nodes::node_shader_tangent_cc + /* node type definition */ -void register_node_type_sh_tangent(void) +void register_node_type_sh_tangent() { + namespace file_ns = blender::nodes::node_shader_tangent_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TANGENT, "Tangent", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, sh_node_tangent_out); + sh_node_type_base(&ntype, SH_NODE_TANGENT, "Tangent", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_tangent; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, node_shader_init_tangent); - node_type_gpu(&ntype, node_shader_gpu_tangent); + node_type_init(&ntype, file_ns::node_shader_init_tangent); + node_type_gpu(&ntype, file_ns::node_shader_gpu_tangent); node_type_storage( &ntype, "NodeShaderTangent", node_free_standard_storage, node_copy_standard_storage); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c deleted file mode 100644 index 1b802f1dfd7..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_tex_brick_in[] = { - {SOCK_VECTOR, - N_("Vector"), - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - PROP_NONE, - SOCK_HIDE_VALUE | SOCK_NO_INTERNAL_LINK}, - {SOCK_RGBA, N_("Color1"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_RGBA, N_("Color2"), 0.2f, 0.2f, 0.2f, 1.0f, 0.0f, 1.0f}, - {SOCK_RGBA, - N_("Mortar"), - 0.0f, - 0.0f, - 0.0f, - 1.0f, - 0.0f, - 1.0f, - PROP_NONE, - SOCK_NO_INTERNAL_LINK}, - {SOCK_FLOAT, - N_("Scale"), - 5.0f, - 0.0f, - 0.0f, - 0.0f, - -1000.0f, - 1000.0f, - PROP_NONE, - SOCK_NO_INTERNAL_LINK}, - {SOCK_FLOAT, - N_("Mortar Size"), - 0.02f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.125f, - PROP_NONE, - SOCK_NO_INTERNAL_LINK}, - {SOCK_FLOAT, - N_("Mortar Smooth"), - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - PROP_NONE, - SOCK_NO_INTERNAL_LINK}, - {SOCK_FLOAT, - N_("Bias"), - 0.0f, - 0.0f, - 0.0f, - 0.0f, - -1.0f, - 1.0f, - PROP_NONE, - SOCK_NO_INTERNAL_LINK}, - {SOCK_FLOAT, - N_("Brick Width"), - 0.5f, - 0.0f, - 0.0f, - 0.0f, - 0.01f, - 100.0f, - PROP_NONE, - SOCK_NO_INTERNAL_LINK}, - {SOCK_FLOAT, - N_("Row Height"), - 0.25f, - 0.0f, - 0.0f, - 0.0f, - 0.01f, - 100.0f, - PROP_NONE, - SOCK_NO_INTERNAL_LINK}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_tex_brick_out[] = { - {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, - N_("Fac"), - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - PROP_FACTOR, - SOCK_NO_INTERNAL_LINK}, - {-1, ""}, -}; - -static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeTexBrick *tex = MEM_callocN(sizeof(NodeTexBrick), "NodeTexBrick"); - BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - BKE_texture_colormapping_default(&tex->base.color_mapping); - - tex->offset = 0.5f; - tex->squash = 1.0f; - tex->offset_freq = 2; - tex->squash_freq = 2; - - node->storage = tex; - - LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - if (STREQ(sock->name, "Mortar Smooth")) { - ((bNodeSocketValueFloat *)sock->default_value)->value = 0.1f; - } - } -} - -static int node_shader_gpu_tex_brick(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - node_shader_gpu_default_tex_coord(mat, node, &in[0].link); - node_shader_gpu_tex_mapping(mat, node, in, out); - NodeTexBrick *tex = (NodeTexBrick *)node->storage; - float offset_freq = tex->offset_freq; - float squash_freq = tex->squash_freq; - return GPU_stack_link(mat, - node, - "node_tex_brick", - in, - out, - GPU_uniform(&tex->offset), - GPU_constant(&offset_freq), - GPU_uniform(&tex->squash), - GPU_constant(&squash_freq)); -} - -/* node type definition */ -void register_node_type_sh_tex_brick(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_TEX_BRICK, "Brick Texture", NODE_CLASS_TEXTURE, 0); - node_type_socket_templates(&ntype, sh_node_tex_brick_in, sh_node_tex_brick_out); - node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, node_shader_init_tex_brick); - node_type_storage( - &ntype, "NodeTexBrick", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_tex_brick); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc b/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc new file mode 100644 index 00000000000..81a69ef18da --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc @@ -0,0 +1,306 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +#include "BLI_math_vec_types.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_tex_brick_cc { + +static void sh_node_tex_brick_declare(NodeDeclarationBuilder &b) +{ + b.is_function_node(); + b.add_input<decl::Vector>(N_("Vector")).min(-10000.0f).max(10000.0f).implicit_field(); + b.add_input<decl::Color>(N_("Color1")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Color>(N_("Color2")).default_value({0.2f, 0.2f, 0.2f, 1.0f}); + b.add_input<decl::Color>(N_("Mortar")).default_value({0.0f, 0.0f, 0.0f, 1.0f}).no_muted_links(); + b.add_input<decl::Float>(N_("Scale")) + .min(-1000.0f) + .max(1000.0f) + .default_value(5.0f) + .no_muted_links(); + b.add_input<decl::Float>(N_("Mortar Size")) + .min(0.0f) + .max(0.125f) + .default_value(0.02f) + .no_muted_links(); + b.add_input<decl::Float>(N_("Mortar Smooth")).min(0.0f).max(1.0f).no_muted_links(); + b.add_input<decl::Float>(N_("Bias")).min(-1.0f).max(1.0f).no_muted_links(); + b.add_input<decl::Float>(N_("Brick Width")) + .min(0.01f) + .max(100.0f) + .default_value(0.5f) + .no_muted_links(); + b.add_input<decl::Float>(N_("Row Height")) + .min(0.01f) + .max(100.0f) + .default_value(0.25f) + .no_muted_links(); + b.add_output<decl::Color>(N_("Color")); + b.add_output<decl::Float>(N_("Fac")); +} + +static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *col; + + col = uiLayoutColumn(layout, true); + uiItemR(col, + ptr, + "offset", + UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_SLIDER, + IFACE_("Offset"), + ICON_NONE); + uiItemR( + col, ptr, "offset_frequency", UI_ITEM_R_SPLIT_EMPTY_NAME, IFACE_("Frequency"), ICON_NONE); + + col = uiLayoutColumn(layout, true); + uiItemR(col, ptr, "squash", UI_ITEM_R_SPLIT_EMPTY_NAME, IFACE_("Squash"), ICON_NONE); + uiItemR( + col, ptr, "squash_frequency", UI_ITEM_R_SPLIT_EMPTY_NAME, IFACE_("Frequency"), ICON_NONE); +} + +static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeTexBrick *tex = MEM_cnew<NodeTexBrick>(__func__); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); + + tex->offset = 0.5f; + tex->squash = 1.0f; + tex->offset_freq = 2; + tex->squash_freq = 2; + + node->storage = tex; + + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + if (STREQ(sock->name, "Mortar Smooth")) { + ((bNodeSocketValueFloat *)sock->default_value)->value = 0.1f; + } + } +} + +static int node_shader_gpu_tex_brick(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + node_shader_gpu_default_tex_coord(mat, node, &in[0].link); + node_shader_gpu_tex_mapping(mat, node, in, out); + NodeTexBrick *tex = (NodeTexBrick *)node->storage; + float offset_freq = tex->offset_freq; + float squash_freq = tex->squash_freq; + return GPU_stack_link(mat, + node, + "node_tex_brick", + in, + out, + GPU_uniform(&tex->offset), + GPU_constant(&offset_freq), + GPU_uniform(&tex->squash), + GPU_constant(&squash_freq)); +} + +class BrickFunction : public fn::MultiFunction { + private: + const float offset_; + const int offset_freq_; + const float squash_; + const int squash_freq_; + + public: + BrickFunction(const float offset, + const int offset_freq, + const float squash, + const int squash_freq) + : offset_(offset), offset_freq_(offset_freq), squash_(squash), squash_freq_(squash_freq) + { + static fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static fn::MFSignature create_signature() + { + fn::MFSignatureBuilder signature{"BrickTexture"}; + signature.single_input<float3>("Vector"); + signature.single_input<ColorGeometry4f>("Color1"); + signature.single_input<ColorGeometry4f>("Color2"); + signature.single_input<ColorGeometry4f>("Mortar"); + signature.single_input<float>("Scale"); + signature.single_input<float>("Mortar Size"); + signature.single_input<float>("Mortar Smooth"); + signature.single_input<float>("Bias"); + signature.single_input<float>("Brick Width"); + signature.single_input<float>("Row Height"); + signature.single_output<ColorGeometry4f>("Color"); + signature.single_output<float>("Fac"); + return signature.build(); + } + + /* Fast integer noise. */ + static float brick_noise(uint n) + { + n = (n + 1013) & 0x7fffffff; + n = (n >> 13) ^ n; + const uint nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; + return 0.5f * ((float)nn / 1073741824.0f); + } + + static float smoothstepf(const float f) + { + const float ff = f * f; + return (3.0f * ff - 2.0f * ff * f); + } + + static float2 brick(float3 p, + float mortar_size, + float mortar_smooth, + float bias, + float brick_width, + float row_height, + float offset_amount, + int offset_frequency, + float squash_amount, + int squash_frequency) + { + float offset = 0.0f; + + const int rownum = (int)floorf(p.y / row_height); + + if (offset_frequency && squash_frequency) { + brick_width *= (rownum % squash_frequency) ? 1.0f : squash_amount; + offset = (rownum % offset_frequency) ? 0.0f : (brick_width * offset_amount); + } + + const int bricknum = (int)floorf((p.x + offset) / brick_width); + + const float x = (p.x + offset) - brick_width * bricknum; + const float y = p.y - row_height * rownum; + + const float tint = clamp_f( + brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias, 0.0f, 1.0f); + float min_dist = std::min(std::min(x, y), std::min(brick_width - x, row_height - y)); + + float mortar; + if (min_dist >= mortar_size) { + mortar = 0.0f; + } + else if (mortar_smooth == 0.0f) { + mortar = 1.0f; + } + else { + min_dist = 1.0f - min_dist / mortar_size; + mortar = (min_dist < mortar_smooth) ? smoothstepf(min_dist / mortar_smooth) : 1.0f; + } + + return float2(tint, mortar); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); + const VArray<ColorGeometry4f> &color1_values = params.readonly_single_input<ColorGeometry4f>( + 1, "Color1"); + const VArray<ColorGeometry4f> &color2_values = params.readonly_single_input<ColorGeometry4f>( + 2, "Color2"); + const VArray<ColorGeometry4f> &mortar_values = params.readonly_single_input<ColorGeometry4f>( + 3, "Mortar"); + const VArray<float> &scale = params.readonly_single_input<float>(4, "Scale"); + const VArray<float> &mortar_size = params.readonly_single_input<float>(5, "Mortar Size"); + const VArray<float> &mortar_smooth = params.readonly_single_input<float>(6, "Mortar Smooth"); + const VArray<float> &bias = params.readonly_single_input<float>(7, "Bias"); + const VArray<float> &brick_width = params.readonly_single_input<float>(8, "Brick Width"); + const VArray<float> &row_height = params.readonly_single_input<float>(9, "Row Height"); + + MutableSpan<ColorGeometry4f> r_color = + params.uninitialized_single_output_if_required<ColorGeometry4f>(10, "Color"); + MutableSpan<float> r_fac = params.uninitialized_single_output_if_required<float>(11, "Fac"); + + const bool store_fac = !r_fac.is_empty(); + const bool store_color = !r_color.is_empty(); + + for (int64_t i : mask) { + const float2 f2 = brick(vector[i] * scale[i], + mortar_size[i], + mortar_smooth[i], + bias[i], + brick_width[i], + row_height[i], + offset_, + offset_freq_, + squash_, + squash_freq_); + + float4 color_data, color1, color2, mortar; + copy_v4_v4(color_data, color1_values[i]); + copy_v4_v4(color1, color1_values[i]); + copy_v4_v4(color2, color2_values[i]); + copy_v4_v4(mortar, mortar_values[i]); + const float tint = f2.x; + const float f = f2.y; + + if (f != 1.0f) { + const float facm = 1.0f - tint; + color_data = color1 * facm + color2 * tint; + } + + if (store_color) { + color_data = color_data * (1.0f - f) + mortar * f; + copy_v4_v4(r_color[i], color_data); + } + if (store_fac) { + r_fac[i] = f; + } + } + } +}; + +static void sh_node_brick_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &builder) +{ + bNode &node = builder.node(); + NodeTexBrick *tex = (NodeTexBrick *)node.storage; + + builder.construct_and_set_matching_fn<BrickFunction>( + tex->offset, tex->offset_freq, tex->squash, tex->squash_freq); +} + +} // namespace blender::nodes::node_shader_tex_brick_cc + +void register_node_type_sh_tex_brick() +{ + namespace file_ns = blender::nodes::node_shader_tex_brick_cc; + + static bNodeType ntype; + + sh_fn_node_type_base(&ntype, SH_NODE_TEX_BRICK, "Brick Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::sh_node_tex_brick_declare; + ntype.draw_buttons = file_ns::node_shader_buts_tex_brick; + node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); + node_type_init(&ntype, file_ns::node_shader_init_tex_brick); + node_type_storage( + &ntype, "NodeTexBrick", node_free_standard_storage, node_copy_standard_storage); + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_brick); + ntype.build_multi_function = file_ns::sh_node_brick_build_multi_function; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c deleted file mode 100644 index 75219f4c3f9..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_tex_checker_in[] = { - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_RGBA, N_("Color1"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_RGBA, N_("Color2"), 0.2f, 0.2f, 0.2f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, - N_("Scale"), - 5.0f, - 0.0f, - 0.0f, - 0.0f, - -1000.0f, - 1000.0f, - PROP_NONE, - SOCK_NO_INTERNAL_LINK}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_tex_checker_out[] = { - {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, - N_("Fac"), - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - PROP_FACTOR, - SOCK_NO_INTERNAL_LINK}, - {-1, ""}, -}; - -static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeTexChecker *tex = MEM_callocN(sizeof(NodeTexChecker), "NodeTexChecker"); - BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - BKE_texture_colormapping_default(&tex->base.color_mapping); - - node->storage = tex; -} - -static int node_shader_gpu_tex_checker(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - node_shader_gpu_default_tex_coord(mat, node, &in[0].link); - node_shader_gpu_tex_mapping(mat, node, in, out); - - return GPU_stack_link(mat, node, "node_tex_checker", in, out); -} - -/* node type definition */ -void register_node_type_sh_tex_checker(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_TEX_CHECKER, "Checker Texture", NODE_CLASS_TEXTURE, 0); - node_type_socket_templates(&ntype, sh_node_tex_checker_in, sh_node_tex_checker_out); - node_type_init(&ntype, node_shader_init_tex_checker); - node_type_storage( - &ntype, "NodeTexChecker", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_tex_checker); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc b/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc new file mode 100644 index 00000000000..6022f13821a --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc @@ -0,0 +1,137 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_tex_checker_cc { + +static void sh_node_tex_checker_declare(NodeDeclarationBuilder &b) +{ + b.is_function_node(); + b.add_input<decl::Vector>(N_("Vector")).min(-10000.0f).max(10000.0f).implicit_field(); + b.add_input<decl::Color>(N_("Color1")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Color>(N_("Color2")).default_value({0.2f, 0.2f, 0.2f, 1.0f}); + b.add_input<decl::Float>(N_("Scale")) + .min(-10000.0f) + .max(10000.0f) + .default_value(5.0f) + .no_muted_links(); + b.add_output<decl::Color>(N_("Color")); + b.add_output<decl::Float>(N_("Fac")); +} + +static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeTexChecker *tex = MEM_cnew<NodeTexChecker>(__func__); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); + + node->storage = tex; +} + +static int node_shader_gpu_tex_checker(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + node_shader_gpu_default_tex_coord(mat, node, &in[0].link); + node_shader_gpu_tex_mapping(mat, node, in, out); + + return GPU_stack_link(mat, node, "node_tex_checker", in, out); +} + +class NodeTexChecker : public fn::MultiFunction { + public: + NodeTexChecker() + { + static fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static fn::MFSignature create_signature() + { + fn::MFSignatureBuilder signature{"Checker"}; + signature.single_input<float3>("Vector"); + signature.single_input<ColorGeometry4f>("Color1"); + signature.single_input<ColorGeometry4f>("Color2"); + signature.single_input<float>("Scale"); + signature.single_output<ColorGeometry4f>("Color"); + signature.single_output<float>("Fac"); + return signature.build(); + } + + void call(blender::IndexMask mask, + fn::MFParams params, + fn::MFContext UNUSED(context)) const override + { + const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); + const VArray<ColorGeometry4f> &color1 = params.readonly_single_input<ColorGeometry4f>( + 1, "Color1"); + const VArray<ColorGeometry4f> &color2 = params.readonly_single_input<ColorGeometry4f>( + 2, "Color2"); + const VArray<float> &scale = params.readonly_single_input<float>(3, "Scale"); + MutableSpan<ColorGeometry4f> r_color = + params.uninitialized_single_output_if_required<ColorGeometry4f>(4, "Color"); + MutableSpan<float> r_fac = params.uninitialized_single_output<float>(5, "Fac"); + + for (int64_t i : mask) { + /* Avoid precision issues on unit coordinates. */ + const float3 p = (vector[i] * scale[i] + 0.000001f) * 0.999999f; + + const int xi = abs((int)(floorf(p.x))); + const int yi = abs((int)(floorf(p.y))); + const int zi = abs((int)(floorf(p.z))); + + r_fac[i] = ((xi % 2 == yi % 2) == (zi % 2)) ? 1.0f : 0.0f; + } + + if (!r_color.is_empty()) { + for (int64_t i : mask) { + r_color[i] = (r_fac[i] == 1.0f) ? color1[i] : color2[i]; + } + } + } +}; + +static void sh_node_tex_checker_build_multi_function( + blender::nodes::NodeMultiFunctionBuilder &builder) +{ + static NodeTexChecker fn; + builder.set_matching_fn(fn); +} + +} // namespace blender::nodes::node_shader_tex_checker_cc + +void register_node_type_sh_tex_checker() +{ + namespace file_ns = blender::nodes::node_shader_tex_checker_cc; + + static bNodeType ntype; + + sh_fn_node_type_base(&ntype, SH_NODE_TEX_CHECKER, "Checker Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::sh_node_tex_checker_declare; + node_type_init(&ntype, file_ns::node_shader_init_tex_checker); + node_type_storage( + &ntype, "NodeTexChecker", node_free_standard_storage, node_copy_standard_storage); + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_checker); + ntype.build_multi_function = file_ns::sh_node_tex_checker_build_multi_function; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc index 76966e0bbee..1bbaed88ea5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc @@ -17,22 +17,31 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" #include "DNA_customdata_types.h" -/* **************** OUTPUT ******************** */ +#include "UI_interface.h" +#include "UI_resources.h" -static bNodeSocketTemplate sh_node_tex_coord_out[] = { - {SOCK_VECTOR, N_("Generated"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("UV"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Object"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Camera"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Window"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Reflection"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_tex_coord_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Vector>(N_("Generated")); + b.add_output<decl::Vector>(N_("Normal")); + b.add_output<decl::Vector>(N_("UV")); + b.add_output<decl::Vector>(N_("Object")); + b.add_output<decl::Vector>(N_("Camera")); + b.add_output<decl::Vector>(N_("Window")); + b.add_output<decl::Vector>(N_("Reflection")); +} + +static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "object", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, 0); + uiItemR(layout, ptr, "from_instancer", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, 0); +} static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *node, @@ -42,25 +51,27 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, { Object *ob = (Object *)node->id; - /* Use special matrix to let the shader branch to using the render object's matrix. */ - float dummy_matrix[4][4]; - dummy_matrix[3][3] = 0.0f; - GPUNodeLink *inv_obmat = (ob != NULL) ? GPU_uniform(&ob->imat[0][0]) : - GPU_uniform(&dummy_matrix[0][0]); + GPUNodeLink *inv_obmat = (ob != nullptr) ? GPU_uniform(&ob->imat[0][0]) : + GPU_builtin(GPU_INVERSE_OBJECT_MATRIX); /* Opti: don't request orco if not needed. */ - GPUNodeLink *orco = (!out[0].hasoutput) ? GPU_constant((float[4]){0.0f, 0.0f, 0.0f, 0.0f}) : + const float default_coords[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPUNodeLink *orco = (!out[0].hasoutput) ? GPU_constant(default_coords) : GPU_attribute(mat, CD_ORCO, ""); GPUNodeLink *mtface = GPU_attribute(mat, CD_MTFACE, ""); + GPUNodeLink *viewpos = GPU_builtin(GPU_VIEW_POSITION); + GPUNodeLink *worldnor = GPU_builtin(GPU_WORLD_NORMAL); + GPUNodeLink *texcofacs = GPU_builtin(GPU_CAMERA_TEXCO_FACTORS); if (out[0].hasoutput) { GPU_link(mat, "generated_from_orco", orco, &orco); } - GPU_stack_link(mat, node, "node_tex_coord", in, out, inv_obmat, orco, mtface); + GPU_stack_link( + mat, node, "node_tex_coord", in, out, viewpos, worldnor, inv_obmat, texcofacs, orco, mtface); - /* for each output. */ - for (int i = 0; sh_node_tex_coord_out[i].type != -1; i++) { + int i; + LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->outputs, i) { node_shader_gpu_bump_tex_coord(mat, node, &out[i].link); /* Normalize some vectors after dFdx/dFdy offsets. * This is the case for interpolated, non linear functions. @@ -74,23 +85,26 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, out[i].link, out[i].link, &out[i].link, - NULL); + nullptr); } } return 1; } +} // namespace blender::nodes::node_shader_tex_coord_cc + /* node type definition */ -void register_node_type_sh_tex_coord(void) +void register_node_type_sh_tex_coord() { + namespace file_ns = blender::nodes::node_shader_tex_coord_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_COORD, "Texture Coordinate", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, sh_node_tex_coord_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_tex_coord); + sh_node_type_base(&ntype, SH_NODE_TEX_COORD, "Texture Coordinate", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_tex_coord; + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_coord); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.cc index 51ced8c2842..24ecdee12d8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.cc @@ -17,23 +17,19 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_tex_environment_cc { -static bNodeSocketTemplate sh_node_tex_environment_in[] = { - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_tex_environment_out[] = { - {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Vector>(N_("Vector")).hide_value(); + b.add_output<decl::Color>(N_("Color")).no_muted_links(); +} static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node) { - NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment"); + NodeTexEnvironment *tex = MEM_cnew<NodeTexEnvironment>("NodeTexEnvironment"); BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); BKE_texture_colormapping_default(&tex->base.color_mapping); tex->projection = SHD_PROJ_EQUIRECTANGULAR; @@ -49,12 +45,12 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, GPUNodeStack *out) { Image *ima = (Image *)node->id; - NodeTexEnvironment *tex = node->storage; + NodeTexEnvironment *tex = (NodeTexEnvironment *)node->storage; /* We get the image user from the original node, since GPU image keeps * a pointer to it and the dependency refreshes the original. */ bNode *node_original = node->original ? node->original : node; - NodeTexImage *tex_original = node_original->storage; + NodeTexImage *tex_original = (NodeTexImage *)node_original->storage; ImageUser *iuser = &tex_original->iuser; eGPUSamplerState sampler = GPU_SAMPLER_REPEAT | GPU_SAMPLER_ANISO | GPU_SAMPLER_FILTER; /* TODO(fclem): For now assume mipmap is always enabled. */ @@ -130,18 +126,22 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, return true; } +} // namespace blender::nodes::node_shader_tex_environment_cc + /* node type definition */ -void register_node_type_sh_tex_environment(void) +void register_node_type_sh_tex_environment() { + namespace file_ns = blender::nodes::node_shader_tex_environment_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_ENVIRONMENT, "Environment Texture", NODE_CLASS_TEXTURE, 0); - node_type_socket_templates(&ntype, sh_node_tex_environment_in, sh_node_tex_environment_out); - node_type_init(&ntype, node_shader_init_tex_environment); + sh_node_type_base(&ntype, SH_NODE_TEX_ENVIRONMENT, "Environment Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::node_declare; + node_type_init(&ntype, file_ns::node_shader_init_tex_environment); node_type_storage( &ntype, "NodeTexEnvironment", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_tex_environment); - node_type_label(&ntype, node_image_label); + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_environment); + ntype.labelfunc = node_image_label; node_type_size_preset(&ntype, NODE_SIZE_LARGE); nodeRegisterType(&ntype); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc index e0520ee49d3..53be5bc09d9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc @@ -17,23 +17,29 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -namespace blender::nodes { +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_tex_gradient_cc { static void sh_node_tex_gradient_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Vector>("Vector").hide_value(); - b.add_output<decl::Color>("Color").no_muted_links(); - b.add_output<decl::Float>("Fac").no_muted_links(); -}; + b.is_function_node(); + b.add_input<decl::Vector>(N_("Vector")).hide_value().implicit_field(); + b.add_output<decl::Color>(N_("Color")).no_muted_links(); + b.add_output<decl::Float>(N_("Fac")).no_muted_links(); +} -} // namespace blender::nodes +static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "gradient_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node) { - NodeTexGradient *tex = (NodeTexGradient *)MEM_callocN(sizeof(NodeTexGradient), - "NodeTexGradient"); + NodeTexGradient *tex = MEM_cnew<NodeTexGradient>(__func__); BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); BKE_texture_colormapping_default(&tex->base.color_mapping); tex->gradient_type = SHD_BLEND_LINEAR; @@ -55,17 +61,122 @@ static int node_shader_gpu_tex_gradient(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_tex_gradient", in, out, GPU_constant(&gradient_type)); } -/* node type definition */ -void register_node_type_sh_tex_gradient(void) +class GradientFunction : public fn::MultiFunction { + private: + int gradient_type_; + + public: + GradientFunction(int gradient_type) : gradient_type_(gradient_type) + { + static fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static fn::MFSignature create_signature() + { + fn::MFSignatureBuilder signature{"GradientFunction"}; + signature.single_input<float3>("Vector"); + signature.single_output<ColorGeometry4f>("Color"); + signature.single_output<float>("Fac"); + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); + + MutableSpan<ColorGeometry4f> r_color = + params.uninitialized_single_output_if_required<ColorGeometry4f>(1, "Color"); + MutableSpan<float> fac = params.uninitialized_single_output<float>(2, "Fac"); + + const bool compute_color = !r_color.is_empty(); + + switch (gradient_type_) { + case SHD_BLEND_LINEAR: { + for (int64_t i : mask) { + fac[i] = vector[i].x; + } + break; + } + case SHD_BLEND_QUADRATIC: { + for (int64_t i : mask) { + const float r = std::max(vector[i].x, 0.0f); + fac[i] = r * r; + } + break; + } + case SHD_BLEND_EASING: { + for (int64_t i : mask) { + const float r = std::min(std::max(vector[i].x, 0.0f), 1.0f); + const float t = r * r; + fac[i] = (3.0f * t - 2.0f * t * r); + } + break; + } + case SHD_BLEND_DIAGONAL: { + for (int64_t i : mask) { + fac[i] = (vector[i].x + vector[i].y) * 0.5f; + } + break; + } + case SHD_BLEND_RADIAL: { + for (int64_t i : mask) { + fac[i] = atan2f(vector[i].y, vector[i].x) / (M_PI * 2.0f) + 0.5f; + } + break; + } + case SHD_BLEND_QUADRATIC_SPHERE: { + for (int64_t i : mask) { + /* Bias a little bit for the case where input is a unit length vector, + * to get exactly zero instead of a small random value depending + * on float precision. */ + const float r = std::max(0.999999f - math::length(vector[i]), 0.0f); + fac[i] = r * r; + } + break; + } + case SHD_BLEND_SPHERICAL: { + for (int64_t i : mask) { + /* Bias a little bit for the case where input is a unit length vector, + * to get exactly zero instead of a small random value depending + * on float precision. */ + fac[i] = std::max(0.999999f - math::length(vector[i]), 0.0f); + } + break; + } + } + if (compute_color) { + for (int64_t i : mask) { + r_color[i] = ColorGeometry4f(fac[i], fac[i], fac[i], 1.0f); + } + } + } +}; + +static void sh_node_gradient_tex_build_multi_function( + blender::nodes::NodeMultiFunctionBuilder &builder) +{ + bNode &node = builder.node(); + NodeTexGradient *tex = (NodeTexGradient *)node.storage; + builder.construct_and_set_matching_fn<GradientFunction>(tex->gradient_type); +} + +} // namespace blender::nodes::node_shader_tex_gradient_cc + +void register_node_type_sh_tex_gradient() { + namespace file_ns = blender::nodes::node_shader_tex_gradient_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_GRADIENT, "Gradient Texture", NODE_CLASS_TEXTURE, 0); - ntype.declare = blender::nodes::sh_node_tex_gradient_declare; - node_type_init(&ntype, node_shader_init_tex_gradient); + sh_fn_node_type_base(&ntype, SH_NODE_TEX_GRADIENT, "Gradient Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::sh_node_tex_gradient_declare; + ntype.draw_buttons = file_ns::node_shader_buts_tex_gradient; + node_type_init(&ntype, file_ns::node_shader_init_tex_gradient); node_type_storage( &ntype, "NodeTexGradient", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_tex_gradient); + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_gradient); + ntype.build_multi_function = file_ns::sh_node_gradient_tex_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.cc index bf7c4edc1c9..7c7154b8f7a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.cc @@ -17,33 +17,21 @@ * All rights reserved. */ -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_tex_image_in[] = { - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_tex_image_out[] = { - {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK}, - {SOCK_FLOAT, - N_("Alpha"), - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - PROP_NONE, - SOCK_NO_INTERNAL_LINK}, - {-1, ""}, -}; +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_tex_image_cc { + +static void sh_node_tex_image_declare(NodeDeclarationBuilder &b) +{ + b.is_function_node(); + b.add_input<decl::Vector>(N_("Vector")).implicit_field(); + b.add_output<decl::Color>(N_("Color")).no_muted_links(); + b.add_output<decl::Float>(N_("Alpha")).no_muted_links(); +} static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node) { - NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage"); + NodeTexImage *tex = MEM_cnew<NodeTexImage>(__func__); BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); BKE_texture_colormapping_default(&tex->base.color_mapping); BKE_imageuser_default(&tex->iuser); @@ -58,12 +46,12 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, GPUNodeStack *out) { Image *ima = (Image *)node->id; - NodeTexImage *tex = node->storage; + NodeTexImage *tex = (NodeTexImage *)node->storage; /* We get the image user from the original node, since GPU image keeps * a pointer to it and the dependency refreshes the original. */ bNode *node_original = node->original ? node->original : node; - NodeTexImage *tex_original = node_original->storage; + NodeTexImage *tex_original = (NodeTexImage *)node_original->storage; ImageUser *iuser = &tex_original->iuser; if (!ima) { @@ -78,7 +66,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, node_shader_gpu_tex_mapping(mat, node, in, out); - eGPUSamplerState sampler_state = 0; + eGPUSamplerState sampler_state = GPU_SAMPLER_DEFAULT; switch (tex->extension) { case SHD_IMAGE_EXTENSION_REPEAT: @@ -94,7 +82,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, if (tex->interpolation != SHD_INTERP_CLOSEST) { sampler_state |= GPU_SAMPLER_ANISO | GPU_SAMPLER_FILTER; /* TODO(fclem): For now assume mipmap is always enabled. */ - sampler_state |= true ? GPU_SAMPLER_MIPMAP : 0; + sampler_state |= GPU_SAMPLER_MIPMAP; } const bool use_cubic = ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART); @@ -181,18 +169,21 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, return true; } -/* node type definition */ -void register_node_type_sh_tex_image(void) +} // namespace blender::nodes::node_shader_tex_image_cc + +void register_node_type_sh_tex_image() { + namespace file_ns = blender::nodes::node_shader_tex_image_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_IMAGE, "Image Texture", NODE_CLASS_TEXTURE, 0); - node_type_socket_templates(&ntype, sh_node_tex_image_in, sh_node_tex_image_out); - node_type_init(&ntype, node_shader_init_tex_image); + sh_node_type_base(&ntype, SH_NODE_TEX_IMAGE, "Image Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::sh_node_tex_image_declare; + node_type_init(&ntype, file_ns::node_shader_init_tex_image); node_type_storage( &ntype, "NodeTexImage", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_tex_image); - node_type_label(&ntype, node_image_label); + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_image); + ntype.labelfunc = node_image_label; node_type_size_preset(&ntype, NODE_SIZE_LARGE); nodeRegisterType(&ntype); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c deleted file mode 100644 index 51721f8bb09..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_tex_magic_in[] = { - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, - {SOCK_FLOAT, N_("Distortion"), 1.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_tex_magic_out[] = { - {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK}, - {SOCK_FLOAT, - N_("Fac"), - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - PROP_FACTOR, - SOCK_NO_INTERNAL_LINK}, - {-1, ""}, -}; - -static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeTexMagic *tex = MEM_callocN(sizeof(NodeTexMagic), "NodeTexMagic"); - BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - BKE_texture_colormapping_default(&tex->base.color_mapping); - tex->depth = 2; - - node->storage = tex; -} - -static int node_shader_gpu_tex_magic(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - NodeTexMagic *tex = (NodeTexMagic *)node->storage; - float depth = tex->depth; - - node_shader_gpu_default_tex_coord(mat, node, &in[0].link); - node_shader_gpu_tex_mapping(mat, node, in, out); - - return GPU_stack_link(mat, node, "node_tex_magic", in, out, GPU_constant(&depth)); -} - -/* node type definition */ -void register_node_type_sh_tex_magic(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_TEX_MAGIC, "Magic Texture", NODE_CLASS_TEXTURE, 0); - node_type_socket_templates(&ntype, sh_node_tex_magic_in, sh_node_tex_magic_out); - node_type_init(&ntype, node_shader_init_tex_magic); - node_type_storage( - &ntype, "NodeTexMagic", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_tex_magic); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc b/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc new file mode 100644 index 00000000000..e40914783b6 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc @@ -0,0 +1,204 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_tex_magic_cc { + +static void sh_node_tex_magic_declare(NodeDeclarationBuilder &b) +{ + b.is_function_node(); + b.add_input<decl::Vector>(N_("Vector")).implicit_field(); + b.add_input<decl::Float>(N_("Scale")).min(-1000.0f).max(1000.0f).default_value(5.0f); + b.add_input<decl::Float>(N_("Distortion")).min(-1000.0f).max(1000.0f).default_value(1.0f); + b.add_output<decl::Color>(N_("Color")).no_muted_links(); + b.add_output<decl::Float>(N_("Fac")).no_muted_links(); +} + +static void node_shader_buts_tex_magic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "turbulence_depth", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); +} + +static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeTexMagic *tex = MEM_cnew<NodeTexMagic>(__func__); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); + tex->depth = 2; + + node->storage = tex; +} + +static int node_shader_gpu_tex_magic(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + NodeTexMagic *tex = (NodeTexMagic *)node->storage; + float depth = tex->depth; + + node_shader_gpu_default_tex_coord(mat, node, &in[0].link); + node_shader_gpu_tex_mapping(mat, node, in, out); + + return GPU_stack_link(mat, node, "node_tex_magic", in, out, GPU_constant(&depth)); +} + +class MagicFunction : public fn::MultiFunction { + private: + int depth_; + + public: + MagicFunction(int depth) : depth_(depth) + { + static fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static fn::MFSignature create_signature() + { + fn::MFSignatureBuilder signature{"MagicFunction"}; + signature.single_input<float3>("Vector"); + signature.single_input<float>("Scale"); + signature.single_input<float>("Distortion"); + signature.single_output<ColorGeometry4f>("Color"); + signature.single_output<float>("Fac"); + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); + const VArray<float> &scale = params.readonly_single_input<float>(1, "Scale"); + const VArray<float> &distortion = params.readonly_single_input<float>(2, "Distortion"); + + MutableSpan<ColorGeometry4f> r_color = params.uninitialized_single_output<ColorGeometry4f>( + 3, "Color"); + MutableSpan<float> r_fac = params.uninitialized_single_output_if_required<float>(4, "Fac"); + + const bool compute_factor = !r_fac.is_empty(); + + for (int64_t i : mask) { + const float3 co = vector[i] * scale[i]; + const float distort = distortion[i]; + float x = sinf((co[0] + co[1] + co[2]) * 5.0f); + float y = cosf((-co[0] + co[1] - co[2]) * 5.0f); + float z = -cosf((-co[0] - co[1] + co[2]) * 5.0f); + + if (depth_ > 0) { + x *= distort; + y *= distort; + z *= distort; + y = -cosf(x - y + z); + y *= distort; + + if (depth_ > 1) { + x = cosf(x - y - z); + x *= distort; + + if (depth_ > 2) { + z = sinf(-x - y - z); + z *= distort; + + if (depth_ > 3) { + x = -cosf(-x + y - z); + x *= distort; + + if (depth_ > 4) { + y = -sinf(-x + y + z); + y *= distort; + + if (depth_ > 5) { + y = -cosf(-x + y + z); + y *= distort; + + if (depth_ > 6) { + x = cosf(x + y + z); + x *= distort; + + if (depth_ > 7) { + z = sinf(x + y - z); + z *= distort; + + if (depth_ > 8) { + x = -cosf(-x - y + z); + x *= distort; + + if (depth_ > 9) { + y = -sinf(x - y + z); + y *= distort; + } + } + } + } + } + } + } + } + } + } + + if (distort != 0.0f) { + const float d = distort * 2.0f; + x /= d; + y /= d; + z /= d; + } + + r_color[i] = ColorGeometry4f(0.5f - x, 0.5f - y, 0.5f - z, 1.0f); + } + if (compute_factor) { + for (int64_t i : mask) { + r_fac[i] = (r_color[i].r + r_color[i].g + r_color[i].b) * (1.0f / 3.0f); + } + } + } +}; + +static void sh_node_magic_tex_build_multi_function( + blender::nodes::NodeMultiFunctionBuilder &builder) +{ + bNode &node = builder.node(); + NodeTexMagic *tex = (NodeTexMagic *)node.storage; + builder.construct_and_set_matching_fn<MagicFunction>(tex->depth); +} + +} // namespace blender::nodes::node_shader_tex_magic_cc + +void register_node_type_sh_tex_magic() +{ + namespace file_ns = blender::nodes::node_shader_tex_magic_cc; + + static bNodeType ntype; + + sh_fn_node_type_base(&ntype, SH_NODE_TEX_MAGIC, "Magic Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::sh_node_tex_magic_declare; + ntype.draw_buttons = file_ns::node_shader_buts_tex_magic; + node_type_init(&ntype, file_ns::node_shader_init_tex_magic); + node_type_storage( + &ntype, "NodeTexMagic", node_free_standard_storage, node_copy_standard_storage); + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_magic); + ntype.build_multi_function = file_ns::sh_node_magic_tex_build_multi_function; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc index 23f150d8135..45c2a83c178 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc @@ -17,30 +17,43 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -namespace blender::nodes { +#include "BLI_noise.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_tex_musgrave_cc { + +NODE_STORAGE_FUNCS(NodeTexMusgrave) static void sh_node_tex_musgrave_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>("Vector").hide_value(); - b.add_input<decl::Float>("W").min(-1000.0f).max(1000.0f); - b.add_input<decl::Float>("Scale").min(-1000.0f).max(1000.0f).default_value(5.0f); - b.add_input<decl::Float>("Detail").min(0.0f).max(16.0f).default_value(2.0f); - b.add_input<decl::Float>("Dimension").min(0.0f).max(1000.0f).default_value(2.0f); - b.add_input<decl::Float>("Lacunarity").min(0.0f).max(1000.0f).default_value(2.0f); - b.add_input<decl::Float>("Offset").min(-1000.0f).max(1000.0f); - b.add_input<decl::Float>("Gain").min(0.0f).max(1000.0f).default_value(1.0f); - b.add_output<decl::Float>("Fac").no_muted_links(); -}; + b.add_input<decl::Vector>(N_("Vector")).hide_value().implicit_field(); + b.add_input<decl::Float>(N_("W")).min(-1000.0f).max(1000.0f).make_available([](bNode &node) { + /* Default to 1 instead of 4, because it is much faster. */ + node_storage(node).dimensions = 1; + }); + b.add_input<decl::Float>(N_("Scale")).min(-1000.0f).max(1000.0f).default_value(5.0f); + b.add_input<decl::Float>(N_("Detail")).min(0.0f).max(15.0f).default_value(2.0f); + b.add_input<decl::Float>(N_("Dimension")).min(0.0f).max(1000.0f).default_value(2.0f); + b.add_input<decl::Float>(N_("Lacunarity")).min(0.0f).max(1000.0f).default_value(2.0f); + b.add_input<decl::Float>(N_("Offset")).min(-1000.0f).max(1000.0f); + b.add_input<decl::Float>(N_("Gain")).min(0.0f).max(1000.0f).default_value(1.0f); + b.add_output<decl::Float>(N_("Fac")).no_muted_links(); +} -} // namespace blender::nodes +static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "musgrave_dimensions", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + uiItemR(layout, ptr, "musgrave_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node) { - NodeTexMusgrave *tex = (NodeTexMusgrave *)MEM_callocN(sizeof(NodeTexMusgrave), - "NodeTexMusgrave"); + NodeTexMusgrave *tex = MEM_cnew<NodeTexMusgrave>(__func__); BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); BKE_texture_colormapping_default(&tex->base.color_mapping); tex->musgrave_type = SHD_MUSGRAVE_FBM; @@ -102,40 +115,447 @@ static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, return GPU_stack_link(mat, node, name, in, out); } -static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node) +static void node_shader_update_tex_musgrave(bNodeTree *ntree, bNode *node) { - NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage; + const NodeTexMusgrave &storage = node_storage(*node); bNodeSocket *inVectorSock = nodeFindSocket(node, SOCK_IN, "Vector"); bNodeSocket *inWSock = nodeFindSocket(node, SOCK_IN, "W"); bNodeSocket *inOffsetSock = nodeFindSocket(node, SOCK_IN, "Offset"); bNodeSocket *inGainSock = nodeFindSocket(node, SOCK_IN, "Gain"); - nodeSetSocketAvailability(inVectorSock, tex->dimensions != 1); - nodeSetSocketAvailability(inWSock, tex->dimensions == 1 || tex->dimensions == 4); - nodeSetSocketAvailability(inOffsetSock, - tex->musgrave_type != SHD_MUSGRAVE_MULTIFRACTAL && - tex->musgrave_type != SHD_MUSGRAVE_FBM); - nodeSetSocketAvailability(inGainSock, - tex->musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL || - tex->musgrave_type == SHD_MUSGRAVE_RIDGED_MULTIFRACTAL); + nodeSetSocketAvailability(ntree, inVectorSock, storage.dimensions != 1); + nodeSetSocketAvailability(ntree, inWSock, storage.dimensions == 1 || storage.dimensions == 4); + nodeSetSocketAvailability(ntree, + inOffsetSock, + storage.musgrave_type != SHD_MUSGRAVE_MULTIFRACTAL && + storage.musgrave_type != SHD_MUSGRAVE_FBM); + nodeSetSocketAvailability(ntree, + inGainSock, + storage.musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL || + storage.musgrave_type == SHD_MUSGRAVE_RIDGED_MULTIFRACTAL); bNodeSocket *outFacSock = nodeFindSocket(node, SOCK_OUT, "Fac"); node_sock_label(outFacSock, "Height"); } -void register_node_type_sh_tex_musgrave(void) +class MusgraveFunction : public fn::MultiFunction { + private: + const int dimensions_; + const int musgrave_type_; + + public: + MusgraveFunction(const int dimensions, const int musgrave_type) + : dimensions_(dimensions), musgrave_type_(musgrave_type) + { + BLI_assert(dimensions >= 1 && dimensions <= 4); + BLI_assert(musgrave_type >= 0 && musgrave_type <= 4); + static std::array<fn::MFSignature, 20> signatures{ + create_signature(1, SHD_MUSGRAVE_MULTIFRACTAL), + create_signature(2, SHD_MUSGRAVE_MULTIFRACTAL), + create_signature(3, SHD_MUSGRAVE_MULTIFRACTAL), + create_signature(4, SHD_MUSGRAVE_MULTIFRACTAL), + + create_signature(1, SHD_MUSGRAVE_FBM), + create_signature(2, SHD_MUSGRAVE_FBM), + create_signature(3, SHD_MUSGRAVE_FBM), + create_signature(4, SHD_MUSGRAVE_FBM), + + create_signature(1, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL), + create_signature(2, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL), + create_signature(3, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL), + create_signature(4, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL), + + create_signature(1, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL), + create_signature(2, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL), + create_signature(3, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL), + create_signature(4, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL), + + create_signature(1, SHD_MUSGRAVE_HETERO_TERRAIN), + create_signature(2, SHD_MUSGRAVE_HETERO_TERRAIN), + create_signature(3, SHD_MUSGRAVE_HETERO_TERRAIN), + create_signature(4, SHD_MUSGRAVE_HETERO_TERRAIN), + }; + this->set_signature(&signatures[dimensions + musgrave_type * 4 - 1]); + } + + static fn::MFSignature create_signature(const int dimensions, const int musgrave_type) + { + fn::MFSignatureBuilder signature{"Musgrave"}; + + if (ELEM(dimensions, 2, 3, 4)) { + signature.single_input<float3>("Vector"); + } + if (ELEM(dimensions, 1, 4)) { + signature.single_input<float>("W"); + } + signature.single_input<float>("Scale"); + signature.single_input<float>("Detail"); + signature.single_input<float>("Dimension"); + signature.single_input<float>("Lacunarity"); + if (ELEM(musgrave_type, + SHD_MUSGRAVE_RIDGED_MULTIFRACTAL, + SHD_MUSGRAVE_HYBRID_MULTIFRACTAL, + SHD_MUSGRAVE_HETERO_TERRAIN)) { + signature.single_input<float>("Offset"); + } + if (ELEM(musgrave_type, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL)) { + signature.single_input<float>("Gain"); + } + + signature.single_output<float>("Fac"); + + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + auto get_vector = [&](int param_index) -> VArray<float3> { + return params.readonly_single_input<float3>(param_index, "Vector"); + }; + auto get_w = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "W"); + }; + auto get_scale = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Scale"); + }; + auto get_detail = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Detail"); + }; + auto get_dimension = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Dimension"); + }; + auto get_lacunarity = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Lacunarity"); + }; + auto get_offset = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Offset"); + }; + auto get_gain = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Gain"); + }; + + auto get_r_factor = [&](int param_index) -> MutableSpan<float> { + return params.uninitialized_single_output_if_required<float>(param_index, "Fac"); + }; + + int param = ELEM(dimensions_, 2, 3, 4) + ELEM(dimensions_, 1, 4); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &detail = get_detail(param++); + const VArray<float> &dimension = get_dimension(param++); + const VArray<float> &lacunarity = get_lacunarity(param++); + + switch (musgrave_type_) { + case SHD_MUSGRAVE_MULTIFRACTAL: { + MutableSpan<float> r_factor = get_r_factor(param++); + const bool compute_factor = !r_factor.is_empty(); + switch (dimensions_) { + case 1: { + const VArray<float> &w = get_w(0); + if (compute_factor) { + for (int64_t i : mask) { + const float position = w[i] * scale[i]; + r_factor[i] = noise::musgrave_multi_fractal( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + case 2: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float2 position = float2(pxyz[0], pxyz[1]); + r_factor[i] = noise::musgrave_multi_fractal( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + case 3: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 position = vector[i] * scale[i]; + r_factor[i] = noise::musgrave_multi_fractal( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + case 4: { + const VArray<float3> &vector = get_vector(0); + const VArray<float> &w = get_w(1); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float pw = w[i] * scale[i]; + const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; + r_factor[i] = noise::musgrave_multi_fractal( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + } + break; + } + case SHD_MUSGRAVE_RIDGED_MULTIFRACTAL: { + const VArray<float> &offset = get_offset(param++); + const VArray<float> &gain = get_gain(param++); + MutableSpan<float> r_factor = get_r_factor(param++); + const bool compute_factor = !r_factor.is_empty(); + switch (dimensions_) { + case 1: { + const VArray<float> &w = get_w(0); + if (compute_factor) { + for (int64_t i : mask) { + const float position = w[i] * scale[i]; + r_factor[i] = noise::musgrave_ridged_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + case 2: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float2 position = float2(pxyz[0], pxyz[1]); + r_factor[i] = noise::musgrave_ridged_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + case 3: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 position = vector[i] * scale[i]; + r_factor[i] = noise::musgrave_ridged_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + case 4: { + const VArray<float3> &vector = get_vector(0); + const VArray<float> &w = get_w(1); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float pw = w[i] * scale[i]; + const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; + r_factor[i] = noise::musgrave_ridged_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + } + break; + } + case SHD_MUSGRAVE_HYBRID_MULTIFRACTAL: { + const VArray<float> &offset = get_offset(param++); + const VArray<float> &gain = get_gain(param++); + MutableSpan<float> r_factor = get_r_factor(param++); + const bool compute_factor = !r_factor.is_empty(); + switch (dimensions_) { + case 1: { + const VArray<float> &w = get_w(0); + if (compute_factor) { + for (int64_t i : mask) { + const float position = w[i] * scale[i]; + r_factor[i] = noise::musgrave_hybrid_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + case 2: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float2 position = float2(pxyz[0], pxyz[1]); + r_factor[i] = noise::musgrave_hybrid_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + case 3: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 position = vector[i] * scale[i]; + r_factor[i] = noise::musgrave_hybrid_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + case 4: { + const VArray<float3> &vector = get_vector(0); + const VArray<float> &w = get_w(1); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float pw = w[i] * scale[i]; + const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; + r_factor[i] = noise::musgrave_hybrid_multi_fractal( + position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]); + } + } + break; + } + } + break; + } + case SHD_MUSGRAVE_FBM: { + MutableSpan<float> r_factor = get_r_factor(param++); + const bool compute_factor = !r_factor.is_empty(); + switch (dimensions_) { + case 1: { + const VArray<float> &w = get_w(0); + if (compute_factor) { + for (int64_t i : mask) { + const float position = w[i] * scale[i]; + r_factor[i] = noise::musgrave_fBm( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + case 2: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float2 position = float2(pxyz[0], pxyz[1]); + r_factor[i] = noise::musgrave_fBm( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + case 3: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 position = vector[i] * scale[i]; + r_factor[i] = noise::musgrave_fBm( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + case 4: { + const VArray<float3> &vector = get_vector(0); + const VArray<float> &w = get_w(1); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float pw = w[i] * scale[i]; + const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; + r_factor[i] = noise::musgrave_fBm( + position, dimension[i], lacunarity[i], detail[i]); + } + } + break; + } + } + break; + } + case SHD_MUSGRAVE_HETERO_TERRAIN: { + const VArray<float> &offset = get_offset(param++); + MutableSpan<float> r_factor = get_r_factor(param++); + const bool compute_factor = !r_factor.is_empty(); + switch (dimensions_) { + case 1: { + const VArray<float> &w = get_w(0); + if (compute_factor) { + for (int64_t i : mask) { + const float position = w[i] * scale[i]; + r_factor[i] = noise::musgrave_hetero_terrain( + position, dimension[i], lacunarity[i], detail[i], offset[i]); + } + } + break; + } + case 2: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float2 position = float2(pxyz[0], pxyz[1]); + r_factor[i] = noise::musgrave_hetero_terrain( + position, dimension[i], lacunarity[i], detail[i], offset[i]); + } + } + break; + } + case 3: { + const VArray<float3> &vector = get_vector(0); + if (compute_factor) { + for (int64_t i : mask) { + const float3 position = vector[i] * scale[i]; + r_factor[i] = noise::musgrave_hetero_terrain( + position, dimension[i], lacunarity[i], detail[i], offset[i]); + } + } + break; + } + case 4: { + const VArray<float3> &vector = get_vector(0); + const VArray<float> &w = get_w(1); + if (compute_factor) { + for (int64_t i : mask) { + const float3 pxyz = vector[i] * scale[i]; + const float pw = w[i] * scale[i]; + const float4 position{pxyz[0], pxyz[1], pxyz[2], pw}; + r_factor[i] = noise::musgrave_hetero_terrain( + position, dimension[i], lacunarity[i], detail[i], offset[i]); + } + } + break; + } + } + break; + } + } + } +}; + +static void sh_node_musgrave_build_multi_function( + blender::nodes::NodeMultiFunctionBuilder &builder) { + bNode &node = builder.node(); + NodeTexMusgrave *tex = (NodeTexMusgrave *)node.storage; + builder.construct_and_set_matching_fn<MusgraveFunction>(tex->dimensions, tex->musgrave_type); +} + +} // namespace blender::nodes::node_shader_tex_musgrave_cc + +void register_node_type_sh_tex_musgrave() +{ + namespace file_ns = blender::nodes::node_shader_tex_musgrave_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE, 0); - ntype.declare = blender::nodes::sh_node_tex_musgrave_declare; + sh_fn_node_type_base(&ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::sh_node_tex_musgrave_declare; + ntype.draw_buttons = file_ns::node_shader_buts_tex_musgrave; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, node_shader_init_tex_musgrave); + node_type_init(&ntype, file_ns::node_shader_init_tex_musgrave); node_type_storage( &ntype, "NodeTexMusgrave", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_tex_musgrave); - node_type_update(&ntype, node_shader_update_tex_musgrave); + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_musgrave); + node_type_update(&ntype, file_ns::node_shader_update_tex_musgrave); + ntype.build_multi_function = file_ns::sh_node_musgrave_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc index 6ffc8979815..1c703313edf 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc @@ -17,34 +17,45 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" #include "BLI_noise.hh" -namespace blender::nodes { +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_tex_noise_cc { + +NODE_STORAGE_FUNCS(NodeTexNoise) static void sh_node_tex_noise_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>("Vector").implicit_field(); - b.add_input<decl::Float>("W").min(-1000.0f).max(1000.0f); - b.add_input<decl::Float>("Scale").min(-1000.0f).max(1000.0f).default_value(5.0f); - b.add_input<decl::Float>("Detail").min(0.0f).max(16.0f).default_value(2.0f); - b.add_input<decl::Float>("Roughness") + b.add_input<decl::Vector>(N_("Vector")).implicit_field(); + b.add_input<decl::Float>(N_("W")).min(-1000.0f).max(1000.0f).make_available([](bNode &node) { + /* Default to 1 instead of 4, because it is much faster. */ + node_storage(node).dimensions = 1; + }); + b.add_input<decl::Float>(N_("Scale")).min(-1000.0f).max(1000.0f).default_value(5.0f); + b.add_input<decl::Float>(N_("Detail")).min(0.0f).max(15.0f).default_value(2.0f); + b.add_input<decl::Float>(N_("Roughness")) .min(0.0f) .max(1.0f) .default_value(0.5f) .subtype(PROP_FACTOR); - b.add_input<decl::Float>("Distortion").min(-1000.0f).max(1000.0f).default_value(0.0f); - b.add_output<decl::Float>("Fac").no_muted_links(); - b.add_output<decl::Color>("Color").no_muted_links(); -}; + b.add_input<decl::Float>(N_("Distortion")).min(-1000.0f).max(1000.0f).default_value(0.0f); + b.add_output<decl::Float>(N_("Fac")).no_muted_links(); + b.add_output<decl::Color>(N_("Color")).no_muted_links(); +} -} // namespace blender::nodes +static void node_shader_buts_tex_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "noise_dimensions", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node) { - NodeTexNoise *tex = (NodeTexNoise *)MEM_callocN(sizeof(NodeTexNoise), "NodeTexNoise"); + NodeTexNoise *tex = MEM_cnew<NodeTexNoise>(__func__); BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); BKE_texture_colormapping_default(&tex->base.color_mapping); tex->dimensions = 3; @@ -71,23 +82,21 @@ static int node_shader_gpu_tex_noise(GPUMaterial *mat, node_shader_gpu_default_tex_coord(mat, node, &in[0].link); node_shader_gpu_tex_mapping(mat, node, in, out); - NodeTexNoise *tex = (NodeTexNoise *)node->storage; - const char *name = gpu_shader_get_name(tex->dimensions); + const NodeTexNoise &storage = node_storage(*node); + const char *name = gpu_shader_get_name(storage.dimensions); return GPU_stack_link(mat, node, name, in, out); } -static void node_shader_update_tex_noise(bNodeTree *UNUSED(ntree), bNode *node) +static void node_shader_update_tex_noise(bNodeTree *ntree, bNode *node) { bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector"); bNodeSocket *sockW = nodeFindSocket(node, SOCK_IN, "W"); - NodeTexNoise *tex = (NodeTexNoise *)node->storage; - nodeSetSocketAvailability(sockVector, tex->dimensions != 1); - nodeSetSocketAvailability(sockW, tex->dimensions == 1 || tex->dimensions == 4); + const NodeTexNoise &storage = node_storage(*node); + nodeSetSocketAvailability(ntree, sockVector, storage.dimensions != 1); + nodeSetSocketAvailability(ntree, sockW, storage.dimensions == 1 || storage.dimensions == 4); } -namespace blender::nodes { - class NoiseFunction : public fn::MultiFunction { private: int dimensions_; @@ -167,14 +176,14 @@ class NoiseFunction : public fn::MultiFunction { const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); if (compute_factor) { for (int64_t i : mask) { - const float2 position = vector[i] * scale[i]; + const float2 position = float2(vector[i] * scale[i]); r_factor[i] = noise::perlin_fractal_distorted( position, detail[i], roughness[i], distortion[i]); } } if (compute_color) { for (int64_t i : mask) { - const float2 position = vector[i] * scale[i]; + const float2 position = float2(vector[i] * scale[i]); const float3 c = noise::perlin_float3_fractal_distorted( position, detail[i], roughness[i], distortion[i]); r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f); @@ -229,30 +238,39 @@ class NoiseFunction : public fn::MultiFunction { } } } + + ExecutionHints get_execution_hints() const override + { + ExecutionHints hints; + hints.allocates_array = false; + hints.min_grain_size = 100; + return hints; + } }; static void sh_node_noise_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &builder) { - bNode &node = builder.node(); - NodeTexNoise *tex = (NodeTexNoise *)node.storage; - builder.construct_and_set_matching_fn<NoiseFunction>(tex->dimensions); + const NodeTexNoise &storage = node_storage(builder.node()); + builder.construct_and_set_matching_fn<NoiseFunction>(storage.dimensions); } -} // namespace blender::nodes +} // namespace blender::nodes::node_shader_tex_noise_cc -/* node type definition */ -void register_node_type_sh_tex_noise(void) +void register_node_type_sh_tex_noise() { + namespace file_ns = blender::nodes::node_shader_tex_noise_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0); - ntype.declare = blender::nodes::sh_node_tex_noise_declare; - node_type_init(&ntype, node_shader_init_tex_noise); + sh_fn_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::sh_node_tex_noise_declare; + ntype.draw_buttons = file_ns::node_shader_buts_tex_noise; + node_type_init(&ntype, file_ns::node_shader_init_tex_noise); node_type_storage( &ntype, "NodeTexNoise", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_tex_noise); - node_type_update(&ntype, node_shader_update_tex_noise); - ntype.build_multi_function = blender::nodes::sh_node_noise_build_multi_function; + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_noise); + node_type_update(&ntype, file_ns::node_shader_update_tex_noise); + ntype.build_multi_function = file_ns::sh_node_noise_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c deleted file mode 100644 index 14cd1fd4c0c..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2015 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -#include "RE_texture.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_tex_pointdensity_in[] = { - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_tex_pointdensity_out[] = { - {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Density"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, - {-1, ""}, -}; - -static void node_shader_init_tex_pointdensity(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeShaderTexPointDensity *point_density = MEM_callocN(sizeof(NodeShaderTexPointDensity), - "new pd node"); - point_density->resolution = 100; - point_density->radius = 0.3f; - point_density->space = SHD_POINTDENSITY_SPACE_OBJECT; - point_density->color_source = SHD_POINTDENSITY_COLOR_PARTAGE; - node->storage = point_density; -} - -static void node_shader_free_tex_pointdensity(bNode *node) -{ - NodeShaderTexPointDensity *point_density = node->storage; - PointDensity *pd = &point_density->pd; - RE_point_density_free(pd); - BKE_texture_pointdensity_free_data(pd); - memset(pd, 0, sizeof(*pd)); - MEM_freeN(point_density); -} - -static void node_shader_copy_tex_pointdensity(bNodeTree *UNUSED(dest_ntree), - bNode *dest_node, - const bNode *src_node) -{ - dest_node->storage = MEM_dupallocN(src_node->storage); - NodeShaderTexPointDensity *point_density = dest_node->storage; - PointDensity *pd = &point_density->pd; - memset(pd, 0, sizeof(*pd)); -} - -/* node type definition */ -void register_node_type_sh_tex_pointdensity(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_TEX_POINTDENSITY, "Point Density", NODE_CLASS_TEXTURE, 0); - node_type_socket_templates(&ntype, sh_node_tex_pointdensity_in, sh_node_tex_pointdensity_out); - node_type_init(&ntype, node_shader_init_tex_pointdensity); - node_type_storage(&ntype, - "NodeShaderTexPointDensity", - node_shader_free_tex_pointdensity, - node_shader_copy_tex_pointdensity); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.cc b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.cc new file mode 100644 index 00000000000..1a4cf70565f --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.cc @@ -0,0 +1,131 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +#include "RE_texture.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_tex_pointdensity_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Vector>(N_("Vector")).hide_value(); + b.add_output<decl::Color>(N_("Color")); + b.add_output<decl::Float>(N_("Density")); +} + +static void node_shader_buts_tex_pointdensity(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + bNode *node = (bNode *)ptr->data; + NodeShaderTexPointDensity *shader_point_density = (NodeShaderTexPointDensity *)node->storage; + Object *ob = (Object *)node->id; + + PointerRNA ob_ptr, obdata_ptr; + RNA_id_pointer_create((ID *)ob, &ob_ptr); + RNA_id_pointer_create(ob ? (ID *)ob->data : nullptr, &obdata_ptr); + + uiItemR(layout, ptr, "point_source", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); + uiItemR(layout, ptr, "object", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + + if (node->id && shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) { + PointerRNA dataptr; + RNA_id_pointer_create((ID *)node->id, &dataptr); + uiItemPointerR( + layout, ptr, "particle_system", &dataptr, "particle_systems", nullptr, ICON_NONE); + } + + uiItemR(layout, ptr, "space", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + uiItemR(layout, ptr, "radius", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + uiItemR(layout, ptr, "interpolation", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + uiItemR(layout, ptr, "resolution", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) { + uiItemR(layout, ptr, "particle_color_source", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + } + else { + uiItemR(layout, ptr, "vertex_color_source", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTWEIGHT) { + if (ob_ptr.data) { + uiItemPointerR( + layout, ptr, "vertex_attribute_name", &ob_ptr, "vertex_groups", "", ICON_NONE); + } + } + if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTCOL) { + if (obdata_ptr.data) { + uiItemPointerR( + layout, ptr, "vertex_attribute_name", &obdata_ptr, "vertex_colors", "", ICON_NONE); + } + } + } +} + +static void node_shader_init_tex_pointdensity(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeShaderTexPointDensity *point_density = MEM_cnew<NodeShaderTexPointDensity>("new pd node"); + point_density->resolution = 100; + point_density->radius = 0.3f; + point_density->space = SHD_POINTDENSITY_SPACE_OBJECT; + point_density->color_source = SHD_POINTDENSITY_COLOR_PARTAGE; + node->storage = point_density; +} + +static void node_shader_free_tex_pointdensity(bNode *node) +{ + NodeShaderTexPointDensity *point_density = (NodeShaderTexPointDensity *)node->storage; + PointDensity *pd = &point_density->pd; + RE_point_density_free(pd); + BKE_texture_pointdensity_free_data(pd); + memset(pd, 0, sizeof(*pd)); + MEM_freeN(point_density); +} + +static void node_shader_copy_tex_pointdensity(bNodeTree *UNUSED(dest_ntree), + bNode *dest_node, + const bNode *src_node) +{ + dest_node->storage = MEM_dupallocN(src_node->storage); + NodeShaderTexPointDensity *point_density = (NodeShaderTexPointDensity *)dest_node->storage; + PointDensity *pd = &point_density->pd; + memset(pd, 0, sizeof(*pd)); +} + +} // namespace blender::nodes::node_shader_tex_pointdensity_cc + +/* node type definition */ +void register_node_type_sh_tex_pointdensity() +{ + namespace file_ns = blender::nodes::node_shader_tex_pointdensity_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_TEX_POINTDENSITY, "Point Density", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_tex_pointdensity; + node_type_init(&ntype, file_ns::node_shader_init_tex_pointdensity); + node_type_storage(&ntype, + "NodeShaderTexPointDensity", + file_ns::node_shader_free_tex_pointdensity, + file_ns::node_shader_copy_tex_pointdensity); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.cc index 5dc11c4df00..b8728d69bba 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.cc @@ -17,24 +17,66 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" #include "sky_model.h" -/* **************** OUTPUT ******************** */ +#include "BKE_context.h" +#include "BKE_scene.h" -static bNodeSocketTemplate sh_node_tex_sky_in[] = { - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {-1, ""}, -}; +#include "UI_interface.h" +#include "UI_resources.h" -static bNodeSocketTemplate sh_node_tex_sky_out[] = { - {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_tex_sky_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Vector>(N_("Vector")).hide_value(); + b.add_output<decl::Color>(N_("Color")).no_muted_links(); +} + +static void node_shader_buts_tex_sky(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiItemR(layout, ptr, "sky_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + + if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_PREETHAM) { + uiItemR(layout, ptr, "sun_direction", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + uiItemR(layout, ptr, "turbidity", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + } + if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_HOSEK) { + uiItemR(layout, ptr, "sun_direction", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + uiItemR(layout, ptr, "turbidity", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + uiItemR(layout, ptr, "ground_albedo", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + } + if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NISHITA) { + Scene *scene = CTX_data_scene(C); + if (BKE_scene_uses_blender_eevee(scene)) { + uiItemL(layout, TIP_("Nishita not available in Eevee"), ICON_ERROR); + } + uiItemR(layout, ptr, "sun_disc", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, 0); + + uiLayout *col; + if (RNA_boolean_get(ptr, "sun_disc")) { + col = uiLayoutColumn(layout, true); + uiItemR(col, ptr, "sun_size", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + uiItemR(col, ptr, "sun_intensity", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + } + + col = uiLayoutColumn(layout, true); + uiItemR(col, ptr, "sun_elevation", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + uiItemR(col, ptr, "sun_rotation", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + + uiItemR(layout, ptr, "altitude", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + + col = uiLayoutColumn(layout, true); + uiItemR(col, ptr, "air_density", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + uiItemR(col, ptr, "dust_density", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + uiItemR(col, ptr, "ozone_density", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + } +} static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node) { - NodeTexSky *tex = MEM_callocN(sizeof(NodeTexSky), "NodeTexSky"); + NodeTexSky *tex = MEM_cnew<NodeTexSky>("NodeTexSky"); BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); BKE_texture_colormapping_default(&tex->base.color_mapping); tex->sun_direction[0] = 0.0f; @@ -55,10 +97,10 @@ static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node) node->storage = tex; } -typedef struct SkyModelPreetham { +struct SkyModelPreetham { float config_Y[5], config_x[5], config_y[5]; /* named after xyY color space */ float radiance[3]; -} SkyModelPreetham; +}; static float sky_perez_function(const float *lam, float theta, float gamma) { @@ -195,27 +237,32 @@ static int node_shader_gpu_tex_sky(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_tex_sky_nishita", in, out); } -static void node_shader_update_sky(bNodeTree *UNUSED(ntree), bNode *node) +static void node_shader_update_sky(bNodeTree *ntree, bNode *node) { bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector"); NodeTexSky *tex = (NodeTexSky *)node->storage; - nodeSetSocketAvailability(sockVector, !(tex->sky_model == 2 && tex->sun_disc == 1)); + nodeSetSocketAvailability(ntree, sockVector, !(tex->sky_model == 2 && tex->sun_disc == 1)); } +} // namespace blender::nodes::node_shader_tex_sky_cc + /* node type definition */ -void register_node_type_sh_tex_sky(void) +void register_node_type_sh_tex_sky() { + namespace file_ns = blender::nodes::node_shader_tex_sky_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_SKY, "Sky Texture", NODE_CLASS_TEXTURE, 0); - node_type_socket_templates(&ntype, sh_node_tex_sky_in, sh_node_tex_sky_out); + sh_node_type_base(&ntype, SH_NODE_TEX_SKY, "Sky Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_tex_sky; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, node_shader_init_tex_sky); + node_type_init(&ntype, file_ns::node_shader_init_tex_sky); node_type_storage(&ntype, "NodeTexSky", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_tex_sky); - /* remove Vector input for Nishita */ - node_type_update(&ntype, node_shader_update_sky); + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_sky); + /* Remove vector input for Nishita sky model. */ + node_type_update(&ntype, file_ns::node_shader_update_sky); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc index e12e5724e8e..209f96449cd 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc @@ -17,39 +17,68 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -namespace blender::nodes { +#include "BLI_noise.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_tex_voronoi_cc { + +NODE_STORAGE_FUNCS(NodeTexVoronoi) static void sh_node_tex_voronoi_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>("Vector").hide_value(); - b.add_input<decl::Float>("W").min(-1000.0f).max(1000.0f); - b.add_input<decl::Float>("Scale").min(-1000.0f).max(1000.0f).default_value(5.0f); - b.add_input<decl::Float>("Smoothness") + b.add_input<decl::Vector>(N_("Vector")).hide_value().implicit_field(); + b.add_input<decl::Float>(N_("W")).min(-1000.0f).max(1000.0f).make_available([](bNode &node) { + /* Default to 1 instead of 4, because it is much faster. */ + node_storage(node).dimensions = 1; + }); + b.add_input<decl::Float>(N_("Scale")).min(-1000.0f).max(1000.0f).default_value(5.0f); + b.add_input<decl::Float>(N_("Smoothness")) .min(0.0f) .max(1.0f) .default_value(1.0f) - .subtype(PROP_FACTOR); - b.add_input<decl::Float>("Exponent").min(0.0f).max(32.0f).default_value(0.5f); - b.add_input<decl::Float>("Randomness") + .subtype(PROP_FACTOR) + .make_available([](bNode &node) { node_storage(node).feature = SHD_VORONOI_SMOOTH_F1; }); + b.add_input<decl::Float>(N_("Exponent")) + .min(0.0f) + .max(32.0f) + .default_value(0.5f) + .make_available([](bNode &node) { node_storage(node).distance = SHD_VORONOI_MINKOWSKI; }); + b.add_input<decl::Float>(N_("Randomness")) .min(0.0f) .max(1.0f) .default_value(1.0f) .subtype(PROP_FACTOR); - b.add_output<decl::Float>("Distance").no_muted_links(); - b.add_output<decl::Color>("Color").no_muted_links(); - b.add_output<decl::Vector>("Position").no_muted_links(); - b.add_output<decl::Float>("W").no_muted_links(); - b.add_output<decl::Float>("Radius").no_muted_links(); -}; + b.add_output<decl::Float>(N_("Distance")).no_muted_links(); + b.add_output<decl::Color>(N_("Color")).no_muted_links(); + b.add_output<decl::Vector>(N_("Position")).no_muted_links(); + b.add_output<decl::Float>(N_("W")).no_muted_links().make_available([](bNode &node) { + /* Default to 1 instead of 4, because it is much faster. */ + node_storage(node).dimensions = 1; + }); + b.add_output<decl::Float>(N_("Radius")).no_muted_links().make_available([](bNode &node) { + node_storage(node).feature = SHD_VORONOI_N_SPHERE_RADIUS; + }); +} -} // namespace blender::nodes +static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "voronoi_dimensions", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + uiItemR(layout, ptr, "feature", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + int feature = RNA_enum_get(ptr, "feature"); + if (!ELEM(feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS) && + RNA_enum_get(ptr, "voronoi_dimensions") != 1) { + uiItemR(layout, ptr, "distance", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + } +} static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node) { - NodeTexVoronoi *tex = (NodeTexVoronoi *)MEM_callocN(sizeof(NodeTexVoronoi), "NodeTexVoronoi"); + NodeTexVoronoi *tex = MEM_cnew<NodeTexVoronoi>(__func__); BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); BKE_texture_colormapping_default(&tex->base.color_mapping); tex->dimensions = 3; @@ -121,7 +150,7 @@ static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, return GPU_stack_link(mat, node, name, in, out, GPU_constant(&metric)); } -static void node_shader_update_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node) +static void node_shader_update_tex_voronoi(bNodeTree *ntree, bNode *node) { bNodeSocket *inVectorSock = nodeFindSocket(node, SOCK_IN, "Vector"); bNodeSocket *inWSock = nodeFindSocket(node, SOCK_IN, "W"); @@ -134,41 +163,1210 @@ static void node_shader_update_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node bNodeSocket *outWSock = nodeFindSocket(node, SOCK_OUT, "W"); bNodeSocket *outRadiusSock = nodeFindSocket(node, SOCK_OUT, "Radius"); - NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage; + const NodeTexVoronoi &storage = node_storage(*node); - nodeSetSocketAvailability(inWSock, tex->dimensions == 1 || tex->dimensions == 4); - nodeSetSocketAvailability(inVectorSock, tex->dimensions != 1); + nodeSetSocketAvailability(ntree, inWSock, storage.dimensions == 1 || storage.dimensions == 4); + nodeSetSocketAvailability(ntree, inVectorSock, storage.dimensions != 1); nodeSetSocketAvailability( + ntree, inExponentSock, - tex->distance == SHD_VORONOI_MINKOWSKI && tex->dimensions != 1 && - !ELEM(tex->feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS)); - nodeSetSocketAvailability(inSmoothnessSock, tex->feature == SHD_VORONOI_SMOOTH_F1); - nodeSetSocketAvailability(outDistanceSock, tex->feature != SHD_VORONOI_N_SPHERE_RADIUS); - nodeSetSocketAvailability(outColorSock, - tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE && - tex->feature != SHD_VORONOI_N_SPHERE_RADIUS); - nodeSetSocketAvailability(outPositionSock, - tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE && - tex->feature != SHD_VORONOI_N_SPHERE_RADIUS && - tex->dimensions != 1); - nodeSetSocketAvailability(outWSock, - tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE && - tex->feature != SHD_VORONOI_N_SPHERE_RADIUS && - (tex->dimensions == 1 || tex->dimensions == 4)); - nodeSetSocketAvailability(outRadiusSock, tex->feature == SHD_VORONOI_N_SPHERE_RADIUS); + storage.distance == SHD_VORONOI_MINKOWSKI && storage.dimensions != 1 && + !ELEM(storage.feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS)); + nodeSetSocketAvailability(ntree, inSmoothnessSock, storage.feature == SHD_VORONOI_SMOOTH_F1); + + nodeSetSocketAvailability( + ntree, outDistanceSock, storage.feature != SHD_VORONOI_N_SPHERE_RADIUS); + nodeSetSocketAvailability(ntree, + outColorSock, + storage.feature != SHD_VORONOI_DISTANCE_TO_EDGE && + storage.feature != SHD_VORONOI_N_SPHERE_RADIUS); + nodeSetSocketAvailability(ntree, + outPositionSock, + storage.feature != SHD_VORONOI_DISTANCE_TO_EDGE && + storage.feature != SHD_VORONOI_N_SPHERE_RADIUS && + storage.dimensions != 1); + nodeSetSocketAvailability(ntree, + outWSock, + storage.feature != SHD_VORONOI_DISTANCE_TO_EDGE && + storage.feature != SHD_VORONOI_N_SPHERE_RADIUS && + (ELEM(storage.dimensions, 1, 4))); + nodeSetSocketAvailability(ntree, outRadiusSock, storage.feature == SHD_VORONOI_N_SPHERE_RADIUS); +} + +static MultiFunction::ExecutionHints voronoi_execution_hints{50, false}; + +class VoronoiMinowskiFunction : public fn::MultiFunction { + private: + int dimensions_; + int feature_; + + public: + VoronoiMinowskiFunction(int dimensions, int feature) : dimensions_(dimensions), feature_(feature) + { + BLI_assert(dimensions >= 2 && dimensions <= 4); + BLI_assert(feature >= 0 && feature <= 2); + static std::array<fn::MFSignature, 9> signatures{ + create_signature(2, SHD_VORONOI_F1), + create_signature(3, SHD_VORONOI_F1), + create_signature(4, SHD_VORONOI_F1), + + create_signature(2, SHD_VORONOI_F2), + create_signature(3, SHD_VORONOI_F2), + create_signature(4, SHD_VORONOI_F2), + + create_signature(2, SHD_VORONOI_SMOOTH_F1), + create_signature(3, SHD_VORONOI_SMOOTH_F1), + create_signature(4, SHD_VORONOI_SMOOTH_F1), + }; + this->set_signature(&signatures[(dimensions - 1) + feature * 3 - 1]); + } + + static fn::MFSignature create_signature(int dimensions, int feature) + { + fn::MFSignatureBuilder signature{"voronoi_minowski"}; + + if (ELEM(dimensions, 2, 3, 4)) { + signature.single_input<float3>("Vector"); + } + if (ELEM(dimensions, 1, 4)) { + signature.single_input<float>("W"); + } + signature.single_input<float>("Scale"); + if (feature == SHD_VORONOI_SMOOTH_F1) { + signature.single_input<float>("Smoothness"); + } + signature.single_input<float>("Exponent"); + signature.single_input<float>("Randomness"); + signature.single_output<float>("Distance"); + signature.single_output<ColorGeometry4f>("Color"); + + if (dimensions != 1) { + signature.single_output<float3>("Position"); + } + if (ELEM(dimensions, 1, 4)) { + signature.single_output<float>("W"); + } + + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + auto get_vector = [&](int param_index) -> VArray<float3> { + return params.readonly_single_input<float3>(param_index, "Vector"); + }; + auto get_w = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "W"); + }; + auto get_scale = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Scale"); + }; + auto get_smoothness = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Smoothness"); + }; + auto get_exponent = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Exponent"); + }; + auto get_randomness = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Randomness"); + }; + auto get_r_distance = [&](int param_index) -> MutableSpan<float> { + return params.uninitialized_single_output_if_required<float>(param_index, "Distance"); + }; + auto get_r_color = [&](int param_index) -> MutableSpan<ColorGeometry4f> { + return params.uninitialized_single_output_if_required<ColorGeometry4f>(param_index, "Color"); + }; + auto get_r_position = [&](int param_index) -> MutableSpan<float3> { + return params.uninitialized_single_output_if_required<float3>(param_index, "Position"); + }; + auto get_r_w = [&](int param_index) -> MutableSpan<float> { + return params.uninitialized_single_output_if_required<float>(param_index, "W"); + }; + + int param = 0; + switch (dimensions_) { + case 2: { + switch (feature_) { + case SHD_VORONOI_F1: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &exponent = get_exponent(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + float2 pos; + noise::voronoi_f1(float2(vector[i].x, vector[i].y) * scale[i], + exponent[i], + rand, + SHD_VORONOI_MINKOWSKI, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + pos = math::safe_divide(pos, scale[i]); + r_position[i] = float3(pos.x, pos.y, 0.0f); + } + } + break; + } + case SHD_VORONOI_F2: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &exponent = get_exponent(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + float2 pos; + noise::voronoi_f2(float2(vector[i].x, vector[i].y) * scale[i], + exponent[i], + rand, + SHD_VORONOI_MINKOWSKI, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + pos = math::safe_divide(pos, scale[i]); + r_position[i] = float3(pos.x, pos.y, 0.0f); + } + } + break; + } + case SHD_VORONOI_SMOOTH_F1: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &smoothness = get_smoothness(param++); + const VArray<float> &exponent = get_exponent(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + for (int64_t i : mask) { + const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + float2 pos; + noise::voronoi_smooth_f1(float2(vector[i].x, vector[i].y) * scale[i], + smth, + exponent[i], + rand, + SHD_VORONOI_MINKOWSKI, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + pos = math::safe_divide(pos, scale[i]); + r_position[i] = float3(pos.x, pos.y, 0.0f); + } + } + break; + } + } + break; + } + case 3: { + switch (feature_) { + case SHD_VORONOI_F1: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &exponent = get_exponent(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + noise::voronoi_f1(vector[i] * scale[i], + exponent[i], + rand, + SHD_VORONOI_MINKOWSKI, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &r_position[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + r_position[i] = math::safe_divide(r_position[i], scale[i]); + } + } + break; + } + case SHD_VORONOI_F2: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &exponent = get_exponent(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + noise::voronoi_f2(vector[i] * scale[i], + exponent[i], + rand, + SHD_VORONOI_MINKOWSKI, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &r_position[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + r_position[i] = math::safe_divide(r_position[i], scale[i]); + } + } + break; + } + case SHD_VORONOI_SMOOTH_F1: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &smoothness = get_smoothness(param++); + const VArray<float> &exponent = get_exponent(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + for (int64_t i : mask) { + const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + noise::voronoi_smooth_f1(vector[i] * scale[i], + smth, + exponent[i], + rand, + SHD_VORONOI_MINKOWSKI, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &r_position[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + r_position[i] = math::safe_divide(r_position[i], scale[i]); + } + } + break; + } + } + break; + } + case 4: { + switch (feature_) { + case SHD_VORONOI_F1: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &w = get_w(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &exponent = get_exponent(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + MutableSpan<float> r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + const bool calc_w = !r_w.is_empty(); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; + float3 col; + float4 pos; + noise::voronoi_f1(p, + exponent[i], + rand, + SHD_VORONOI_F1, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position || calc_w ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position || calc_w) { + pos = math::safe_divide(pos, scale[i]); + if (calc_position) { + r_position[i] = float3(pos.x, pos.y, pos.z); + } + if (calc_w) { + r_w[i] = pos.w; + } + } + } + break; + } + case SHD_VORONOI_F2: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &w = get_w(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &exponent = get_exponent(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + MutableSpan<float> r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + const bool calc_w = !r_w.is_empty(); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; + float3 col; + float4 pos; + noise::voronoi_f2(p, + exponent[i], + rand, + SHD_VORONOI_MINKOWSKI, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position || calc_w ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position || calc_w) { + pos = math::safe_divide(pos, scale[i]); + if (calc_position) { + r_position[i] = float3(pos.x, pos.y, pos.z); + } + if (calc_w) { + r_w[i] = pos.w; + } + } + } + break; + } + case SHD_VORONOI_SMOOTH_F1: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &w = get_w(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &smoothness = get_smoothness(param++); + const VArray<float> &exponent = get_exponent(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + MutableSpan<float> r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + const bool calc_w = !r_w.is_empty(); + for (int64_t i : mask) { + const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; + float3 col; + float4 pos; + noise::voronoi_smooth_f1(p, + smth, + exponent[i], + rand, + SHD_VORONOI_MINKOWSKI, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position || calc_w ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position || calc_w) { + pos = math::safe_divide(pos, scale[i]); + if (calc_position) { + r_position[i] = float3(pos.x, pos.y, pos.z); + } + if (calc_w) { + r_w[i] = pos.w; + } + } + } + break; + } + } + break; + } + } + } + + ExecutionHints get_execution_hints() const override + { + return voronoi_execution_hints; + } +}; + +class VoronoiMetricFunction : public fn::MultiFunction { + private: + int dimensions_; + int feature_; + int metric_; + + public: + VoronoiMetricFunction(int dimensions, int feature, int metric) + : dimensions_(dimensions), feature_(feature), metric_(metric) + { + BLI_assert(dimensions >= 1 && dimensions <= 4); + BLI_assert(feature >= 0 && feature <= 4); + static std::array<fn::MFSignature, 12> signatures{ + create_signature(1, SHD_VORONOI_F1), + create_signature(2, SHD_VORONOI_F1), + create_signature(3, SHD_VORONOI_F1), + create_signature(4, SHD_VORONOI_F1), + + create_signature(1, SHD_VORONOI_F2), + create_signature(2, SHD_VORONOI_F2), + create_signature(3, SHD_VORONOI_F2), + create_signature(4, SHD_VORONOI_F2), + + create_signature(1, SHD_VORONOI_SMOOTH_F1), + create_signature(2, SHD_VORONOI_SMOOTH_F1), + create_signature(3, SHD_VORONOI_SMOOTH_F1), + create_signature(4, SHD_VORONOI_SMOOTH_F1), + }; + this->set_signature(&signatures[dimensions + feature * 4 - 1]); + } + + static fn::MFSignature create_signature(int dimensions, int feature) + { + fn::MFSignatureBuilder signature{"voronoi_metric"}; + + if (ELEM(dimensions, 2, 3, 4)) { + signature.single_input<float3>("Vector"); + } + if (ELEM(dimensions, 1, 4)) { + signature.single_input<float>("W"); + } + signature.single_input<float>("Scale"); + if (feature == SHD_VORONOI_SMOOTH_F1) { + signature.single_input<float>("Smoothness"); + } + signature.single_input<float>("Randomness"); + signature.single_output<float>("Distance"); + signature.single_output<ColorGeometry4f>("Color"); + + if (dimensions != 1) { + signature.single_output<float3>("Position"); + } + if (ELEM(dimensions, 1, 4)) { + signature.single_output<float>("W"); + } + + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + auto get_vector = [&](int param_index) -> VArray<float3> { + return params.readonly_single_input<float3>(param_index, "Vector"); + }; + auto get_w = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "W"); + }; + auto get_scale = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Scale"); + }; + auto get_smoothness = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Smoothness"); + }; + auto get_randomness = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Randomness"); + }; + auto get_r_distance = [&](int param_index) -> MutableSpan<float> { + return params.uninitialized_single_output_if_required<float>(param_index, "Distance"); + }; + auto get_r_color = [&](int param_index) -> MutableSpan<ColorGeometry4f> { + return params.uninitialized_single_output_if_required<ColorGeometry4f>(param_index, "Color"); + }; + auto get_r_position = [&](int param_index) -> MutableSpan<float3> { + return params.uninitialized_single_output_if_required<float3>(param_index, "Position"); + }; + auto get_r_w = [&](int param_index) -> MutableSpan<float> { + return params.uninitialized_single_output_if_required<float>(param_index, "W"); + }; + + int param = 0; + switch (dimensions_) { + case 1: { + switch (feature_) { + case SHD_VORONOI_F1: { + const VArray<float> &w = get_w(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float> r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_w = !r_w.is_empty(); + for (int64_t i : mask) { + const float p = w[i] * scale[i]; + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + noise::voronoi_f1(p, + rand, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_w ? &r_w[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_w) { + r_w[i] = safe_divide(r_w[i], scale[i]); + } + } + break; + } + case SHD_VORONOI_F2: { + const VArray<float> &w = get_w(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float> r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_w = !r_w.is_empty(); + for (int64_t i : mask) { + const float p = w[i] * scale[i]; + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + noise::voronoi_f2(p, + rand, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_w ? &r_w[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_w) { + r_w[i] = safe_divide(r_w[i], scale[i]); + } + } + break; + } + case SHD_VORONOI_SMOOTH_F1: { + const VArray<float> &w = get_w(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &smoothness = get_smoothness(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float> r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_w = !r_w.is_empty(); + for (int64_t i : mask) { + const float p = w[i] * scale[i]; + const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + noise::voronoi_smooth_f1(p, + smth, + rand, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_w ? &r_w[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_w) { + r_w[i] = safe_divide(r_w[i], scale[i]); + } + } + break; + } + } + break; + } + case 2: { + switch (feature_) { + case SHD_VORONOI_F1: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + float2 pos; + noise::voronoi_f1(float2(vector[i].x, vector[i].y) * scale[i], + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + pos = math::safe_divide(pos, scale[i]); + r_position[i] = float3(pos.x, pos.y, 0.0f); + } + } + break; + } + case SHD_VORONOI_F2: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + float2 pos; + noise::voronoi_f2(float2(vector[i].x, vector[i].y) * scale[i], + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + pos = math::safe_divide(pos, scale[i]); + r_position[i] = float3(pos.x, pos.y, 0.0f); + } + } + break; + } + case SHD_VORONOI_SMOOTH_F1: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &smoothness = get_smoothness(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + for (int64_t i : mask) { + const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + float2 pos; + noise::voronoi_smooth_f1(float2(vector[i].x, vector[i].y) * scale[i], + smth, + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + pos = math::safe_divide(pos, scale[i]); + r_position[i] = float3(pos.x, pos.y, 0.0f); + } + } + break; + } + } + break; + } + case 3: { + switch (feature_) { + case SHD_VORONOI_F1: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + noise::voronoi_f1(vector[i] * scale[i], + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &r_position[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + r_position[i] = math::safe_divide(r_position[i], scale[i]); + } + } + break; + } + case SHD_VORONOI_F2: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + noise::voronoi_f2(vector[i] * scale[i], + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &r_position[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + r_position[i] = math::safe_divide(r_position[i], scale[i]); + } + } + break; + } + case SHD_VORONOI_SMOOTH_F1: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &smoothness = get_smoothness(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + { + for (int64_t i : mask) { + const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + noise::voronoi_smooth_f1(vector[i] * scale[i], + smth, + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &r_position[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + r_position[i] = math::safe_divide(r_position[i], scale[i]); + } + } + } + + break; + } + } + break; + } + case 4: { + switch (feature_) { + case SHD_VORONOI_F1: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &w = get_w(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + MutableSpan<float> r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + const bool calc_w = !r_w.is_empty(); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; + float3 col; + float4 pos; + noise::voronoi_f1(p, + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position || calc_w ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position || calc_w) { + pos = math::safe_divide(pos, scale[i]); + if (calc_position) { + r_position[i] = float3(pos.x, pos.y, pos.z); + } + if (calc_w) { + r_w[i] = pos.w; + } + } + } + break; + } + case SHD_VORONOI_F2: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &w = get_w(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + MutableSpan<float> r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + const bool calc_w = !r_w.is_empty(); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; + float3 col; + float4 pos; + noise::voronoi_f2(p, + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position || calc_w ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position || calc_w) { + pos = math::safe_divide(pos, scale[i]); + if (calc_position) { + r_position[i] = float3(pos.x, pos.y, pos.z); + } + if (calc_w) { + r_w[i] = pos.w; + } + } + } + break; + } + case SHD_VORONOI_SMOOTH_F1: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &w = get_w(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &smoothness = get_smoothness(param++); + const VArray<float> &randomness = get_randomness(param++); + MutableSpan<float> r_distance = get_r_distance(param++); + MutableSpan<ColorGeometry4f> r_color = get_r_color(param++); + MutableSpan<float3> r_position = get_r_position(param++); + MutableSpan<float> r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + const bool calc_w = !r_w.is_empty(); + for (int64_t i : mask) { + const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; + float3 col; + float4 pos; + noise::voronoi_smooth_f1(p, + smth, + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position || calc_w ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position || calc_w) { + pos = math::safe_divide(pos, scale[i]); + if (calc_position) { + r_position[i] = float3(pos.x, pos.y, pos.z); + } + if (calc_w) { + r_w[i] = pos.w; + } + } + } + break; + } + } + break; + } + } + } + + ExecutionHints get_execution_hints() const override + { + return voronoi_execution_hints; + } +}; + +class VoronoiEdgeFunction : public fn::MultiFunction { + private: + int dimensions_; + int feature_; + + public: + VoronoiEdgeFunction(int dimensions, int feature) : dimensions_(dimensions), feature_(feature) + { + BLI_assert(dimensions >= 1 && dimensions <= 4); + BLI_assert(feature >= 3 && feature <= 4); + static std::array<fn::MFSignature, 8> signatures{ + create_signature(1, SHD_VORONOI_DISTANCE_TO_EDGE), + create_signature(2, SHD_VORONOI_DISTANCE_TO_EDGE), + create_signature(3, SHD_VORONOI_DISTANCE_TO_EDGE), + create_signature(4, SHD_VORONOI_DISTANCE_TO_EDGE), + + create_signature(1, SHD_VORONOI_N_SPHERE_RADIUS), + create_signature(2, SHD_VORONOI_N_SPHERE_RADIUS), + create_signature(3, SHD_VORONOI_N_SPHERE_RADIUS), + create_signature(4, SHD_VORONOI_N_SPHERE_RADIUS), + }; + this->set_signature(&signatures[dimensions + (feature - 3) * 4 - 1]); + } + + static fn::MFSignature create_signature(int dimensions, int feature) + { + fn::MFSignatureBuilder signature{"voronoi_edge"}; + + if (ELEM(dimensions, 2, 3, 4)) { + signature.single_input<float3>("Vector"); + } + if (ELEM(dimensions, 1, 4)) { + signature.single_input<float>("W"); + } + signature.single_input<float>("Scale"); + signature.single_input<float>("Randomness"); + + if (feature == SHD_VORONOI_DISTANCE_TO_EDGE) { + signature.single_output<float>("Distance"); + } + if (feature == SHD_VORONOI_N_SPHERE_RADIUS) { + signature.single_output<float>("Radius"); + } + + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + auto get_vector = [&](int param_index) -> VArray<float3> { + return params.readonly_single_input<float3>(param_index, "Vector"); + }; + auto get_w = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "W"); + }; + auto get_scale = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Scale"); + }; + auto get_randomness = [&](int param_index) -> VArray<float> { + return params.readonly_single_input<float>(param_index, "Randomness"); + }; + auto get_r_distance = [&](int param_index) -> MutableSpan<float> { + return params.uninitialized_single_output<float>(param_index, "Distance"); + }; + auto get_r_radius = [&](int param_index) -> MutableSpan<float> { + return params.uninitialized_single_output<float>(param_index, "Radius"); + }; + + int param = 0; + switch (dimensions_) { + case 1: { + const VArray<float> &w = get_w(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &randomness = get_randomness(param++); + switch (feature_) { + case SHD_VORONOI_DISTANCE_TO_EDGE: { + MutableSpan<float> r_distance = get_r_distance(param++); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + const float p = w[i] * scale[i]; + noise::voronoi_distance_to_edge(p, rand, &r_distance[i]); + } + break; + } + case SHD_VORONOI_N_SPHERE_RADIUS: { + MutableSpan<float> r_radius = get_r_radius(param++); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + const float p = w[i] * scale[i]; + noise::voronoi_n_sphere_radius(p, rand, &r_radius[i]); + } + break; + } + } + break; + } + case 2: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &randomness = get_randomness(param++); + switch (feature_) { + case SHD_VORONOI_DISTANCE_TO_EDGE: { + MutableSpan<float> r_distance = get_r_distance(param++); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + const float2 p = float2(vector[i].x, vector[i].y) * scale[i]; + noise::voronoi_distance_to_edge(p, rand, &r_distance[i]); + } + break; + } + case SHD_VORONOI_N_SPHERE_RADIUS: { + MutableSpan<float> r_radius = get_r_radius(param++); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + const float2 p = float2(vector[i].x, vector[i].y) * scale[i]; + noise::voronoi_n_sphere_radius(p, rand, &r_radius[i]); + } + break; + } + } + break; + } + case 3: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &randomness = get_randomness(param++); + switch (feature_) { + case SHD_VORONOI_DISTANCE_TO_EDGE: { + MutableSpan<float> r_distance = get_r_distance(param++); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + noise::voronoi_distance_to_edge(vector[i] * scale[i], rand, &r_distance[i]); + } + break; + } + case SHD_VORONOI_N_SPHERE_RADIUS: { + MutableSpan<float> r_radius = get_r_radius(param++); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + noise::voronoi_n_sphere_radius(vector[i] * scale[i], rand, &r_radius[i]); + } + break; + } + } + break; + } + case 4: { + const VArray<float3> &vector = get_vector(param++); + const VArray<float> &w = get_w(param++); + const VArray<float> &scale = get_scale(param++); + const VArray<float> &randomness = get_randomness(param++); + switch (feature_) { + case SHD_VORONOI_DISTANCE_TO_EDGE: { + MutableSpan<float> r_distance = get_r_distance(param++); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; + noise::voronoi_distance_to_edge(p, rand, &r_distance[i]); + } + break; + } + case SHD_VORONOI_N_SPHERE_RADIUS: { + MutableSpan<float> r_radius = get_r_radius(param++); + for (int64_t i : mask) { + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; + noise::voronoi_n_sphere_radius(p, rand, &r_radius[i]); + } + break; + } + } + break; + } + } + } + + ExecutionHints get_execution_hints() const override + { + return voronoi_execution_hints; + } +}; + +static void sh_node_voronoi_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &builder) +{ + const NodeTexVoronoi &storage = node_storage(builder.node()); + bool minowski = + (storage.distance == SHD_VORONOI_MINKOWSKI && storage.dimensions != 1 && + !ELEM(storage.feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS)); + bool dist_radius = ELEM( + storage.feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS); + if (dist_radius) { + builder.construct_and_set_matching_fn<VoronoiEdgeFunction>(storage.dimensions, + storage.feature); + } + else if (minowski) { + builder.construct_and_set_matching_fn<VoronoiMinowskiFunction>(storage.dimensions, + storage.feature); + } + else { + builder.construct_and_set_matching_fn<VoronoiMetricFunction>( + storage.dimensions, storage.feature, storage.distance); + } } -void register_node_type_sh_tex_voronoi(void) +} // namespace blender::nodes::node_shader_tex_voronoi_cc + +void register_node_type_sh_tex_voronoi() { + namespace file_ns = blender::nodes::node_shader_tex_voronoi_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_VORONOI, "Voronoi Texture", NODE_CLASS_TEXTURE, 0); - ntype.declare = blender::nodes::sh_node_tex_voronoi_declare; - node_type_init(&ntype, node_shader_init_tex_voronoi); + sh_fn_node_type_base(&ntype, SH_NODE_TEX_VORONOI, "Voronoi Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::sh_node_tex_voronoi_declare; + ntype.draw_buttons = file_ns::node_shader_buts_tex_voronoi; + node_type_init(&ntype, file_ns::node_shader_init_tex_voronoi); node_type_storage( &ntype, "NodeTexVoronoi", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_tex_voronoi); - node_type_update(&ntype, node_shader_update_tex_voronoi); + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_voronoi); + node_type_update(&ntype, file_ns::node_shader_update_tex_voronoi); + ntype.build_multi_function = file_ns::sh_node_voronoi_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c deleted file mode 100644 index bba568ed5b7..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -#include "../node_shader_util.h" - -/* **************** WAVE ******************** */ - -static bNodeSocketTemplate sh_node_tex_wave_in[] = { - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, - {SOCK_FLOAT, N_("Distortion"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, - {SOCK_FLOAT, N_("Detail"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 16.0f}, - {SOCK_FLOAT, N_("Detail Scale"), 1.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, - {SOCK_FLOAT, N_("Detail Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Phase Offset"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_tex_wave_out[] = { - {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK}, - {SOCK_FLOAT, - N_("Fac"), - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - PROP_FACTOR, - SOCK_NO_INTERNAL_LINK}, - {-1, ""}, -}; - -static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node) -{ - NodeTexWave *tex = MEM_callocN(sizeof(NodeTexWave), "NodeTexWave"); - BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - BKE_texture_colormapping_default(&tex->base.color_mapping); - tex->wave_type = SHD_WAVE_BANDS; - tex->bands_direction = SHD_WAVE_BANDS_DIRECTION_X; - tex->rings_direction = SHD_WAVE_RINGS_DIRECTION_X; - tex->wave_profile = SHD_WAVE_PROFILE_SIN; - node->storage = tex; -} - -static int node_shader_gpu_tex_wave(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - node_shader_gpu_default_tex_coord(mat, node, &in[0].link); - node_shader_gpu_tex_mapping(mat, node, in, out); - - NodeTexWave *tex = (NodeTexWave *)node->storage; - float wave_type = tex->wave_type; - float bands_direction = tex->bands_direction; - float rings_direction = tex->rings_direction; - float wave_profile = tex->wave_profile; - - return GPU_stack_link(mat, - node, - "node_tex_wave", - in, - out, - GPU_constant(&wave_type), - GPU_constant(&bands_direction), - GPU_constant(&rings_direction), - GPU_constant(&wave_profile)); -} - -/* node type definition */ -void register_node_type_sh_tex_wave(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_TEX_WAVE, "Wave Texture", NODE_CLASS_TEXTURE, 0); - node_type_socket_templates(&ntype, sh_node_tex_wave_in, sh_node_tex_wave_out); - node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, node_shader_init_tex_wave); - node_type_storage(&ntype, "NodeTexWave", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_tex_wave); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc new file mode 100644 index 00000000000..fc6c66061ff --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc @@ -0,0 +1,250 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "node_shader_util.hh" + +#include "BLI_noise.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_tex_wave_cc { + +static void sh_node_tex_wave_declare(NodeDeclarationBuilder &b) +{ + b.is_function_node(); + b.add_input<decl::Vector>(N_("Vector")).implicit_field(); + b.add_input<decl::Float>(N_("Scale")).min(-1000.0f).max(1000.0f).default_value(5.0f); + b.add_input<decl::Float>(N_("Distortion")).min(-1000.0f).max(1000.0f).default_value(0.0f); + b.add_input<decl::Float>(N_("Detail")).min(0.0f).max(15.0f).default_value(2.0f); + b.add_input<decl::Float>(N_("Detail Scale")).min(-1000.0f).max(1000.0f).default_value(1.0f); + b.add_input<decl::Float>(N_("Detail Roughness")) + .min(0.0f) + .max(1.0f) + .default_value(0.5f) + .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Phase Offset")).min(-1000.0f).max(1000.0f).default_value(0.0f); + b.add_output<decl::Color>(N_("Color")).no_muted_links(); + b.add_output<decl::Float>(N_("Fac")).no_muted_links(); +} + +static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "wave_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + int type = RNA_enum_get(ptr, "wave_type"); + if (type == SHD_WAVE_BANDS) { + uiItemR(layout, ptr, "bands_direction", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + } + else { /* SHD_WAVE_RINGS */ + uiItemR(layout, ptr, "rings_direction", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + } + + uiItemR(layout, ptr, "wave_profile", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} + +static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeTexWave *tex = MEM_cnew<NodeTexWave>(__func__); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); + tex->wave_type = SHD_WAVE_BANDS; + tex->bands_direction = SHD_WAVE_BANDS_DIRECTION_X; + tex->rings_direction = SHD_WAVE_RINGS_DIRECTION_X; + tex->wave_profile = SHD_WAVE_PROFILE_SIN; + node->storage = tex; +} + +static int node_shader_gpu_tex_wave(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + node_shader_gpu_default_tex_coord(mat, node, &in[0].link); + node_shader_gpu_tex_mapping(mat, node, in, out); + + NodeTexWave *tex = (NodeTexWave *)node->storage; + float wave_type = tex->wave_type; + float bands_direction = tex->bands_direction; + float rings_direction = tex->rings_direction; + float wave_profile = tex->wave_profile; + + return GPU_stack_link(mat, + node, + "node_tex_wave", + in, + out, + GPU_constant(&wave_type), + GPU_constant(&bands_direction), + GPU_constant(&rings_direction), + GPU_constant(&wave_profile)); +} + +class WaveFunction : public fn::MultiFunction { + private: + int wave_type_; + int bands_direction_; + int rings_direction_; + int wave_profile_; + + public: + WaveFunction(int wave_type, int bands_direction, int rings_direction, int wave_profile) + : wave_type_(wave_type), + bands_direction_(bands_direction), + rings_direction_(rings_direction), + wave_profile_(wave_profile) + { + static fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static fn::MFSignature create_signature() + { + fn::MFSignatureBuilder signature{"MagicFunction"}; + signature.single_input<float3>("Vector"); + signature.single_input<float>("Scale"); + signature.single_input<float>("Distortion"); + signature.single_input<float>("Detail"); + signature.single_input<float>("Detail Scale"); + signature.single_input<float>("Detail Roughness"); + signature.single_input<float>("Phase Offset"); + signature.single_output<ColorGeometry4f>("Color"); + signature.single_output<float>("Fac"); + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); + const VArray<float> &scale = params.readonly_single_input<float>(1, "Scale"); + const VArray<float> &distortion = params.readonly_single_input<float>(2, "Distortion"); + const VArray<float> &detail = params.readonly_single_input<float>(3, "Detail"); + const VArray<float> &dscale = params.readonly_single_input<float>(4, "Detail Scale"); + const VArray<float> &droughness = params.readonly_single_input<float>(5, "Detail Roughness"); + const VArray<float> &phase = params.readonly_single_input<float>(6, "Phase Offset"); + + MutableSpan<ColorGeometry4f> r_color = + params.uninitialized_single_output_if_required<ColorGeometry4f>(7, "Color"); + MutableSpan<float> r_fac = params.uninitialized_single_output<float>(8, "Fac"); + + for (int64_t i : mask) { + + float3 p = vector[i] * scale[i]; + /* Prevent precision issues on unit coordinates. */ + p = (p + 0.000001f) * 0.999999f; + + float n = 0.0f; + float val = 0.0f; + + switch (wave_type_) { + case SHD_WAVE_BANDS: + switch (bands_direction_) { + case SHD_WAVE_BANDS_DIRECTION_X: + n = p.x * 20.0f; + break; + case SHD_WAVE_BANDS_DIRECTION_Y: + n = p.y * 20.0f; + break; + case SHD_WAVE_BANDS_DIRECTION_Z: + n = p.z * 20.0f; + break; + case SHD_WAVE_BANDS_DIRECTION_DIAGONAL: + n = (p.x + p.y + p.z) * 10.0f; + break; + } + break; + case SHD_WAVE_RINGS: + float3 rp = p; + switch (rings_direction_) { + case SHD_WAVE_RINGS_DIRECTION_X: + rp *= float3(0.0f, 1.0f, 1.0f); + break; + case SHD_WAVE_RINGS_DIRECTION_Y: + rp *= float3(1.0f, 0.0f, 1.0f); + break; + case SHD_WAVE_RINGS_DIRECTION_Z: + rp *= float3(1.0f, 1.0f, 0.0f); + break; + case SHD_WAVE_RINGS_DIRECTION_SPHERICAL: + /* Ignore. */ + break; + } + n = len_v3(rp) * 20.0f; + break; + } + + n += phase[i]; + + if (distortion[i] != 0.0f) { + n += distortion[i] * + (noise::perlin_fractal(p * dscale[i], detail[i], droughness[i]) * 2.0f - 1.0f); + } + + switch (wave_profile_) { + case SHD_WAVE_PROFILE_SIN: + val = 0.5f + 0.5f * sinf(n - M_PI_2); + break; + case SHD_WAVE_PROFILE_SAW: + n /= M_PI * 2.0f; + val = n - floorf(n); + break; + case SHD_WAVE_PROFILE_TRI: + n /= M_PI * 2.0f; + val = fabsf(n - floorf(n + 0.5f)) * 2.0f; + break; + } + + r_fac[i] = val; + } + if (!r_color.is_empty()) { + for (int64_t i : mask) { + r_color[i] = ColorGeometry4f(r_fac[i], r_fac[i], r_fac[i], 1.0f); + } + } + } +}; + +static void sh_node_wave_tex_build_multi_function( + blender::nodes::NodeMultiFunctionBuilder &builder) +{ + bNode &node = builder.node(); + NodeTexWave *tex = (NodeTexWave *)node.storage; + builder.construct_and_set_matching_fn<WaveFunction>( + tex->wave_type, tex->bands_direction, tex->rings_direction, tex->wave_profile); +} + +} // namespace blender::nodes::node_shader_tex_wave_cc + +void register_node_type_sh_tex_wave() +{ + namespace file_ns = blender::nodes::node_shader_tex_wave_cc; + + static bNodeType ntype; + + sh_fn_node_type_base(&ntype, SH_NODE_TEX_WAVE, "Wave Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::sh_node_tex_wave_declare; + ntype.draw_buttons = file_ns::node_shader_buts_tex_wave; + node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); + node_type_init(&ntype, file_ns::node_shader_init_tex_wave); + node_type_storage(&ntype, "NodeTexWave", node_free_standard_storage, node_copy_standard_storage); + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_wave); + ntype.build_multi_function = file_ns::sh_node_wave_tex_build_multi_function; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc index 03543e5f7fe..3a5bc98896c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc @@ -17,20 +17,31 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -namespace blender::nodes { +#include "BLI_noise.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_tex_white_noise_cc { static void sh_node_tex_white_noise_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>("Vector").min(-10000.0f).max(10000.0f); - b.add_input<decl::Float>("W").min(-10000.0f).max(10000.0f); - b.add_output<decl::Float>("Value"); - b.add_output<decl::Color>("Color"); -}; + b.add_input<decl::Vector>(N_("Vector")).min(-10000.0f).max(10000.0f).implicit_field(); + b.add_input<decl::Float>(N_("W")).min(-10000.0f).max(10000.0f).make_available([](bNode &node) { + /* Default to 1 instead of 4, because it is faster. */ + node.custom1 = 1; + }); + b.add_output<decl::Float>(N_("Value")); + b.add_output<decl::Color>(N_("Color")); +} -} // namespace blender::nodes +static void node_shader_buts_white_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "noise_dimensions", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} static void node_shader_init_tex_white_noise(bNodeTree *UNUSED(ntree), bNode *node) { @@ -56,24 +67,150 @@ static int gpu_shader_tex_white_noise(GPUMaterial *mat, return GPU_stack_link(mat, node, name, in, out); } -static void node_shader_update_tex_white_noise(bNodeTree *UNUSED(ntree), bNode *node) +static void node_shader_update_tex_white_noise(bNodeTree *ntree, bNode *node) { bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector"); bNodeSocket *sockW = nodeFindSocket(node, SOCK_IN, "W"); - nodeSetSocketAvailability(sockVector, node->custom1 != 1); - nodeSetSocketAvailability(sockW, node->custom1 == 1 || node->custom1 == 4); + nodeSetSocketAvailability(ntree, sockVector, node->custom1 != 1); + nodeSetSocketAvailability(ntree, sockW, node->custom1 == 1 || node->custom1 == 4); +} + +class WhiteNoiseFunction : public fn::MultiFunction { + private: + int dimensions_; + + public: + WhiteNoiseFunction(int dimensions) : dimensions_(dimensions) + { + BLI_assert(dimensions >= 1 && dimensions <= 4); + static std::array<fn::MFSignature, 4> signatures{ + create_signature(1), + create_signature(2), + create_signature(3), + create_signature(4), + }; + this->set_signature(&signatures[dimensions - 1]); + } + + static fn::MFSignature create_signature(int dimensions) + { + fn::MFSignatureBuilder signature{"WhiteNoise"}; + + if (ELEM(dimensions, 2, 3, 4)) { + signature.single_input<float3>("Vector"); + } + if (ELEM(dimensions, 1, 4)) { + signature.single_input<float>("W"); + } + + signature.single_output<float>("Value"); + signature.single_output<ColorGeometry4f>("Color"); + + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + int param = ELEM(dimensions_, 2, 3, 4) + ELEM(dimensions_, 1, 4); + + MutableSpan<float> r_value = params.uninitialized_single_output_if_required<float>(param++, + "Value"); + MutableSpan<ColorGeometry4f> r_color = + params.uninitialized_single_output_if_required<ColorGeometry4f>(param++, "Color"); + + const bool compute_value = !r_value.is_empty(); + const bool compute_color = !r_color.is_empty(); + + switch (dimensions_) { + case 1: { + const VArray<float> &w = params.readonly_single_input<float>(0, "W"); + if (compute_color) { + for (int64_t i : mask) { + const float3 c = noise::hash_float_to_float3(w[i]); + r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f); + } + } + if (compute_value) { + for (int64_t i : mask) { + r_value[i] = noise::hash_float_to_float(w[i]); + } + } + break; + } + case 2: { + const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); + if (compute_color) { + for (int64_t i : mask) { + const float3 c = noise::hash_float_to_float3(float2(vector[i].x, vector[i].y)); + r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f); + } + } + if (compute_value) { + for (int64_t i : mask) { + r_value[i] = noise::hash_float_to_float(float2(vector[i].x, vector[i].y)); + } + } + break; + } + case 3: { + const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); + if (compute_color) { + for (int64_t i : mask) { + const float3 c = noise::hash_float_to_float3(vector[i]); + r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f); + } + } + if (compute_value) { + for (int64_t i : mask) { + r_value[i] = noise::hash_float_to_float(vector[i]); + } + } + break; + } + case 4: { + const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); + const VArray<float> &w = params.readonly_single_input<float>(1, "W"); + if (compute_color) { + for (int64_t i : mask) { + const float3 c = noise::hash_float_to_float3( + float4(vector[i].x, vector[i].y, vector[i].z, w[i])); + r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f); + } + } + if (compute_value) { + for (int64_t i : mask) { + r_value[i] = noise::hash_float_to_float( + float4(vector[i].x, vector[i].y, vector[i].z, w[i])); + } + } + break; + } + } + } +}; + +static void sh_node_noise_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &builder) +{ + bNode &node = builder.node(); + builder.construct_and_set_matching_fn<WhiteNoiseFunction>((int)node.custom1); } -void register_node_type_sh_tex_white_noise(void) +} // namespace blender::nodes::node_shader_tex_white_noise_cc + +void register_node_type_sh_tex_white_noise() { + namespace file_ns = blender::nodes::node_shader_tex_white_noise_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_WHITE_NOISE, "White Noise Texture", NODE_CLASS_TEXTURE, 0); - ntype.declare = blender::nodes::sh_node_tex_white_noise_declare; - node_type_init(&ntype, node_shader_init_tex_white_noise); - node_type_gpu(&ntype, gpu_shader_tex_white_noise); - node_type_update(&ntype, node_shader_update_tex_white_noise); + sh_fn_node_type_base(&ntype, SH_NODE_TEX_WHITE_NOISE, "White Noise Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::sh_node_tex_white_noise_declare; + ntype.draw_buttons = file_ns::node_shader_buts_white_noise; + node_type_init(&ntype, file_ns::node_shader_init_tex_white_noise); + node_type_gpu(&ntype, file_ns::gpu_shader_tex_white_noise); + node_type_update(&ntype, file_ns::node_shader_update_tex_white_noise); + ntype.build_multi_function = file_ns::sh_node_noise_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c b/source/blender/nodes/shader/nodes/node_shader_uv_along_stroke.cc index 05c3248af65..382a0f16ecd 100644 --- a/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c +++ b/source/blender/nodes/shader/nodes/node_shader_uv_along_stroke.cc @@ -17,23 +17,35 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +#include "UI_interface.h" +#include "UI_resources.h" -static bNodeSocketTemplate sh_node_uvalongstroke_out[] = { - {SOCK_VECTOR, N_("UV"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_uv_along_stroke_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Vector>(N_("UV")); +} + +static void node_shader_buts_uvalongstroke(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "use_tips", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, 0); +} + +} // namespace blender::nodes::node_shader_uv_along_stroke_cc /* node type definition */ -void register_node_type_sh_uvalongstroke(void) +void register_node_type_sh_uvalongstroke() { + namespace file_ns = blender::nodes::node_shader_uv_along_stroke_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_UVALONGSTROKE, "UV Along Stroke", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, sh_node_uvalongstroke_out); - node_type_init(&ntype, NULL); + sh_node_type_base(&ntype, SH_NODE_UVALONGSTROKE, "UV Along Stroke", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_uvalongstroke; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_uvmap.c b/source/blender/nodes/shader/nodes/node_shader_uvmap.cc index 775b8ffbc06..b004be75188 100644 --- a/source/blender/nodes/shader/nodes/node_shader_uvmap.c +++ b/source/blender/nodes/shader/nodes/node_shader_uvmap.cc @@ -17,20 +17,39 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" + +#include "BKE_context.h" #include "DNA_customdata_types.h" -/* **************** OUTPUT ******************** */ +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_uvmap_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Vector>(N_("UV")); +} -static bNodeSocketTemplate sh_node_uvmap_out[] = { - {SOCK_VECTOR, N_("UV"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +static void node_shader_buts_uvmap(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiItemR(layout, ptr, "from_instancer", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, 0); + + if (!RNA_boolean_get(ptr, "from_instancer")) { + PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); + + if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { + PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); + uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); + } + } +} static void node_shader_init_uvmap(bNodeTree *UNUSED(ntree), bNode *node) { - NodeShaderUVMap *attr = MEM_callocN(sizeof(NodeShaderUVMap), "NodeShaderUVMap"); + NodeShaderUVMap *attr = MEM_cnew<NodeShaderUVMap>("NodeShaderUVMap"); node->storage = attr; } @@ -40,7 +59,7 @@ static int node_shader_gpu_uvmap(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - NodeShaderUVMap *attr = node->storage; + NodeShaderUVMap *attr = static_cast<NodeShaderUVMap *>(node->storage); GPUNodeLink *mtface = GPU_attribute(mat, CD_MTFACE, attr->uv_map); GPU_stack_link(mat, node, "node_uvmap", in, out, mtface); @@ -50,18 +69,23 @@ static int node_shader_gpu_uvmap(GPUMaterial *mat, return 1; } +} // namespace blender::nodes::node_shader_uvmap_cc + /* node type definition */ -void register_node_type_sh_uvmap(void) +void register_node_type_sh_uvmap() { + namespace file_ns = blender::nodes::node_shader_uvmap_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_UVMAP, "UV Map", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, sh_node_uvmap_out); + sh_node_type_base(&ntype, SH_NODE_UVMAP, "UV Map", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_uvmap; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, node_shader_init_uvmap); + node_type_init(&ntype, file_ns::node_shader_init_uvmap); node_type_storage( &ntype, "NodeShaderUVMap", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_uvmap); + node_type_gpu(&ntype, file_ns::node_shader_gpu_uvmap); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_value.cc b/source/blender/nodes/shader/nodes/node_shader_value.cc index 1344ce5c5d9..265f03e6e88 100644 --- a/source/blender/nodes/shader/nodes/node_shader_value.cc +++ b/source/blender/nodes/shader/nodes/node_shader_value.cc @@ -21,16 +21,14 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include "node_shader_util.hh" -namespace blender::nodes { +namespace blender::nodes::node_shader_value_cc { static void sh_node_value_declare(NodeDeclarationBuilder &b) { - b.add_output<decl::Float>("Value"); -}; - -} // namespace blender::nodes + b.add_output<decl::Float>(N_("Value")); +} static int gpu_shader_value(GPUMaterial *mat, bNode *node, @@ -49,14 +47,18 @@ static void sh_node_value_build_multi_function(blender::nodes::NodeMultiFunction builder.construct_and_set_matching_fn<blender::fn::CustomMF_Constant<float>>(value->value); } -void register_node_type_sh_value(void) +} // namespace blender::nodes::node_shader_value_cc + +void register_node_type_sh_value() { + namespace file_ns = blender::nodes::node_shader_value_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_VALUE, "Value", NODE_CLASS_INPUT, 0); - ntype.declare = blender::nodes::sh_node_value_declare; - node_type_gpu(&ntype, gpu_shader_value); - ntype.build_multi_function = sh_node_value_build_multi_function; + sh_fn_node_type_base(&ntype, SH_NODE_VALUE, "Value", NODE_CLASS_INPUT); + ntype.declare = file_ns::sh_node_value_declare; + node_type_gpu(&ntype, file_ns::gpu_shader_value); + ntype.build_multi_function = file_ns::sh_node_value_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.cc index 2b69e781e30..d34ef29c30a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c +++ b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.cc @@ -17,21 +17,17 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_vector_displacement_cc { -static bNodeSocketTemplate sh_node_vector_displacement_in[] = { - {SOCK_RGBA, N_("Vector"), 0.00f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_FLOAT, N_("Midlevel"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_FLOAT, N_("Scale"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_vector_displacement_out[] = { - {SOCK_VECTOR, N_("Displacement"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Vector")).hide_value(); + b.add_input<decl::Float>(N_("Midlevel")).default_value(0.0f).min(0.0f).max(1000.0f); + b.add_input<decl::Float>(N_("Scale")).default_value(1.0f).min(0.0f).max(1000.0f); + b.add_output<decl::Vector>(N_("Displacement")); +} static void node_shader_init_vector_displacement(bNodeTree *UNUSED(ntree), bNode *node) { @@ -60,18 +56,20 @@ static int gpu_shader_vector_displacement(GPUMaterial *mat, } } +} // namespace blender::nodes::node_shader_vector_displacement_cc + /* node type definition */ -void register_node_type_sh_vector_displacement(void) +void register_node_type_sh_vector_displacement() { + namespace file_ns = blender::nodes::node_shader_vector_displacement_cc; + static bNodeType ntype; sh_node_type_base( - &ntype, SH_NODE_VECTOR_DISPLACEMENT, "Vector Displacement", NODE_CLASS_OP_VECTOR, 0); - node_type_socket_templates( - &ntype, sh_node_vector_displacement_in, sh_node_vector_displacement_out); - node_type_storage(&ntype, "", NULL, NULL); - node_type_init(&ntype, node_shader_init_vector_displacement); - node_type_gpu(&ntype, gpu_shader_vector_displacement); + &ntype, SH_NODE_VECTOR_DISPLACEMENT, "Vector Displacement", NODE_CLASS_OP_VECTOR); + ntype.declare = file_ns::node_declare; + node_type_init(&ntype, file_ns::node_shader_init_vector_displacement); + node_type_gpu(&ntype, file_ns::gpu_shader_vector_displacement); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc index f49ff06cef1..591734c7dd6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc @@ -21,24 +21,74 @@ * \ingroup shdnodes */ -#include "node_shader_util.h" +#include "node_shader_util.hh" #include "NOD_math_functions.hh" +#include "NOD_socket_search_link.hh" -namespace blender::nodes { +#include "RNA_enum_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_vector_math_cc { static void sh_node_vector_math_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>("Vector").min(-10000.0f).max(10000.0f); - b.add_input<decl::Vector>("Vector", "Vector_001").min(-10000.0f).max(10000.0f); - b.add_input<decl::Vector>("Vector", "Vector_002").min(-10000.0f).max(10000.0f); - b.add_input<decl::Float>("Scale").default_value(1.0f).min(-10000.0f).max(10000.0f); - b.add_output<decl::Vector>("Vector"); - b.add_output<decl::Float>("Value"); + b.add_input<decl::Vector>(N_("Vector")).min(-10000.0f).max(10000.0f); + b.add_input<decl::Vector>(N_("Vector"), "Vector_001").min(-10000.0f).max(10000.0f); + b.add_input<decl::Vector>(N_("Vector"), "Vector_002").min(-10000.0f).max(10000.0f); + b.add_input<decl::Float>(N_("Scale")).default_value(1.0f).min(-10000.0f).max(10000.0f); + b.add_output<decl::Vector>(N_("Vector")); + b.add_output<decl::Float>(N_("Value")); +} + +static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "operation", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} + +class SocketSearchOp { + public: + std::string socket_name; + NodeVectorMathOperation mode = NODE_VECTOR_MATH_ADD; + void operator()(LinkSearchOpParams ¶ms) + { + bNode &node = params.add_node("ShaderNodeVectorMath"); + node.custom1 = mode; + params.update_and_connect_available_socket(node, socket_name); + } }; -} // namespace blender::nodes +static void sh_node_vector_math_gather_link_searches(GatherLinkSearchOpParams ¶ms) +{ + if (!params.node_tree().typeinfo->validate_link( + static_cast<eNodeSocketDatatype>(params.other_socket().type), SOCK_VECTOR)) { + return; + } + + const int weight = ELEM(params.other_socket().type, SOCK_VECTOR, SOCK_RGBA) ? 0 : -1; + + for (const EnumPropertyItem *item = rna_enum_node_vec_math_items; item->identifier != nullptr; + item++) { + if (item->name != nullptr && item->identifier[0] != '\0') { + if ((params.in_out() == SOCK_OUT) && ELEM(item->value, + NODE_VECTOR_MATH_LENGTH, + NODE_VECTOR_MATH_DISTANCE, + NODE_VECTOR_MATH_DOT_PRODUCT)) { + params.add_item(IFACE_(item->name), + SocketSearchOp{"Value", (NodeVectorMathOperation)item->value}, + weight); + } + else { + params.add_item(IFACE_(item->name), + SocketSearchOp{"Vector", (NodeVectorMathOperation)item->value}, + weight); + } + } + } +} static const char *gpu_shader_get_name(int mode) { @@ -119,7 +169,7 @@ static int gpu_shader_vector_math(GPUMaterial *mat, return 0; } -static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node) +static void node_shader_update_vector_math(bNodeTree *ntree, bNode *node) { bNodeSocket *sockB = (bNodeSocket *)BLI_findlink(&node->inputs, 1); bNodeSocket *sockC = (bNodeSocket *)BLI_findlink(&node->inputs, 2); @@ -128,7 +178,8 @@ static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node bNodeSocket *sockVector = nodeFindSocket(node, SOCK_OUT, "Vector"); bNodeSocket *sockValue = nodeFindSocket(node, SOCK_OUT, "Value"); - nodeSetSocketAvailability(sockB, + nodeSetSocketAvailability(ntree, + sockB, !ELEM(node->custom1, NODE_VECTOR_MATH_SINE, NODE_VECTOR_MATH_COSINE, @@ -140,19 +191,22 @@ static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node NODE_VECTOR_MATH_ABSOLUTE, NODE_VECTOR_MATH_FRACTION, NODE_VECTOR_MATH_NORMALIZE)); - nodeSetSocketAvailability(sockC, + nodeSetSocketAvailability(ntree, + sockC, ELEM(node->custom1, NODE_VECTOR_MATH_WRAP, NODE_VECTOR_MATH_FACEFORWARD, NODE_VECTOR_MATH_MULTIPLY_ADD)); - nodeSetSocketAvailability(sockScale, - ELEM(node->custom1, NODE_VECTOR_MATH_SCALE, NODE_VECTOR_MATH_REFRACT)); - nodeSetSocketAvailability(sockVector, + nodeSetSocketAvailability( + ntree, sockScale, ELEM(node->custom1, NODE_VECTOR_MATH_SCALE, NODE_VECTOR_MATH_REFRACT)); + nodeSetSocketAvailability(ntree, + sockVector, !ELEM(node->custom1, NODE_VECTOR_MATH_LENGTH, NODE_VECTOR_MATH_DISTANCE, NODE_VECTOR_MATH_DOT_PRODUCT)); - nodeSetSocketAvailability(sockValue, + nodeSetSocketAvailability(ntree, + sockValue, ELEM(node->custom1, NODE_VECTOR_MATH_LENGTH, NODE_VECTOR_MATH_DISTANCE, @@ -197,8 +251,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_fl3_to_fl3( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{info.title_case_name, - function}; + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{ + info.title_case_name.c_str(), function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -208,7 +262,7 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_fl3_fl3_to_fl3( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{ - info.title_case_name, function}; + info.title_case_name.c_str(), function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -218,7 +272,7 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_fl3_fl_to_fl3( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{ - info.title_case_name, function}; + info.title_case_name.c_str(), function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -227,8 +281,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_fl3_to_fl( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{info.title_case_name, - function}; + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{ + info.title_case_name.c_str(), function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -237,8 +291,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_fl_to_fl3( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SI_SO<float3, float, float3> fn{info.title_case_name, - function}; + static blender::fn::CustomMF_SI_SI_SO<float3, float, float3> fn{ + info.title_case_name.c_str(), function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -247,7 +301,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_to_fl3( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SO<float3, float3> fn{info.title_case_name, function}; + static blender::fn::CustomMF_SI_SO<float3, float3> fn{info.title_case_name.c_str(), + function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -256,7 +311,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_to_fl( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SO<float3, float> fn{info.title_case_name, function}; + static blender::fn::CustomMF_SI_SO<float3, float> fn{info.title_case_name.c_str(), + function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -273,16 +329,22 @@ static void sh_node_vector_math_build_multi_function( builder.set_matching_fn(fn); } -void register_node_type_sh_vect_math(void) +} // namespace blender::nodes::node_shader_vector_math_cc + +void register_node_type_sh_vect_math() { + namespace file_ns = blender::nodes::node_shader_vector_math_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_OP_VECTOR, 0); - ntype.declare = blender::nodes::sh_node_vector_math_declare; - node_type_label(&ntype, node_vector_math_label); - node_type_gpu(&ntype, gpu_shader_vector_math); - node_type_update(&ntype, node_shader_update_vector_math); - ntype.build_multi_function = sh_node_vector_math_build_multi_function; + sh_fn_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_OP_VECTOR); + ntype.declare = file_ns::sh_node_vector_math_declare; + ntype.draw_buttons = file_ns::node_shader_buts_vect_math; + ntype.labelfunc = node_vector_math_label; + node_type_gpu(&ntype, file_ns::gpu_shader_vector_math); + node_type_update(&ntype, file_ns::node_shader_update_vector_math); + ntype.build_multi_function = file_ns::sh_node_vector_math_build_multi_function; + ntype.gather_link_search_ops = file_ns::sh_node_vector_math_gather_link_searches; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc index c9b26fa5199..d8dcd028c56 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc @@ -21,22 +21,29 @@ * \ingroup shdnodes */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -namespace blender::nodes { +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_vector_rotate_cc { static void sh_node_vector_rotate_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>("Vector").min(0.0f).max(1.0f).hide_value(); - b.add_input<decl::Vector>("Center"); - b.add_input<decl::Vector>("Axis").min(-1.0f).max(1.0f).default_value({0.0f, 0.0f, 1.0f}); - b.add_input<decl::Float>("Angle").subtype(PROP_ANGLE); - b.add_input<decl::Vector>("Rotation").subtype(PROP_EULER); - b.add_output<decl::Vector>("Vector"); -}; + b.add_input<decl::Vector>(N_("Vector")).min(0.0f).max(1.0f).hide_value(); + b.add_input<decl::Vector>(N_("Center")); + b.add_input<decl::Vector>(N_("Axis")).min(-1.0f).max(1.0f).default_value({0.0f, 0.0f, 1.0f}); + b.add_input<decl::Float>(N_("Angle")).subtype(PROP_ANGLE); + b.add_input<decl::Vector>(N_("Rotation")).subtype(PROP_EULER); + b.add_output<decl::Vector>(N_("Vector")); +} -} // namespace blender::nodes +static void node_shader_buts_vector_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "rotation_type", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); + uiItemR(layout, ptr, "invert", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, 0); +} static const char *gpu_shader_get_name(int mode) { @@ -193,25 +200,32 @@ static void sh_node_vector_rotate_build_multi_function( builder.set_matching_fn(fn); } -static void node_shader_update_vector_rotate(bNodeTree *UNUSED(ntree), bNode *node) +static void node_shader_update_vector_rotate(bNodeTree *ntree, bNode *node) { bNodeSocket *sock_rotation = nodeFindSocket(node, SOCK_IN, "Rotation"); - nodeSetSocketAvailability(sock_rotation, ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ)); + nodeSetSocketAvailability( + ntree, sock_rotation, ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ)); bNodeSocket *sock_axis = nodeFindSocket(node, SOCK_IN, "Axis"); - nodeSetSocketAvailability(sock_axis, ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_AXIS)); + nodeSetSocketAvailability(ntree, sock_axis, ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_AXIS)); bNodeSocket *sock_angle = nodeFindSocket(node, SOCK_IN, "Angle"); - nodeSetSocketAvailability(sock_angle, !ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ)); + nodeSetSocketAvailability( + ntree, sock_angle, !ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ)); } -void register_node_type_sh_vector_rotate(void) +} // namespace blender::nodes::node_shader_vector_rotate_cc + +void register_node_type_sh_vector_rotate() { + namespace file_ns = blender::nodes::node_shader_vector_rotate_cc; + static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_VECTOR_ROTATE, "Vector Rotate", NODE_CLASS_OP_VECTOR, 0); - ntype.declare = blender::nodes::sh_node_vector_rotate_declare; - node_type_gpu(&ntype, gpu_shader_vector_rotate); - node_type_update(&ntype, node_shader_update_vector_rotate); - ntype.build_multi_function = sh_node_vector_rotate_build_multi_function; + sh_fn_node_type_base(&ntype, SH_NODE_VECTOR_ROTATE, "Vector Rotate", NODE_CLASS_OP_VECTOR); + ntype.declare = file_ns::sh_node_vector_rotate_declare; + ntype.draw_buttons = file_ns::node_shader_buts_vector_rotate; + node_type_gpu(&ntype, file_ns::gpu_shader_vector_rotate); + node_type_update(&ntype, file_ns::node_shader_update_vector_rotate); + ntype.build_multi_function = file_ns::sh_node_vector_rotate_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c b/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc index 41e61da60d7..a8a6902e30c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c +++ b/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc @@ -21,23 +21,37 @@ * \ingroup shdnodes */ -#include "BLI_string.h" +#include "node_shader_util.hh" -#include "../node_shader_util.h" +#include "UI_interface.h" +#include "UI_resources.h" -/* **************** Vector Transform ******************** */ -static bNodeSocketTemplate sh_node_vect_transform_in[] = { - {SOCK_VECTOR, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, {-1, ""}}; +namespace blender::nodes::node_shader_vector_transform_cc { -static bNodeSocketTemplate sh_node_vect_transform_out[] = { - {SOCK_VECTOR, N_("Vector")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Vector>(N_("Vector")) + .default_value({0.5f, 0.5f, 0.5f}) + .min(-10000.0f) + .max(10000.0f); + b.add_output<decl::Vector>(N_("Vector")); +} + +static void node_shader_buts_vect_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, + ptr, + "vector_type", + UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_EXPAND, + nullptr, + ICON_NONE); + uiItemR(layout, ptr, "convert_from", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + uiItemR(layout, ptr, "convert_to", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); +} static void node_shader_init_vect_transform(bNodeTree *UNUSED(ntree), bNode *node) { - NodeShaderVectTransform *vect = MEM_callocN(sizeof(NodeShaderVectTransform), - "NodeShaderVectTransform"); + NodeShaderVectTransform *vect = MEM_cnew<NodeShaderVectTransform>("NodeShaderVectTransform"); /* Convert World into Object Space per default */ vect->convert_to = 1; @@ -45,52 +59,42 @@ static void node_shader_init_vect_transform(bNodeTree *UNUSED(ntree), bNode *nod node->storage = vect; } -static void node_shader_exec_vect_transform(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **UNUSED(in), - bNodeStack **UNUSED(out)) -{ -} - -static const char *get_gpufn_name_from_to(short from, short to) +static GPUNodeLink *get_gpulink_matrix_from_to(short from, short to) { switch (from) { case SHD_VECT_TRANSFORM_SPACE_OBJECT: switch (to) { case SHD_VECT_TRANSFORM_SPACE_OBJECT: - return NULL; + return nullptr; case SHD_VECT_TRANSFORM_SPACE_WORLD: - return "object_to_world"; + return GPU_builtin(GPU_OBJECT_MATRIX); case SHD_VECT_TRANSFORM_SPACE_CAMERA: - return "object_to_view"; + return GPU_builtin(GPU_LOC_TO_VIEW_MATRIX); } break; case SHD_VECT_TRANSFORM_SPACE_WORLD: switch (to) { case SHD_VECT_TRANSFORM_SPACE_WORLD: - return NULL; + return nullptr; case SHD_VECT_TRANSFORM_SPACE_CAMERA: - return "world_to_view"; + return GPU_builtin(GPU_VIEW_MATRIX); case SHD_VECT_TRANSFORM_SPACE_OBJECT: - return "world_to_object"; + return GPU_builtin(GPU_INVERSE_OBJECT_MATRIX); } break; case SHD_VECT_TRANSFORM_SPACE_CAMERA: switch (to) { case SHD_VECT_TRANSFORM_SPACE_CAMERA: - return NULL; + return nullptr; case SHD_VECT_TRANSFORM_SPACE_WORLD: - return "view_to_world"; + return GPU_builtin(GPU_INVERSE_VIEW_MATRIX); case SHD_VECT_TRANSFORM_SPACE_OBJECT: - return "view_to_object"; + return GPU_builtin(GPU_INVERSE_LOC_TO_VIEW_MATRIX); } break; } - return NULL; + return nullptr; } - static int gpu_shader_vect_transform(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), @@ -98,6 +102,11 @@ static int gpu_shader_vect_transform(GPUMaterial *mat, GPUNodeStack *out) { struct GPUNodeLink *inputlink; + struct GPUNodeLink *fromto; + + const char *vtransform = "direction_transform_m4v3"; + const char *ptransform = "point_transform_m4v3"; + const char *func_name = nullptr; NodeShaderVectTransform *nodeprop = (NodeShaderVectTransform *)node->storage; @@ -108,10 +117,9 @@ static int gpu_shader_vect_transform(GPUMaterial *mat, inputlink = GPU_constant(in[0].vec); } - const char *xform = (nodeprop->type == SHD_VECT_TRANSFORM_TYPE_POINT) ? "point_transform_" : - "direction_transform_"; - const char *fromto = get_gpufn_name_from_to(nodeprop->convert_from, nodeprop->convert_to); + fromto = get_gpulink_matrix_from_to(nodeprop->convert_from, nodeprop->convert_to); + func_name = (nodeprop->type == SHD_VECT_TRANSFORM_TYPE_POINT) ? ptransform : vtransform; if (fromto) { /* For cycles we have inverted Z */ /* TODO: pass here the correct matrices */ @@ -119,11 +127,7 @@ static int gpu_shader_vect_transform(GPUMaterial *mat, nodeprop->convert_to != SHD_VECT_TRANSFORM_SPACE_CAMERA) { GPU_link(mat, "invert_z", inputlink, &inputlink); } - - char func_name[48]; - SNPRINTF(func_name, "%s%s", xform, fromto); - GPU_link(mat, func_name, inputlink, &out[0].link); - + GPU_link(mat, func_name, inputlink, fromto, &out[0].link); if (nodeprop->convert_to == SHD_VECT_TRANSFORM_SPACE_CAMERA && nodeprop->convert_from != SHD_VECT_TRANSFORM_SPACE_CAMERA) { GPU_link(mat, "invert_z", out[0].link, &out[0].link); @@ -140,17 +144,21 @@ static int gpu_shader_vect_transform(GPUMaterial *mat, return true; } -void register_node_type_sh_vect_transform(void) +} // namespace blender::nodes::node_shader_vector_transform_cc + +void register_node_type_sh_vect_transform() { + namespace file_ns = blender::nodes::node_shader_vector_transform_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_VECT_TRANSFORM, "Vector Transform", NODE_CLASS_OP_VECTOR, 0); - node_type_init(&ntype, node_shader_init_vect_transform); - node_type_socket_templates(&ntype, sh_node_vect_transform_in, sh_node_vect_transform_out); + sh_node_type_base(&ntype, SH_NODE_VECT_TRANSFORM, "Vector Transform", NODE_CLASS_OP_VECTOR); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_vect_transform; + node_type_init(&ntype, file_ns::node_shader_init_vect_transform); node_type_storage( &ntype, "NodeShaderVectTransform", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_vect_transform); - node_type_gpu(&ntype, gpu_shader_vect_transform); + node_type_gpu(&ntype, file_ns::gpu_shader_vect_transform); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c b/source/blender/nodes/shader/nodes/node_shader_vertex_color.cc index 40576b68dd5..6501527ef5d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c +++ b/source/blender/nodes/shader/nodes/node_shader_vertex_color.cc @@ -17,18 +17,44 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -static bNodeSocketTemplate sh_node_vertex_color_out[] = { - {SOCK_RGBA, N_("Color")}, - {SOCK_FLOAT, N_("Alpha")}, - {-1, ""}, -}; +#include "BKE_context.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_shader_vertex_color_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Color>(N_("Color")); + b.add_output<decl::Float>(N_("Alpha")); +} + +static void node_shader_buts_vertex_color(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); + if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { + PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); + + if (U.experimental.use_sculpt_vertex_colors && + RNA_collection_length(&dataptr, "sculpt_vertex_colors")) { + uiItemPointerR( + layout, ptr, "layer_name", &dataptr, "sculpt_vertex_colors", "", ICON_GROUP_VCOL); + } + else { + uiItemPointerR(layout, ptr, "layer_name", &dataptr, "vertex_colors", "", ICON_GROUP_VCOL); + } + } + else { + uiItemL(layout, TIP_("No mesh in active object"), ICON_ERROR); + } +} static void node_shader_init_vertex_color(bNodeTree *UNUSED(ntree), bNode *node) { - NodeShaderVertexColor *vertexColor = MEM_callocN(sizeof(NodeShaderVertexColor), - "NodeShaderVertexColor"); + NodeShaderVertexColor *vertexColor = MEM_cnew<NodeShaderVertexColor>("NodeShaderVertexColor"); node->storage = vertexColor; } @@ -47,16 +73,21 @@ static int node_shader_gpu_vertex_color(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink); } -void register_node_type_sh_vertex_color(void) +} // namespace blender::nodes::node_shader_vertex_color_cc + +void register_node_type_sh_vertex_color() { + namespace file_ns = blender::nodes::node_shader_vertex_color_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_VERTEX_COLOR, "Vertex Color", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, sh_node_vertex_color_out); - node_type_init(&ntype, node_shader_init_vertex_color); + sh_node_type_base(&ntype, SH_NODE_VERTEX_COLOR, "Vertex Color", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_vertex_color; + node_type_init(&ntype, file_ns::node_shader_init_vertex_color); node_type_storage( &ntype, "NodeShaderVertexColor", node_free_standard_storage, node_copy_standard_storage); - node_type_gpu(&ntype, node_shader_gpu_vertex_color); + node_type_gpu(&ntype, file_ns::node_shader_gpu_vertex_color); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_absorption.c b/source/blender/nodes/shader/nodes/node_shader_volume_absorption.cc index 3c9fab2401b..a31bfdb6543 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_absorption.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_absorption.cc @@ -17,21 +17,16 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_volume_absorption_cc { -static bNodeSocketTemplate sh_node_volume_absorption_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_volume_absorption_out[] = { - {SOCK_SHADER, N_("Volume")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Float>(N_("Density")).default_value(1.0f).min(0.0f).max(1000.0f); + b.add_output<decl::Shader>(N_("Volume")); +} static int node_shader_gpu_volume_absorption(GPUMaterial *mat, bNode *node, @@ -42,16 +37,18 @@ static int node_shader_gpu_volume_absorption(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_volume_absorption", in, out); } +} // namespace blender::nodes::node_shader_volume_absorption_cc + /* node type definition */ -void register_node_type_sh_volume_absorption(void) +void register_node_type_sh_volume_absorption() { + namespace file_ns = blender::nodes::node_shader_volume_absorption_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_VOLUME_ABSORPTION, "Volume Absorption", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_volume_absorption_in, sh_node_volume_absorption_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_volume_absorption); + sh_node_type_base(&ntype, SH_NODE_VOLUME_ABSORPTION, "Volume Absorption", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_volume_absorption); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_info.c b/source/blender/nodes/shader/nodes/node_shader_volume_info.cc index 6cafc991e13..6a973cdbad7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_info.cc @@ -17,15 +17,17 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -static bNodeSocketTemplate sh_node_volume_info_out[] = { - {SOCK_RGBA, N_("Color")}, - {SOCK_FLOAT, N_("Density")}, - {SOCK_FLOAT, N_("Flame")}, - {SOCK_FLOAT, N_("Temperature")}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_volume_info_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Color>(N_("Color")); + b.add_output<decl::Float>(N_("Density")); + b.add_output<decl::Float>(N_("Flame")); + b.add_output<decl::Float>(N_("Temperature")); +} static int node_shader_gpu_volume_info(GPUMaterial *mat, bNode *UNUSED(node), @@ -49,13 +51,17 @@ static int node_shader_gpu_volume_info(GPUMaterial *mat, return true; } -void register_node_type_sh_volume_info(void) +} // namespace blender::nodes::node_shader_volume_info_cc + +void register_node_type_sh_volume_info() { + namespace file_ns = blender::nodes::node_shader_volume_info_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_VOLUME_INFO, "Volume Info", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, NULL, sh_node_volume_info_out); - node_type_gpu(&ntype, node_shader_gpu_volume_info); + sh_node_type_base(&ntype, SH_NODE_VOLUME_INFO, "Volume Info", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_volume_info); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_principled.c b/source/blender/nodes/shader/nodes/node_shader_volume_principled.cc index 41c3abd7ca4..54e92eafcf6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_principled.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_principled.cc @@ -17,31 +17,34 @@ * All rights reserved. */ -#include "../node_shader_util.h" - -/* **************** OUTPUT ******************** */ - -static bNodeSocketTemplate sh_node_volume_principled_in[] = { - {SOCK_RGBA, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f}, - {SOCK_STRING, N_("Color Attribute"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_STRING, N_("Density Attribute"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Anisotropy"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_FACTOR}, - {SOCK_RGBA, N_("Absorption Color"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Emission Strength"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1000.0f}, - {SOCK_RGBA, N_("Emission Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Blackbody Intensity"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_RGBA, N_("Blackbody Tint"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Temperature"), 1000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 6500.0f}, - {SOCK_STRING, N_("Temperature Attribute"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_volume_principled_out[] = { - {SOCK_SHADER, N_("Volume")}, - {-1, ""}, -}; +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_volume_principled_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.5f, 0.5f, 0.5f, 1.0f}); + b.add_input<decl::String>(N_("Color Attribute")); + b.add_input<decl::Float>(N_("Density")).default_value(1.0f).min(0.0f).max(1000.0f); + b.add_input<decl::String>(N_("Density Attribute")); + b.add_input<decl::Float>(N_("Anisotropy")) + .default_value(0.0f) + .min(-1.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Color>(N_("Absorption Color")).default_value({0.0f, 0.0f, 0.0f, 1.0f}); + b.add_input<decl::Float>(N_("Emission Strength")).default_value(0.0f).min(0.0f).max(1000.0f); + b.add_input<decl::Color>(N_("Emission Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Blackbody Intensity")) + .default_value(0.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Color>(N_("Blackbody Tint")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Temperature")).default_value(1000.0f).min(0.0f).max(6500.0f); + b.add_input<decl::String>(N_("Temperature Attribute")); + b.add_output<decl::Shader>(N_("Volume")); +} static void node_shader_init_volume_principled(bNodeTree *UNUSED(ntree), bNode *node) { @@ -65,14 +68,14 @@ static int node_shader_gpu_volume_principled(GPUMaterial *mat, bool use_blackbody = (in[8].link || in[8].vec[0] != 0.0f); /* Get volume attributes. */ - GPUNodeLink *density = NULL, *color = NULL, *temperature = NULL; + GPUNodeLink *density = nullptr, *color = nullptr, *temperature = nullptr; LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { if (sock->typeinfo->type != SOCK_STRING) { continue; } - bNodeSocketValueString *value = sock->default_value; + bNodeSocketValueString *value = (bNodeSocketValueString *)sock->default_value; const char *attribute_name = value->value; if (attribute_name[0] == '\0') { continue; @@ -107,11 +110,11 @@ static int node_shader_gpu_volume_principled(GPUMaterial *mat, const int size = CM_TABLE + 1; float *data, layer; if (use_blackbody) { - data = MEM_mallocN(sizeof(float) * size * 4, "blackbody texture"); + data = (float *)MEM_mallocN(sizeof(float) * size * 4, "blackbody texture"); blackbody_temperature_to_rgb_table(data, size, 965.0f, 12000.0f); } else { - data = MEM_callocN(sizeof(float) * size * 4, "blackbody black"); + data = (float *)MEM_callocN(sizeof(float) * size * 4, "blackbody black"); } GPUNodeLink *spectrummap = GPU_color_band(mat, size, data, &layer); @@ -127,17 +130,20 @@ static int node_shader_gpu_volume_principled(GPUMaterial *mat, GPU_constant(&layer)); } +} // namespace blender::nodes::node_shader_volume_principled_cc + /* node type definition */ -void register_node_type_sh_volume_principled(void) +void register_node_type_sh_volume_principled() { + namespace file_ns = blender::nodes::node_shader_volume_principled_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_VOLUME_PRINCIPLED, "Principled Volume", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_volume_principled_in, sh_node_volume_principled_out); + sh_node_type_base(&ntype, SH_NODE_VOLUME_PRINCIPLED, "Principled Volume", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; node_type_size_preset(&ntype, NODE_SIZE_LARGE); - node_type_init(&ntype, node_shader_init_volume_principled); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_volume_principled); + node_type_init(&ntype, file_ns::node_shader_init_volume_principled); + node_type_gpu(&ntype, file_ns::node_shader_gpu_volume_principled); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.cc index 282a49dc944..abd10cfcbcf 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.cc @@ -17,22 +17,21 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** OUTPUT ******************** */ +namespace blender::nodes::node_shader_volume_scatter_cc { -static bNodeSocketTemplate sh_node_volume_scatter_in[] = { - {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - {SOCK_FLOAT, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - {SOCK_FLOAT, N_("Anisotropy"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Weight"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_UNAVAIL}, - {-1, ""}, -}; - -static bNodeSocketTemplate sh_node_volume_scatter_out[] = { - {SOCK_SHADER, N_("Volume")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); + b.add_input<decl::Float>(N_("Density")).default_value(1.0f).min(0.0f).max(1000.0f); + b.add_input<decl::Float>(N_("Anisotropy")) + .default_value(0.0f) + .min(-1.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_output<decl::Shader>(N_("Volume")); +} static int node_shader_gpu_volume_scatter(GPUMaterial *mat, bNode *node, @@ -43,16 +42,18 @@ static int node_shader_gpu_volume_scatter(GPUMaterial *mat, return GPU_stack_link(mat, node, "node_volume_scatter", in, out); } +} // namespace blender::nodes::node_shader_volume_scatter_cc + /* node type definition */ -void register_node_type_sh_volume_scatter(void) +void register_node_type_sh_volume_scatter() { + namespace file_ns = blender::nodes::node_shader_volume_scatter_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_VOLUME_SCATTER, "Volume Scatter", NODE_CLASS_SHADER, 0); - node_type_socket_templates(&ntype, sh_node_volume_scatter_in, sh_node_volume_scatter_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_volume_scatter); + sh_node_type_base(&ntype, SH_NODE_VOLUME_SCATTER, "Volume Scatter", NODE_CLASS_SHADER); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_volume_scatter); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_wavelength.c b/source/blender/nodes/shader/nodes/node_shader_wavelength.cc index f978537ee85..a67c7830edd 100644 --- a/source/blender/nodes/shader/nodes/node_shader_wavelength.c +++ b/source/blender/nodes/shader/nodes/node_shader_wavelength.cc @@ -17,18 +17,15 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** Wavelength ******************** */ -static bNodeSocketTemplate sh_node_wavelength_in[] = { - {SOCK_FLOAT, N_("Wavelength"), 500.0f, 0.0f, 0.0f, 0.0f, 380.0f, 780.0f}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_wavelength_cc { -static bNodeSocketTemplate sh_node_wavelength_out[] = { - {SOCK_RGBA, N_("Color")}, - {-1, ""}, -}; +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Wavelength")).default_value(500.0f).min(380.0f).max(780.0f); + b.add_output<decl::Color>(N_("Color")); +} static int node_shader_gpu_wavelength(GPUMaterial *mat, bNode *node, @@ -37,7 +34,7 @@ static int node_shader_gpu_wavelength(GPUMaterial *mat, GPUNodeStack *out) { const int size = CM_TABLE + 1; - float *data = MEM_mallocN(sizeof(float) * size * 4, "cie_xyz texture"); + float *data = static_cast<float *>(MEM_mallocN(sizeof(float) * size * 4, "cie_xyz texture")); wavelength_to_xyz_table(data, size); @@ -57,17 +54,19 @@ static int node_shader_gpu_wavelength(GPUMaterial *mat, GPU_uniform(xyz_to_rgb.b)); } +} // namespace blender::nodes::node_shader_wavelength_cc + /* node type definition */ -void register_node_type_sh_wavelength(void) +void register_node_type_sh_wavelength() { + namespace file_ns = blender::nodes::node_shader_wavelength_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_WAVELENGTH, "Wavelength", NODE_CLASS_CONVERTER, 0); + sh_node_type_base(&ntype, SH_NODE_WAVELENGTH, "Wavelength", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::node_declare; node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_socket_templates(&ntype, sh_node_wavelength_in, sh_node_wavelength_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_wavelength); + node_type_gpu(&ntype, file_ns::node_shader_gpu_wavelength); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_wireframe.c b/source/blender/nodes/shader/nodes/node_shader_wireframe.cc index e8c2b6971bc..c4771cc13e9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_wireframe.c +++ b/source/blender/nodes/shader/nodes/node_shader_wireframe.cc @@ -17,18 +17,23 @@ * All rights reserved. */ -#include "../node_shader_util.h" +#include "node_shader_util.hh" -/* **************** Wireframe ******************** */ -static bNodeSocketTemplate sh_node_wireframe_in[] = { - {SOCK_FLOAT, N_("Size"), 0.01f, 0.0f, 0.0f, 0.0f, 0.0f, 100.0f}, - {-1, ""}, -}; +#include "UI_interface.h" +#include "UI_resources.h" -static bNodeSocketTemplate sh_node_wireframe_out[] = { - {SOCK_FLOAT, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {-1, ""}, -}; +namespace blender::nodes::node_shader_wireframe_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Size")).default_value(0.01f).min(0.0f).max(100.0f); + b.add_output<decl::Float>(N_("Fac")); +} + +static void node_shader_buts_wireframe(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "use_pixel_size", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, 0); +} static int node_shader_gpu_wireframe(GPUMaterial *mat, bNode *node, @@ -46,16 +51,19 @@ static int node_shader_gpu_wireframe(GPUMaterial *mat, } } +} // namespace blender::nodes::node_shader_wireframe_cc + /* node type definition */ -void register_node_type_sh_wireframe(void) +void register_node_type_sh_wireframe() { + namespace file_ns = blender::nodes::node_shader_wireframe_cc; + static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_WIREFRAME, "Wireframe", NODE_CLASS_INPUT, 0); - node_type_socket_templates(&ntype, sh_node_wireframe_in, sh_node_wireframe_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); - node_type_gpu(&ntype, node_shader_gpu_wireframe); + sh_node_type_base(&ntype, SH_NODE_WIREFRAME, "Wireframe", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + ntype.draw_buttons = file_ns::node_shader_buts_wireframe; + node_type_gpu(&ntype, file_ns::node_shader_gpu_wireframe); nodeRegisterType(&ntype); } |