Handle basecolor gamma

This commit is contained in:
Lubos Lenco 2016-12-21 19:15:51 +01:00
parent 0954693781
commit 82fc7176b2
8 changed files with 69 additions and 38 deletions

View file

@ -1804,6 +1804,10 @@ class ArmoryExporter:
# arbitrary stage in the modifier stack.
exportMesh = bobject.to_mesh(scene, applyModifiers, "RENDER", True, False)
if exportMesh == None:
print('Armory Warning: ' + oid + ' was not exported')
return
if len(exportMesh.uv_layers) > 2:
print('Armory Warning: ' + oid + ' exceeds maximum of 2 UV Maps supported')
@ -2218,6 +2222,8 @@ class ArmoryExporter:
self.output['world_datas'].append(o)
def export_grease_pencils(self):
return # Disabled for now
gpRef = self.scene.grease_pencil
if gpRef == None or self.scene.gp_export == False:
return

View file

@ -19,7 +19,7 @@ import assets
import make_state
import material.mat_state as mat_state
import material.texture as texture
import material.functions
import material.functions as functions
def parse(nodes, vert, frag, geom, tesc, tese, parse_surface=True, parse_opacity=True, parse_displacement=True):
output_node = node_by_type(nodes, 'OUTPUT_MATERIAL')
@ -38,6 +38,7 @@ def parse_output(node, _vert, _frag, _geom, _tesc, _tese, _parse_surface, _parse
global tese
global parse_surface
global parse_opacity
global parsing_basecol
vert = _vert
frag = _frag
geom = _geom
@ -45,6 +46,7 @@ def parse_output(node, _vert, _frag, _geom, _tesc, _tese, _parse_surface, _parse
tese = _tese
parse_surface = _parse_surface
parse_opacity = _parse_opacity
parsing_basecol = False
# Surface
if parse_surface or parse_opacity:
@ -128,6 +130,7 @@ def write_normal(inp):
normal_written = True
def parse_shader(node, socket):
global parsing_basecol
out_basecol = 'vec3(0.8)'
out_roughness = '0.0'
out_metallic = '0.0'
@ -138,7 +141,9 @@ def parse_shader(node, socket):
if node.node_tree.name.startswith('Armory PBR'):
if parse_surface:
parsing_basecol = True
out_basecol = parse_vector_input(node.inputs[0])
parsing_basecol = False
# TODO: deprecated, occlussion is value instead of vector now
if node.inputs[1].type == 'RGBA':
out_occlusion = '{0}.r'.format(parse_vector_input(node.inputs[1]))
@ -171,7 +176,9 @@ def parse_shader(node, socket):
bc1, rough1, met1, occ1, opac1 = parse_shader_input(node.inputs[1])
bc2, rough2, met2, occ2, opac2 = parse_shader_input(node.inputs[2])
if parse_surface:
parsing_basecol = True
out_basecol = '({0} * {3} + {1} * {2})'.format(bc1, bc2, fac_var, fac_inv_var)
parsing_basecol = False
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)
@ -182,7 +189,9 @@ def parse_shader(node, socket):
bc1, rough1, met1, occ1, opac1 = parse_shader_input(node.inputs[0])
bc2, rough2, met2, occ2, opac2 = parse_shader_input(node.inputs[1])
if parse_surface:
parsing_basecol = True
out_basecol = '({0} + {1})'.format(bc1, bc2)
parsing_basecol = False
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)
@ -192,13 +201,17 @@ def parse_shader(node, socket):
elif node.type == 'BSDF_DIFFUSE':
if parse_surface:
write_normal(node.inputs[2])
parsing_basecol = True
out_basecol = parse_vector_input(node.inputs[0])
parsing_basecol = False
out_roughness = parse_value_input(node.inputs[1])
elif node.type == 'BSDF_GLOSSY':
if parse_surface:
write_normal(node.inputs[2])
parsing_basecol = True
out_basecol = parse_vector_input(node.inputs[0])
parsing_basecol = False
out_roughness = parse_value_input(node.inputs[1])
out_metallic = '1.0'
@ -211,14 +224,18 @@ def parse_shader(node, socket):
if parse_surface:
write_normal(node.inputs[4])
# Revert to glossy
parsing_basecol = True
out_basecol = parse_vector_input(node.inputs[0])
parsing_basecol = False
out_roughness = parse_value_input(node.inputs[1])
out_metallic = '1.0'
elif node.type == 'EMISSION':
if parse_surface:
# Multiply basecol
parsing_basecol = True
out_basecol = parse_vector_input(node.inputs[0])
parsing_basecol = False
strength = parse_value_input(node.inputs[1])
out_basecol = '({0} * {1} * 50.0)'.format(out_basecol, strength)
@ -262,7 +279,9 @@ def parse_shader(node, socket):
elif node.type == 'BSDF_VELVET':
if parse_surface:
write_normal(node.inputs[2])
parsing_basecol = True
out_basecol = parse_vector_input(node.inputs[0])
parsing_basecol = False
out_roughness = '1.0'
out_metallic = '1.0'
@ -398,7 +417,8 @@ def parse_rgb(node, socket):
tex_name = armutils.safe_source_name(node.name)
tex = texture.make_texture(node, tex_name)
if tex != None:
return '{0}.rgb'.format(texture_store(node, tex, tex_name))
to_linear = parsing_basecol and not tex['file'].endswith('.hdr')
return '{0}.rgb'.format(texture_store(node, tex, tex_name, to_linear))
else:
return tovec3([0.0, 0.0, 0.0])
@ -603,7 +623,7 @@ def parse_rgb(node, socket):
def store_var_name(node):
return node_name(node.name) + '_store'
def texture_store(node, tex, tex_name):
def texture_store(node, tex, tex_name, to_linear=False):
mat_state.mat_context['bind_textures'].append(tex)
mat_state.data.add_elem('tex', 2)
curshader.add_uniform('sampler2D {0}'.format(tex_name))
@ -613,7 +633,7 @@ def texture_store(node, tex, tex_name):
uv_name = 'texCoord'
tex_store = store_var_name(node)
curshader.write('vec4 {0} = texture({1}, {2}.xy);'.format(tex_store, tex_name, uv_name))
if not tex['file'].endswith('.hdr'):
if to_linear:
curshader.write('{0}.rgb = pow({0}.rgb, vec3(2.2));'.format(tex_store))
return tex_store
@ -678,24 +698,24 @@ def parse_vector(node, socket):
#obj = node.object
#dupli = node.from_dupli
if socket == node.outputs[0]: # Generated
return 'vec2(0.0)'
return 'vec2(0.0)', 2
elif socket == node.outputs[1]: # Normal
return 'vec2(0.0)'
return 'vec2(0.0)', 2
elif socket == node.outputs[2]: # UV
return 'vec2(0.0)'
return 'texCoord', 2
elif socket == node.outputs[3]: # Object
return 'vec2(0.0)'
return 'vec2(0.0)', 2
elif socket == node.outputs[4]: # Camera
return 'vec2(0.0)'
return 'vec2(0.0)', 2
elif socket == node.outputs[5]: # Window
return 'vec2(0.0)'
return 'vec2(0.0)', 2
elif socket == node.outputs[6]: # Reflection
return 'vec2(0.0)'
return 'vec2(0.0)', 2
elif node.type == 'UVMAP':
#map = node.uv_map
#dupli = node.from_dupli
return 'vec2(0.0)'
return 'vec2(0.0)', 2
elif node.type == 'BUMP':
#invert = node.invert
@ -707,8 +727,7 @@ def parse_vector(node, socket):
return 'n'
elif node.type == 'MAPPING':
# vector = parse_vector_input(node.inputs[0])
return 'vec3(0.0)'
return parse_vector_input(node.inputs[0]), 2
elif node.type == 'NORMAL':
if socket == node.outputs[0]:
@ -718,11 +737,14 @@ def parse_vector(node, socket):
return 'vec3(dot({0}, {1}))'.format(tovec3(node.outputs[0].default_value), nor)
elif node.type == 'NORMAL_MAP':
#space = node.space
#map = node.uv_map
# strength = parse_value_input(node.inputs[0])
parse_normal_map_color_input(node.inputs[1]) # Color
return None
if curshader == tese:
return parse_vector_input(node.inputs[1])
else:
#space = node.space
#map = node.uv_map
# strength = parse_value_input(node.inputs[0])
parse_normal_map_color_input(node.inputs[1]) # Color
return None
elif node.type == 'CURVE_VEC':
# fac = parse_value_input(node.inputs[0])
@ -846,33 +868,33 @@ def parse_value(node, socket):
elif node.type == 'LIGHT_PATH':
if socket == node.outputs[0]: # Is Camera Ray
return '1.0'
elif socket == node.outputs[0]: # Is Shadow Ray
elif socket == node.outputs[1]: # Is Shadow Ray
return '0.0'
elif socket == node.outputs[0]: # Is Diffuse Ray
elif socket == node.outputs[2]: # Is Diffuse Ray
return '1.0'
elif socket == node.outputs[0]: # Is Glossy Ray
elif socket == node.outputs[3]: # Is Glossy Ray
return '1.0'
elif socket == node.outputs[0]: # Is Singular Ray
elif socket == node.outputs[4]: # Is Singular Ray
return '0.0'
elif socket == node.outputs[0]: # Is Reflection Ray
elif socket == node.outputs[5]: # Is Reflection Ray
return '0.0'
elif socket == node.outputs[0]: # Is Transmission Ray
elif socket == node.outputs[6]: # Is Transmission Ray
return '0.0'
elif socket == node.outputs[0]: # Ray Length
elif socket == node.outputs[7]: # Ray Length
return '0.0'
elif socket == node.outputs[0]: # Ray Depth
elif socket == node.outputs[8]: # Ray Depth
return '0.0'
elif socket == node.outputs[0]: # Transparent Depth
elif socket == node.outputs[9]: # Transparent Depth
return '0.0'
elif socket == node.outputs[0]: # Transmission Depth
elif socket == node.outputs[10]: # Transmission Depth
return '0.0'
elif node.type == 'OBJECT_INFO':
if socket == node.outputs[0]: # Object Index
return '0.0'
elif socket == node.outputs[0]: # Material Index
elif socket == node.outputs[1]: # Material Index
return '0.0'
elif socket == node.outputs[0]: # Random
elif socket == node.outputs[2]: # Random
return '0.0'
elif node.type == 'PARTICLE_INFO':

