Render: make Cycles and Evee support each other's output material nodes.

This changes the Cycles exporting and Cycles/Eevee UI code to support both
output material nodes, giving priority to the renderer native one. Still
missing is Eevee code to prefer the Eevee output node.
This commit is contained in:
2017-08-01 18:03:16 +02:00
parent 110d6832a8
commit c42c129393
7 changed files with 85 additions and 66 deletions

View File

@@ -899,19 +899,22 @@ class CYCLES_OT_use_shading_nodes(Operator):
return {'FINISHED'}
def panel_node_draw(layout, id_data, output_type, input_name):
def panel_node_draw(layout, id_data, output_types, input_name):
if not id_data.use_nodes:
layout.operator("cycles.use_shading_nodes", icon='NODETREE')
return False
ntree = id_data.node_tree
node = find_output_node(ntree, output_type)
if not node:
layout.label(text="No output node")
else:
node = find_output_node(ntree, output_types)
if node:
input = find_node_input(node, input_name)
if input:
layout.template_node_view(ntree, node, input)
else:
layout.label(text="Incompatible output node")
else:
layout.label(text="No output node")
return True
@@ -1000,7 +1003,7 @@ class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
layout = self.layout
lamp = context.lamp
if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
if not panel_node_draw(layout, lamp, ['OUTPUT_LAMP'], 'Surface'):
layout.prop(lamp, "color")
@@ -1055,7 +1058,7 @@ class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
world = context.world
if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
if not panel_node_draw(layout, world, ['OUTPUT_WORLD'], 'Surface'):
layout.prop(world, "horizon_color", text="Color")
@@ -1073,7 +1076,7 @@ class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
layout = self.layout
world = context.world
panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
panel_node_draw(layout, world, ['OUTPUT_WORLD'], 'Volume')
class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
@@ -1218,7 +1221,7 @@ class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
layout = self.layout
mat = context.material
if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
if not panel_node_draw(layout, mat, ['OUTPUT_MATERIAL', 'OUTPUT_EEVEE_MATERIAL'], 'Surface'):
layout.prop(mat, "diffuse_color")
@@ -1238,7 +1241,7 @@ class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
mat = context.material
# cmat = mat.cycles
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
panel_node_draw(layout, mat, ['OUTPUT_MATERIAL', 'OUTPUT_EEVEE_MATERIAL'], 'Volume')
class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
@@ -1254,7 +1257,7 @@ class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
layout = self.layout
mat = context.material
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
panel_node_draw(layout, mat, ['OUTPUT_MATERIAL', 'OUTPUT_EEVEE_MATERIAL'], 'Displacement')
class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):

View File

