예제 #1
0
/* Use specified node and socket as an input for unconnected normal sockets. */
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) {
		if (node == node_from) {
			/* Don't connect node itself! */
			continue;
		}
		bNodeSocket *sock = ntree_shader_node_find_input(node, "Normal");
		/* TODO(sergey): Can we do something smarter here than just a name-based
		 * matching?
		 */
		if (sock == NULL) {
			/* There's no Normal input, nothing to link. */
			continue;
		}
		if (sock->link != NULL) {
			/* Something is linked to the normal input already. can't
			 * use other input for that.
			 */
			continue;
		}
		/* Create connection between specified node and the normal input. */
		nodeAddLink(ntree, node_from, socket_from, node, sock);
	}
}
예제 #2
0
/* Check whether shader has a displacement.
 *
 * Will also return a node and it's socket which is connected to a displacement
 * output. Additionally, link which is attached to the displacement output is
 * also returned.
 */
static bool ntree_shader_has_displacement(bNodeTree *ntree,
                                          bNode **r_node,
                                          bNodeSocket **r_socket,
                                          bNodeLink **r_link)
{
	bNode *output_node = ntree_shader_output_node(ntree);
	if (output_node == NULL) {
		/* We can't have displacement without output node, apparently. */
		return false;
	}
	/* Make sure sockets links pointers are correct. */
	ntreeUpdateTree(G.main, ntree);
	bNodeSocket *displacement = ntree_shader_node_find_input(output_node,
	                                                         "Displacement");

	if (displacement == NULL) {
		/* Non-cycles node is used as an output. */
		return false;
	}
	if (displacement->link != NULL) {
		*r_node = displacement->link->fromnode;
		*r_socket = displacement->link->fromsock;
		*r_link = displacement->link;
	}
	return displacement->link != NULL;
}
예제 #3
0
/* Re-link displacement output to unconnected normal sockets via bump node.
 * This way material with have proper displacement in the viewport.
 */
static void ntree_shader_relink_displacement(bNodeTree *ntree,
        short compatibility)
{
    if (compatibility != NODE_NEW_SHADING) {
        /* We can only deal with new shading system here. */
        return;
    }
    bNode *displacement_node;
    bNodeSocket *displacement_socket;
    bNodeLink *displacement_link;
    if (!ntree_shader_has_displacement(ntree,
                                       &displacement_node,
                                       &displacement_socket,
                                       &displacement_link))
    {
        /* There is no displacement output connected, nothing to re-link. */
        return;
    }
    /* We have to disconnect displacement output socket, otherwise we'll have
     * cycles in the Cycles material :)
     */
    nodeRemLink(ntree, displacement_link);
    /* 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);
    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);
    /* Connect bump node to where displacement output was originally
     * connected to.
     */
    nodeAddLink(ntree,
                displacement_node, displacement_socket,
                bump_node, bump_input_socket);
    /* Connect all free-standing Normal inputs. */
    ntree_shader_link_builtin_normal(ntree,
                                     bump_node,
                                     bump_output_socket,
                                     displacement_node,
                                     displacement_socket);
    /* TODO(sergey): Reconnect Geometry Info->Normal sockets to the new
     * bump node.
     */
    /* We modified the tree, it needs to be updated now. */
    ntreeUpdateTree(G.main, ntree);
}
예제 #4
0
static bool ntree_shader_relink_node_normal(bNodeTree *ntree,
        bNode *node,
        bNode *node_from,
        bNodeSocket *socket_from)
{
    bNodeSocket *sock = ntree_shader_node_find_input(node, "Normal");
    /* TODO(sergey): Can we do something smarter here than just a name-based
     * matching?
     */
    if (sock == NULL) {
        /* There's no Normal input, nothing to link. */
        return false;
    }
    if (sock->link != NULL) {
        /* Something is linked to the normal input already. can't
         * use other input for that.
         */
        return false;
    }
    /* Create connection between specified node and the normal input. */
    nodeAddLink(ntree, node_from, socket_from, node, sock);
    return true;
}
예제 #5
0
static void ntree_shader_link_builtin_group_normal(
    bNodeTree *ntree,
    bNode *group_node,
    bNode *node_from,
    bNodeSocket *socket_from,
    bNode *displacement_node,
    bNodeSocket *displacement_socket)
{
    bNodeTree *group_ntree = (bNodeTree *)group_node->id;
    /* Create input socket to plug displacement connection to. */
    bNodeSocket *group_normal_socket =
        ntreeAddSocketInterface(group_ntree,
                                SOCK_IN,
                                "NodeSocketVector",
                                "Normal");
    /* Need to update tree so all node instances nodes gets proper sockets. */
    bNode *group_input_node = ntreeFindType(group_ntree, NODE_GROUP_INPUT);
    node_group_verify(ntree, group_node, &group_ntree->id);
    if (group_input_node)
        node_group_input_verify(group_ntree, group_input_node, &group_ntree->id);
    ntreeUpdateTree(G.main, group_ntree);
    /* Assumes sockets are always added at the end. */
    bNodeSocket *group_node_normal_socket = group_node->inputs.last;
    if (displacement_node == group_node) {
        /* If displacement is coming from this node group we need to perform
         * some internal re-linking in order to avoid cycles.
         */
        bNode *group_output_node = ntreeFindType(group_ntree, NODE_GROUP_OUTPUT);
        BLI_assert(group_output_node != NULL);
        bNodeSocket *group_output_node_displacement_socket =
            nodeFindSocket(group_output_node,
                           SOCK_IN,
                           displacement_socket->identifier);
        bNodeLink *group_displacement_link = group_output_node_displacement_socket->link;
        if (group_displacement_link == NULL) {
            /* Displacement output is not connected to anything, can just stop
             * right away.
             */
            return;
        }
        /* This code is similar to ntree_shader_relink_displacement() */
        bNode *group_displacement_node = group_displacement_link->fromnode;
        bNodeSocket *group_displacement_socket = group_displacement_link->fromsock;
        /* Create and link bump node.
         * Can't re-use bump node from parent tree because it'll cause cycle.
         */
        bNode *bump_node = nodeAddStaticNode(NULL, group_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);
        nodeAddLink(group_ntree,
                    group_displacement_node, group_displacement_socket,
                    bump_node, bump_input_socket);
        /* Relink normals inside of the instanced tree. */
        ntree_shader_link_builtin_normal(group_ntree,
                                         bump_node,
                                         bump_output_socket,
                                         group_displacement_node,
                                         group_displacement_socket);
        ntreeUpdateTree(G.main, group_ntree);
    }
    else if (group_input_node) {
        /* Connect group node normal input. */
        nodeAddLink(ntree,
                    node_from, socket_from,
                    group_node, group_node_normal_socket);
        BLI_assert(group_input_node != NULL);
        bNodeSocket *group_input_node_normal_socket =
            nodeFindSocket(group_input_node,
                           SOCK_OUT,
                           group_normal_socket->identifier);
        BLI_assert(group_input_node_normal_socket != NULL);
        /* Relink normals inside of the instanced tree. */
        ntree_shader_link_builtin_normal(group_ntree,
                                         group_input_node,
                                         group_input_node_normal_socket,
                                         displacement_node,
                                         displacement_socket);
        ntreeUpdateTree(G.main, group_ntree);
    }
}