View file

@ -100,6 +100,6 @@ def write_shader(shader, ext, rpass, keep_cache=True):
return
shader_path = mat_state.path + '/' + armutils.safe_source_name(mat_state.material.name) + '_' + rpass + '.' + ext + '.glsl'
assets.add_shader(shader_path)
if not os.path.isfile(shader_path) or keep_cache:
if not os.path.isfile(shader_path) or not keep_cache:
with open(shader_path, 'w') as f:
f.write(shader.get())

View file

@ -181,6 +181,7 @@ def make_deferred(con_mesh):
def make_forward(con_mesh):
make_forward_base(con_mesh)
frag = con_mesh.frag
frag.add_out('vec4 fragColor')
frag.write('fragColor = vec4(direct * lightColor * visibility + indirect * occlusion * envmapStrength, 1.0);')

View file

@ -18,6 +18,8 @@ def make(context_id, rpasses):
parse_opacity = 'translucent' in rpasses
if parse_opacity:
frag.write('vec3 n = vec3(0.0);') # Discard at compile time
frag.write('float dotNV = 0.0;')
frag.write('float opacity;')
if mat_state.data.is_elem('bone'):

View file

@ -26,7 +26,7 @@ def get_rpasses(material):
else:
ar.append('mesh')
if 'mesh' in ar or 'translucent' in ar:
if material.cast_shadow and ('mesh' in ar or 'translucent' in ar):
ar.append('shadowmap')
return ar