@@ -231,14 +231,6 @@ static void get_tex_mapping(TextureMapping *mapping,
mapping->max = get_float3(b_mapping.max());
}
static bool is_output_node(BL::Node& b_node)
{
return (b_node.is_a(&RNA_ShaderNodeOutputMaterial)
|| b_node.is_a(&RNA_ShaderNodeOutputWorld)
|| b_node.is_a(&RNA_ShaderNodeOutputLamp)
|| b_node.is_a(&RNA_ShaderNodeOutputEeveeMaterial));
}
static ShaderNode *add_node(Scene *scene,
BL::RenderEngine& b_engine,
BL::BlendData& b_data,
@@ -951,6 +943,42 @@ static ShaderOutput *node_find_output_by_name(ShaderNode *node,
return node->output(name.c_str());
}
static BL::ShaderNode find_output_node(BL::ShaderNodeTree& b_ntree)
{
BL::ShaderNodeTree::nodes_iterator b_node;
BL::ShaderNode output_node(PointerRNA_NULL);
BL::ShaderNode eevee_output_node(PointerRNA_NULL);
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
BL::ShaderNodeOutputMaterial b_output_node(*b_node);
if (b_output_node.is_a(&RNA_ShaderNodeOutputMaterial) ||
b_output_node.is_a(&RNA_ShaderNodeOutputWorld) ||
b_output_node.is_a(&RNA_ShaderNodeOutputLamp)) {
/* regular Cycles output node */
if(b_output_node.is_active_output()) {
output_node = b_output_node;
break;
}
else if(!output_node.ptr.data) {
output_node = b_output_node;
}
}
else if (b_output_node.is_a(&RNA_ShaderNodeOutputEeveeMaterial)) {
/* Eevee output used if no Cycles node exists */
if(b_output_node.is_active_output()) {
eevee_output_node = b_output_node;
}
else if(!eevee_output_node.ptr.data) {
eevee_output_node = b_output_node;
}
}
}
return (output_node.ptr.data) ? output_node : eevee_output_node;
}
static void add_nodes(Scene *scene,
BL::RenderEngine& b_engine,
BL::BlendData& b_data,
@@ -971,23 +999,7 @@ static void add_nodes(Scene *scene,
BL::Node::outputs_iterator b_output;
/* find the node to use for output if there are multiple */
bool found_active_output = false;
BL::ShaderNode output_node(PointerRNA_NULL);
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
if(is_output_node(*b_node)) {
BL::ShaderNodeOutputMaterial b_output_node(*b_node);
if(b_output_node.is_active_output()) {
output_node = b_output_node;
found_active_output = true;
break;
}
else if(!output_node.ptr.data && !found_active_output) {
output_node = b_output_node;
}
}
}
BL::ShaderNode output_node = find_output_node(b_ntree);
/* add nodes */
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
@@ -1085,11 +1097,9 @@ static void add_nodes(Scene *scene,
else {
ShaderNode *node = NULL;
if(is_output_node(*b_node)) {
if(b_node->ptr.data == output_node.ptr.data) {
node = graph->output();
}
}
else {
BL::ShaderNode b_shader_node(*b_node);
node = add_node(scene,

View File

@@ -32,16 +32,19 @@ def find_node_input(node, name):
return None
# Return the output node to display in the UI
def find_output_node(ntree, nodetype):
# Return the output node to display in the UI. In case multiple node types are
# specified, node types earlier in the list get priority.
def find_output_node(ntree, nodetypes):
if ntree:
active_output_node = None
output_node = None
for nodetype in nodetypes:
for node in ntree.nodes:
if getattr(node, "type", None) == nodetype:
if getattr(node, "is_active_output", True):
return node
if not active_output_node:
active_output_node = node
return active_output_node
if not output_node:
output_node = node
if output_node:
return output_node
return None

View File

@@ -1120,10 +1120,12 @@ def panel_node_draw(layout, ntree, output_type):
if node:
input = find_node_input(node, 'Surface')
if input:
layout.template_node_view(ntree, node, input)
return True
return False
else:
layout.label(text="Incompatible output node")
else:
layout.label(text="No output node")
class EEVEE_MATERIAL_PT_surface(MaterialButtonsPanel, Panel):
@@ -1145,8 +1147,7 @@ class EEVEE_MATERIAL_PT_surface(MaterialButtonsPanel, Panel):
layout.separator()
if mat.use_nodes:
if not panel_node_draw(layout, mat.node_tree, 'OUTPUT_EEVEE_MATERIAL'):
layout.label(text="No output node")
panel_node_draw(layout, mat.node_tree, ['OUTPUT_EEVEE_MATERIAL', 'OUTPUT_MATERIAL'])
else:
raym = mat.raytrace_mirror
layout.prop(mat, "diffuse_color", text="Base Color")

View File

@@ -270,13 +270,16 @@ class EEVEE_WORLD_PT_surface(WorldButtonsPanel, Panel):
if world.use_nodes:
ntree = world.node_tree
node = find_output_node(ntree, 'OUTPUT_WORLD')
node = find_output_node(ntree, ['OUTPUT_WORLD'])
if not node:
layout.label(text="No output node")
else:
if node:
input = find_node_input(node, 'Surface')
if input:
layout.template_node_view(ntree, node, input)
else:
layout.label(text="Incompatible output node")
else:
layout.label(text="No output node")
else:
layout.prop(world, "horizon_color", text="Color")

View File

@@ -214,6 +214,9 @@ static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
* 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.
*
* It also does not yet take into account render engine specific output nodes,
* it should give priority to e.g. the Eevee material output node for Eevee.
*/
static bNode *ntree_shader_output_node(bNodeTree *ntree)
{

View File

@@ -42,10 +42,6 @@ static int node_shader_gpu_output_material(GPUMaterial *mat, bNode *node, bNodeE
{
GPUNodeLink *outlink;
if (BKE_scene_uses_blender_eevee(GPU_material_scene(mat))) {
return false;
}
GPU_stack_link(mat, node, "node_output_material", in, out, &outlink);
GPU_material_output_link(mat, outlink);