From 89cad4e25ecac211fb66088211ce159fcea67f34 Mon Sep 17 00:00:00 2001 From: luboslenco Date: Wed, 23 Jan 2019 18:09:53 +0100 Subject: [PATCH] Emission fixes --- .../deferred_light/deferred_light.frag.glsl | 9 +++++- blender/arm/material/cycles.py | 31 ++++++++++++------- blender/arm/material/make_mesh.py | 20 +++++++++++- blender/arm/material/make_shader.py | 3 ++ blender/arm/material/mat_utils.py | 26 ++++++++++++++++ 5 files changed, 76 insertions(+), 13 deletions(-) diff --git a/Shaders/deferred_light/deferred_light.frag.glsl b/Shaders/deferred_light/deferred_light.frag.glsl index f96eabb1..58759b2b 100644 --- a/Shaders/deferred_light/deferred_light.frag.glsl +++ b/Shaders/deferred_light/deferred_light.frag.glsl @@ -166,7 +166,7 @@ in vec3 viewRay; out vec4 fragColor; void main() { - vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, metallic/roughness, depth + vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, metallic/roughness, matid vec3 n; n.z = 1.0 - abs(g0.x) - abs(g0.y); @@ -278,6 +278,13 @@ void main() { // #endif #endif +#ifdef _Emission + if (g0.a == 1.0) { + fragColor.rgb += g1.rgb; // materialid + albedo = vec3(0.0); + } +#endif + // Show voxels // vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99); // vec3 direction = vec3(0.0, 0.0, -1.0); diff --git a/blender/arm/material/cycles.py b/blender/arm/material/cycles.py index ab34c716..04651794 100644 --- a/blender/arm/material/cycles.py +++ b/blender/arm/material/cycles.py @@ -71,6 +71,7 @@ def parse_output(node, _con, _vert, _frag, _geom, _tesc, _tese, _parse_surface, particle_info['angular_velocity'] = False sample_bump = False sample_bump_res = '' + wrd = bpy.data.worlds['Arm'] # Surface if parse_surface or parse_opacity: @@ -79,13 +80,15 @@ def parse_output(node, _con, _vert, _frag, _geom, _tesc, _tese, _parse_surface, normal_parsed = False curshader = frag - out_basecol, out_roughness, out_metallic, out_occlusion, out_specular, out_opacity = parse_shader_input(node.inputs[0]) + out_basecol, out_roughness, out_metallic, out_occlusion, out_specular, out_opacity, out_emission = parse_shader_input(node.inputs[0]) if parse_surface: frag.write('basecol = {0};'.format(out_basecol)) frag.write('roughness = {0};'.format(out_roughness)) frag.write('metallic = {0};'.format(out_metallic)) frag.write('occlusion = {0};'.format(out_occlusion)) frag.write('specular = {0};'.format(out_specular)) + if '_Emission' in wrd.world_defs: + frag.write('emission = {0};'.format(out_emission)) if parse_opacity: frag.write('opacity = {0};'.format(out_opacity)) @@ -149,7 +152,8 @@ def parse_shader_input(inp): out_occlusion = '1.0' out_specular = '1.0' out_opacity = '1.0' - return out_basecol, out_roughness, out_metallic, out_occlusion, out_specular, out_opacity + out_emission = '0.0' + return out_basecol, out_roughness, out_metallic, out_occlusion, out_specular, out_opacity, out_emission def parse_shader(node, socket): global emission_found @@ -159,6 +163,7 @@ def parse_shader(node, socket): out_occlusion = '1.0' out_specular = '1.0' out_opacity = '1.0' + out_emission = '0.0' if node.type == 'GROUP': if node.node_tree.name.startswith('Armory PBR'): @@ -177,9 +182,10 @@ def parse_shader(node, socket): parse_normal_map_color_input(node.inputs[5]) # Emission if node.inputs[6].is_linked or node.inputs[6].default_value != 0.0: - out_emission = parse_value_input(node.inputs[6]) + out_emission = '1.0' + emission_strength = parse_value_input(node.inputs[6]) emission_found = True - out_basecol = '({0} + vec3({1} * 100.0))'.format(out_basecol, out_emission) + out_basecol = '({0} * {1})'.format(out_basecol, emission_strength) if parse_opacity: out_opacity = parse_value_input(node.inputs[1]) else: @@ -195,26 +201,28 @@ def parse_shader(node, socket): fac_inv_var = node_name(node.name) + '_fac_inv' curshader.write('{0}float {1} = {2};'.format(prefix, fac_var, fac)) curshader.write('{0}float {1} = 1.0 - {2};'.format(prefix, fac_inv_var, fac_var)) - bc1, rough1, met1, occ1, spec1, opac1 = parse_shader_input(node.inputs[1]) - bc2, rough2, met2, occ2, spec2, opac2 = parse_shader_input(node.inputs[2]) + bc1, rough1, met1, occ1, spec1, opac1, emi1 = parse_shader_input(node.inputs[1]) + bc2, rough2, met2, occ2, spec2, opac2, emi2 = parse_shader_input(node.inputs[2]) if parse_surface: out_basecol = '({0} * {3} + {1} * {2})'.format(bc1, bc2, fac_var, fac_inv_var) out_roughness = '({0} * {3} + {1} * {2})'.format(rough1, rough2, fac_var, fac_inv_var) out_metallic = '({0} * {3} + {1} * {2})'.format(met1, met2, fac_var, fac_inv_var) out_occlusion = '({0} * {3} + {1} * {2})'.format(occ1, occ2, fac_var, fac_inv_var) out_specular = '({0} * {3} + {1} * {2})'.format(spec1, spec2, fac_var, fac_inv_var) + out_emission = '({0} * {3} + {1} * {2})'.format(emi1, emi2, fac_var, fac_inv_var) if parse_opacity: out_opacity = '({0} * {3} + {1} * {2})'.format(opac1, opac2, fac_var, fac_inv_var) elif node.type == 'ADD_SHADER': - bc1, rough1, met1, occ1, spec1, opac1 = parse_shader_input(node.inputs[0]) - bc2, rough2, met2, occ2, spec2, opac2 = parse_shader_input(node.inputs[1]) + bc1, rough1, met1, occ1, spec1, opac1, emi1 = parse_shader_input(node.inputs[0]) + bc2, rough2, met2, occ2, spec2, opac2, emi2 = parse_shader_input(node.inputs[1]) if parse_surface: out_basecol = '({0} + {1})'.format(bc1, bc2) out_roughness = '({0} * 0.5 + {1} * 0.5)'.format(rough1, rough2) out_metallic = '({0} * 0.5 + {1} * 0.5)'.format(met1, met2) out_occlusion = '({0} * 0.5 + {1} * 0.5)'.format(occ1, occ2) out_specular = '({0} * 0.5 + {1} * 0.5)'.format(spec1, spec2) + out_emission = '({0} * 0.5 + {1} * 0.5)'.format(emi1, emi2) if parse_opacity: out_opacity = '({0} * 0.5 + {1} * 0.5)'.format(opac1, opac2) @@ -270,9 +278,10 @@ def parse_shader(node, socket): if parse_surface: # Multiply basecol out_basecol = parse_vector_input(node.inputs[0]) + out_emission = '1.0' emission_found = True - strength = parse_value_input(node.inputs[1]) - out_basecol = '({0} * ({1} * 100.0))'.format(out_basecol, strength) + emission_strength = parse_value_input(node.inputs[1]) + out_basecol = '({0} * {1})'.format(out_basecol, emission_strength) elif node.type == 'BSDF_GLASS': if parse_surface: @@ -325,7 +334,7 @@ def parse_shader(node, socket): elif node.type == 'VOLUME_SCATTER': pass - return out_basecol, out_roughness, out_metallic, out_occlusion, out_specular, out_opacity + return out_basecol, out_roughness, out_metallic, out_occlusion, out_specular, out_opacity, out_emission def parse_displacement_input(inp): if inp.is_linked: diff --git a/blender/arm/material/make_mesh.py b/blender/arm/material/make_mesh.py index 689b4202..1a110b96 100644 --- a/blender/arm/material/make_mesh.py +++ b/blender/arm/material/make_mesh.py @@ -68,6 +68,7 @@ def make_base(con_mesh, parse_opacity): global write_material_attribs global write_material_attribs_post global write_vertex_attribs + wrd = bpy.data.worlds['Arm'] vert = con_mesh.make_vert() frag = con_mesh.make_frag() @@ -110,6 +111,8 @@ def make_base(con_mesh, parse_opacity): frag.write('float metallic;') frag.write('float occlusion;') frag.write('float specular;') + if '_Emission' in wrd.world_defs: + frag.write('float emission;') if parse_opacity: frag.write('float opacity;') cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity) @@ -242,7 +245,12 @@ def make_deferred(con_mesh): frag.write('n /= (abs(n.x) + abs(n.y) + abs(n.z));') frag.write('n.xy = n.z >= 0.0 ? n.xy : octahedronWrap(n.xy);') - frag.write('fragColor[0] = vec4(n.xy, packFloat(metallic, roughness), 1.0);') + if '_Emission' in wrd.world_defs: + frag.write('float matid = 0.0;') + frag.write('if (emission > 0) matid = 1.0;') + else: + frag.write('const float matid = 0.0;') + frag.write('fragColor[0] = vec4(n.xy, packFloat(metallic, roughness), matid);') frag.write('fragColor[1] = vec4(basecol.rgb, packFloat2(occlusion, specular));') if '_gbuffer2' in wrd.world_defs: @@ -284,6 +292,8 @@ def make_forward_mobile(con_mesh): frag.write('float metallic;') frag.write('float occlusion;') frag.write('float specular;') + if '_Emission' in wrd.world_defs: + frag.write('float emission;') arm_discard = mat_state.material.arm_discard blend = mat_state.material.arm_blending @@ -434,6 +444,8 @@ def make_forward_solid(con_mesh): frag.write('float metallic;') frag.write('float occlusion;') frag.write('float specular;') + if '_Emission' in wrd.world_defs: + frag.write('float emission;') arm_discard = mat_state.material.arm_discard blend = mat_state.material.arm_blending @@ -661,3 +673,9 @@ def make_forward_base(con_mesh, parse_opacity=False): frag.write('indirectSpecular *= f0 * envBRDF.x + envBRDF.y;') frag.write('indirect += indirectSpecular * voxelgiSpec * specular;') frag.write('}') + + if '_Emission' in wrd.world_defs: + frag.write('if (emission > 0.0) {') + frag.write(' direct = vec3(0.0);') + frag.write(' indirect += basecol;') + frag.write('}') diff --git a/blender/arm/material/make_shader.py b/blender/arm/material/make_shader.py index 1fb80886..88e389da 100644 --- a/blender/arm/material/make_shader.py +++ b/blender/arm/material/make_shader.py @@ -31,6 +31,9 @@ def build(material, mat_users, mat_armusers): wrd = bpy.data.worlds['Arm'] rpdat = arm.utils.get_rp() rpasses = mat_utils.get_rpasses(material) + is_emissive = mat_utils.is_emmisive(material) + if is_emissive and '_Emission' not in wrd.world_defs: + wrd.world_defs += '_Emission' matname = arm.utils.safesrc(arm.utils.asset_name(material)) rel_path = arm.utils.build_dir() + '/compiled/Shaders/' full_path = arm.utils.get_fp() + '/' + rel_path diff --git a/blender/arm/material/mat_utils.py b/blender/arm/material/mat_utils.py index a9c2665d..84b4d273 100644 --- a/blender/arm/material/mat_utils.py +++ b/blender/arm/material/mat_utils.py @@ -75,3 +75,29 @@ def is_transluc_type(node): (node.type == 'GROUP' and node.node_tree.name.startswith('Armory PBR') and (node.inputs[1].is_linked or node.inputs[1].default_value != 1.0)): return True return False + +def is_emmisive(material): + nodes = material.node_tree.nodes + output_node = cycles.node_by_type(nodes, 'OUTPUT_MATERIAL') + if output_node == None or output_node.inputs[0].is_linked == False: + return False + + surface_node = output_node.inputs[0].links[0].from_node + return is_emmisive_traverse(surface_node) + +def is_emmisive_traverse(node): + # TODO: traverse groups + if is_emmisive_type(node): + return True + for inp in node.inputs: + if inp.is_linked: + res = is_emmisive_traverse(inp.links[0].from_node) + if res: + return True + return False + +def is_emmisive_type(node): + if node.type == 'EMISSION' or \ + (node.type == 'GROUP' and node.node_tree.name.startswith('Armory PBR') and (node.inputs[6].is_linked or node.inputs[6].default_value != 0.0)): + return True + return False