diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-07-18 15:13:02 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-07-18 15:13:16 +0300 |
commit | 3d67819a1709e35b2fb42a9d554b30136a72eec9 (patch) | |
tree | da74b41c52fab9592ee12e3db0c046bf70d85d5a /source/blender/nodes | |
parent | 257d072317f21861cdb7c168a60497bcb74d73d4 (diff) | |
parent | 5078b9d2d08a34ae3786100c2301ea960165e7f2 (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/nodes')
-rw-r--r-- | source/blender/nodes/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/nodes/NOD_composite.h | 1 | ||||
-rw-r--r-- | source/blender/nodes/NOD_shader.h | 1 | ||||
-rw-r--r-- | source/blender/nodes/NOD_static_types.h | 2 | ||||
-rw-r--r-- | source/blender/nodes/composite/nodes/node_composite_cryptomatte.c | 302 | ||||
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c | 132 |
6 files changed, 440 insertions, 0 deletions
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 67c86180188..8df114afa24 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -60,6 +60,7 @@ set(SRC composite/nodes/node_composite_composite.c composite/nodes/node_composite_cornerpin.c composite/nodes/node_composite_crop.c + composite/nodes/node_composite_cryptomatte.c composite/nodes/node_composite_curves.c composite/nodes/node_composite_despeckle.c composite/nodes/node_composite_doubleEdgeMask.c @@ -168,6 +169,7 @@ set(SRC shader/nodes/node_shader_bsdf_transparent.c shader/nodes/node_shader_bsdf_velvet.c shader/nodes/node_shader_bsdf_hair.c + shader/nodes/node_shader_bsdf_hair_principled.c shader/nodes/node_shader_bump.c shader/nodes/node_shader_emission.c shader/nodes/node_shader_fresnel.c diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index dfcb83b873a..a728d1e228d 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -109,6 +109,7 @@ void register_node_type_cmp_luma_matte(void); void register_node_type_cmp_doubleedgemask(void); void register_node_type_cmp_keyingscreen(void); void register_node_type_cmp_keying(void); +void register_node_type_cmp_cryptomatte(void); void register_node_type_cmp_translate(void); void register_node_type_cmp_rotate(void); diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 83a5f5c5bf1..2f466b0296c 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -111,6 +111,7 @@ void register_node_type_sh_volume_absorption(void); void register_node_type_sh_volume_scatter(void); void register_node_type_sh_volume_principled(void); void register_node_type_sh_bsdf_hair(void); +void register_node_type_sh_bsdf_hair_principled(void); void register_node_type_sh_subsurface_scattering(void); void register_node_type_sh_mix_shader(void); void register_node_type_sh_add_shader(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index cf974132961..22c2afcc466 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -85,6 +85,7 @@ DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BS DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_TOON, def_toon, "BSDF_TOON", BsdfToon, "Toon BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_HAIR, def_hair, "BSDF_HAIR", BsdfHair, "Hair BSDF", "" ) +DefNode( ShaderNode, SH_NODE_BSDF_HAIR_PRINCIPLED, def_hair_principled, "BSDF_HAIR_PRINCIPLED", BsdfHairPrincipled, "Principled Hair BSDF", "") DefNode( ShaderNode, SH_NODE_SUBSURFACE_SCATTERING, def_sh_subsurface, "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","") DefNode( ShaderNode, SH_NODE_VOLUME_ABSORPTION, 0, "VOLUME_ABSORPTION", VolumeAbsorption, "Volume Absorption", "" ) DefNode( ShaderNode, SH_NODE_VOLUME_SCATTER, 0, "VOLUME_SCATTER", VolumeScatter, "Volume Scatter", "" ) @@ -215,6 +216,7 @@ DefNode( CompositorNode, CMP_NODE_PIXELATE, 0, "PIXEL DefNode( CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLANETRACKDEFORM",PlaneTrackDeform,"Plane Track Deform","" ) DefNode( CompositorNode, CMP_NODE_CORNERPIN, 0, "CORNERPIN", CornerPin, "Corner Pin", "" ) DefNode( CompositorNode, CMP_NODE_SUNBEAMS, def_cmp_sunbeams, "SUNBEAMS", SunBeams, "Sun Beams", "" ) +DefNode( CompositorNode, CMP_NODE_CRYPTOMATTE, def_cmp_cryptomatte, "CRYPTOMATTE", Cryptomatte, "Cryptomatte", "" ) DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" ) DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" ) diff --git a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c new file mode 100644 index 00000000000..0231e4717b2 --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c @@ -0,0 +1,302 @@ +/* + * ***** 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) 2018 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Lukas Stockner, Stefan Werner + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_cryptomatte.c + * \ingroup cmpnodes + */ + +#include "node_composite_util.h" +#include "BLI_assert.h" +#include "BLI_dynstr.h" +#include "BLI_hash_mm3.h" +#include "BLI_utildefines.h" + +/* this is taken from the cryptomatte specification 1.0 */ + +static inline float hash_to_float(uint32_t hash) +{ + uint32_t mantissa = hash & (( 1 << 23) - 1); + uint32_t exponent = (hash >> 23) & ((1 << 8) - 1); + exponent = MAX2(exponent, (uint32_t) 1); + exponent = MIN2(exponent, (uint32_t) 254); + exponent = exponent << 23; + uint32_t sign = (hash >> 31); + sign = sign << 31; + uint32_t float_bits = sign | exponent | mantissa; + float f; + /* Bit casting relies on equal size for both types. */ + BLI_STATIC_ASSERT(sizeof(float) == sizeof(uint32_t), "float and uint32_t are not the same size") + memcpy(&f, &float_bits, sizeof(float)); + return f; +} + +static void cryptomatte_add(NodeCryptomatte* n, float f) +{ + /* Turn the number into a string. */ + char number[32]; + BLI_snprintf(number, sizeof(number), "<%.9g>", f); + + /* Search if we already have the number. */ + if (n->matte_id && strlen(n->matte_id) != 0) { + size_t start = 0; + const size_t end = strlen(n->matte_id); + size_t token_len = 0; + while (start < end) { + /* Ignore leading whitespace. */ + while (start < end && n->matte_id[start] == ' ') { + ++start; + } + + /* Find the next seprator. */ + char* token_end = strchr(n->matte_id+start, ','); + if (token_end == NULL || token_end == n->matte_id+start) { + token_end = n->matte_id+end; + } + /* Be aware that token_len still contains any trailing white space. */ + token_len = token_end - (n->matte_id + start); + + /* If this has a leading bracket, assume a raw floating point number and look for the closing bracket. */ + if (n->matte_id[start] == '<') { + if (strncmp(n->matte_id+start, number, strlen(number)) == 0) { + /* This number is already there, so continue. */ + return; + } + } + else { + /* Remove trailing white space */ + size_t name_len = token_len; + while (n->matte_id[start+name_len] == ' ' && name_len > 0) { + name_len--; + } + /* Calculate the hash of the token and compare. */ + uint32_t hash = BLI_hash_mm3((const unsigned char*)(n->matte_id+start), name_len, 0); + if (f == hash_to_float(hash)) { + return; + } + } + start += token_len+1; + } + } + + DynStr *new_matte = BLI_dynstr_new(); + if (!new_matte) { + return; + } + + if(n->matte_id) { + BLI_dynstr_append(new_matte, n->matte_id); + MEM_freeN(n->matte_id); + } + + if(BLI_dynstr_get_len(new_matte) > 0) { + BLI_dynstr_append(new_matte, ","); + } + BLI_dynstr_append(new_matte, number); + n->matte_id = BLI_dynstr_get_cstring(new_matte); + BLI_dynstr_free(new_matte); +} + +static void cryptomatte_remove(NodeCryptomatte*n, float f) +{ + if (n->matte_id == NULL || strlen(n->matte_id) == 0) { + /* Empty string, nothing to remove. */ + return; + } + + /* This will be the new string without the removed key. */ + DynStr *new_matte = BLI_dynstr_new(); + if (!new_matte) { + return; + } + + /* Turn the number into a string. */ + static char number[32]; + BLI_snprintf(number, sizeof(number), "<%.9g>", f); + + /* Search if we already have the number. */ + size_t start = 0; + const size_t end = strlen(n->matte_id); + size_t token_len = 0; + bool is_first = true; + while (start < end) { + bool skip = false; + /* Ignore leading whitespace or commas. */ + while (start < end && ((n->matte_id[start] == ' ') || (n->matte_id[start] == ','))) { + ++start; + } + + /* Find the next seprator. */ + char* token_end = strchr(n->matte_id+start+1, ','); + if (token_end == NULL || token_end == n->matte_id+start) { + token_end = n->matte_id+end; + } + /* Be aware that token_len still contains any trailing white space. */ + token_len = token_end - (n->matte_id + start); + + if (token_len == 1) { + skip = true; + } + /* If this has a leading bracket, assume a raw floating point number and look for the closing bracket. */ + else if (n->matte_id[start] == '<') { + if (strncmp(n->matte_id+start, number, strlen(number)) == 0) { + /* This number is already there, so skip it. */ + skip = true; + } + } + else { + /* Remove trailing white space */ + size_t name_len = token_len; + while (n->matte_id[start+name_len] == ' ' && name_len > 0) { + name_len--; + } + /* Calculate the hash of the token and compare. */ + uint32_t hash = BLI_hash_mm3((const unsigned char*)(n->matte_id+start), name_len, 0); + if (f == hash_to_float(hash)) { + skip = true; + } + } + if (!skip) { + if (is_first) { + is_first = false; + } + else { + BLI_dynstr_append(new_matte, ", "); + } + BLI_dynstr_nappend(new_matte, n->matte_id+start, token_len); + } + start += token_len+1; + } + + if(n->matte_id) { + MEM_freeN(n->matte_id); + n->matte_id = NULL; + } + if(BLI_dynstr_get_len(new_matte) > 0) { + n->matte_id = BLI_dynstr_get_cstring(new_matte); + } + BLI_dynstr_free(new_matte); +} + +static bNodeSocketTemplate outputs[] = { + { SOCK_RGBA, 0, N_("Image")}, + { SOCK_FLOAT, 0, N_("Matte")}, + { SOCK_RGBA, 0, N_("Pick")}, + { -1, 0, "" } +}; + +void ntreeCompositCryptomatteSyncFromAdd(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeCryptomatte *n = node->storage; + if (n->add[0] != 0.0f) { + cryptomatte_add(n, n->add[0]); + n->add[0] = 0.0f; + n->add[1] = 0.0f; + n->add[2] = 0.0f; + } +} + +void ntreeCompositCryptomatteSyncFromRemove(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeCryptomatte *n = node->storage; + if (n->remove[0] != 0.0f) { + cryptomatte_remove(n, n->remove[0]); + n->remove[0] = 0.0f; + n->remove[1] = 0.0f; + n->remove[2] = 0.0f; + } +} + +bNodeSocket *ntreeCompositCryptomatteAddSocket(bNodeTree *ntree, bNode *node) +{ + NodeCryptomatte *n = node->storage; + char sockname[32]; + n->num_inputs++; + BLI_snprintf(sockname, sizeof(sockname), "Crypto %.2d", n->num_inputs-1); + bNodeSocket *sock = nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, NULL, sockname); + return sock; +} + +int ntreeCompositCryptomatteRemoveSocket(bNodeTree *ntree, bNode *node) +{ + NodeCryptomatte *n = node->storage; + if (n->num_inputs < 2) { + return 0; + } + bNodeSocket *sock = node->inputs.last; + nodeRemoveSocket(ntree, node, sock); + n->num_inputs--; + return 1; +} + +static void init(bNodeTree *ntree, bNode *node) +{ + NodeCryptomatte *user = MEM_callocN(sizeof(NodeCryptomatte), "cryptomatte user"); + node->storage = user; + + + nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, "image", "Image"); + + /* Add three inputs by default, as recommended by the Cryptomatte specification. */ + ntreeCompositCryptomatteAddSocket(ntree, node); + ntreeCompositCryptomatteAddSocket(ntree, node); + ntreeCompositCryptomatteAddSocket(ntree, node); +} + +static void node_free_cryptomatte(bNode *node) +{ + NodeCryptomatte *nc = node->storage; + + if (nc) { + if (nc->matte_id) { + MEM_freeN(nc->matte_id); + } + + MEM_freeN(nc); + } +} + +static void node_copy_cryptomatte(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node) +{ + NodeCryptomatte *src_nc = src_node->storage; + NodeCryptomatte *dest_nc = MEM_dupallocN(src_nc); + + if (src_nc->matte_id) + dest_nc->matte_id = MEM_dupallocN(src_nc->matte_id); + + dest_node->storage = dest_nc; +} + +void register_node_type_cmp_cryptomatte(void) +{ + static bNodeType ntype; + + cmp_node_type_base(&ntype, CMP_NODE_CRYPTOMATTE, "Cryptomatte", NODE_CLASS_CONVERTOR, 0); + node_type_socket_templates(&ntype, NULL, outputs); + node_type_init(&ntype, init); + node_type_storage(&ntype, "NodeCryptomatte", node_free_cryptomatte, node_copy_cryptomatte); + 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 new file mode 100644 index 00000000000..5fff2548ba1 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c @@ -0,0 +1,132 @@ +/* + * ***** 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) 2018 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Lukas Stockner, L. E. Segovia + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#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, 1, N_("Color"), 0.017513f, 0.005763f, 0.002059f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Melanin"), 0.8f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Melanin Redness"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_RGBA, 1, N_("Tint"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 1, N_("Absorption Coefficient"), 0.245531f, 0.52f, 1.365f, 0.0f, 0.0f, 1000.0f}, + { SOCK_FLOAT, 1, N_("Roughness"), 0.3f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Radial Roughness"), 0.3f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Coat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("IOR"), 1.55f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, + { SOCK_FLOAT, 1, N_("Offset"), 2.f*((float)M_PI)/180.f, 0.0f, 0.0f, 0.0f, -M_PI_2, M_PI_2, PROP_ANGLE}, + { SOCK_FLOAT, 1, N_("Random Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Random Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Random"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { -1, 0, "" }, +}; + +static bNodeSocketTemplate sh_node_bsdf_hair_principled_out[] = { + { SOCK_SHADER, 0, N_("BSDF")}, + { -1, 0, "" } +}; + +/* 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, NULL); + + nodeRegisterType(&ntype); +} |