View file

@ -236,7 +236,7 @@ class InvalidateMaterialCacheButton(bpy.types.Operator):
bl_label = "Invalidate Cache"
def execute(self, context):
context.object.material.is_cached = False
context.material.is_cached = False
return{'FINISHED'}
class InvalidateGPCacheButton(bpy.types.Operator):
@ -295,7 +295,7 @@ class MaterialPropsPanel(bpy.types.Panel):
layout.prop(mat, 'height_tess_shadows_outer')
layout.prop(mat, 'transluc_shadows')
layout.operator("arm.invalidate_cache")
layout.operator("arm.invalidate_material_cache")
class WorldPropsPanel(bpy.types.Panel):
bl_label = "Armory Props"

View file

@ -40,13 +40,13 @@ def write_probes(image_filepath, disable_hdr, cached_num_mips, generate_radiance
if armutils.get_os() == 'win':
cmft_path = sdk_path + '/armory/tools/cmft/cmft.exe'
kraffiti_path = sdk_path + '/win32/resources/app/extensions/kha/Kha/Kore/Tools/kraffiti/kraffiti.exe'
kraffiti_path = sdk_path + '/win32/Kha/Kore/Tools/kraffiti/kraffiti.exe'
elif armutils.get_os() == 'mac':
cmft_path = sdk_path + '/armory/tools/cmft/cmft-osx'
kraffiti_path = sdk_path + '/"Kode Studio.app"/Contents/Resources/app/extensions/kha/Kha/Kore/Tools/kraffiti/kraffiti-osx'
kraffiti_path = sdk_path + '/"Kode Studio.app"/Contents/Kha/Kore/Tools/kraffiti/kraffiti-osx'
else:
cmft_path = sdk_path + '/armory/tools/cmft/cmft-linux64'
kraffiti_path = sdk_path + '/linux64/resources/app/extensions/kha/Kha/Kore/Tools/kraffiti/kraffiti-linux64'
kraffiti_path = sdk_path + '/linux64/Kha/Kore/Tools/kraffiti/kraffiti-linux64'
output_gama_numerator = '1.0' if disable_hdr else '2.2'
input_file = armutils.safe_assetpath(image_filepath)