armory/blender/arm/material/make.py

129 lines
5.2 KiB
Python
Raw Normal View History

2020-12-30 01:06:54 +01:00
from typing import Dict, List
2016-12-17 15:34:43 +01:00
import bpy
2020-12-30 01:06:54 +01:00
from bpy.types import Material
from bpy.types import Object
import arm.material.cycles as cycles
2017-03-15 12:30:14 +01:00
import arm.material.make_shader as make_shader
import arm.material.mat_batch as mat_batch
2020-12-30 01:06:54 +01:00
import arm.node_utils
import arm.utils
2017-03-14 20:43:54 +01:00
if arm.is_reload(__name__):
2021-08-04 22:49:38 +02:00
cycles = arm.reload_module(cycles)
make_shader = arm.reload_module(make_shader)
mat_batch = arm.reload_module(mat_batch)
arm.node_utils = arm.reload_module(arm.node_utils)
arm.utils = arm.reload_module(arm.utils)
else:
arm.enable_reload(__name__)
2021-08-04 22:49:38 +02:00
2017-03-14 20:43:54 +01:00
2017-11-20 14:32:36 +01:00
def glsl_value(val):
2017-03-14 20:43:54 +01:00
if str(type(val)) == "<class 'bpy_prop_array'>":
res = []
for v in val:
res.append(v)
return res
else:
return val
2017-02-09 22:52:47 +01:00
2020-12-30 01:06:54 +01:00
def parse(material: Material, mat_data, mat_users: Dict[Material, List[Object]], mat_armusers):
2016-12-19 01:25:22 +01:00
wrd = bpy.data.worlds['Arm']
2017-08-21 20:16:06 +02:00
rpdat = arm.utils.get_rp()
2016-12-13 01:09:17 +01:00
2017-03-14 20:43:54 +01:00
# No batch - shader data per material
2017-09-17 16:59:00 +02:00
if material.arm_custom_material != '':
rpasses = ['mesh']
2020-12-30 01:06:54 +01:00
con = {'vertex_elements': []}
con['vertex_elements'].append({'name': 'pos', 'data': 'short4norm'})
con['vertex_elements'].append({'name': 'nor', 'data': 'short2norm'})
con['vertex_elements'].append({'name': 'tex', 'data': 'short2norm'})
con['vertex_elements'].append({'name': 'tex1', 'data': 'short2norm'})
sd = {'contexts': [con]}
2017-09-17 16:59:00 +02:00
shader_data_name = material.arm_custom_material
2020-12-30 01:06:54 +01:00
bind_constants = {'mesh': []}
bind_textures = {'mesh': []}
make_shader.make_instancing_and_skinning(material, mat_users)
2017-09-17 16:59:00 +02:00
elif not wrd.arm_batch_materials or material.name.startswith('armdefault'):
2017-08-21 15:36:21 +02:00
rpasses, shader_data, shader_data_name, bind_constants, bind_textures = make_shader.build(material, mat_users, mat_armusers)
2017-09-17 16:59:00 +02:00
sd = shader_data.sd
2017-03-14 20:43:54 +01:00
else:
rpasses, shader_data, shader_data_name, bind_constants, bind_textures = mat_batch.get(material)
2017-09-17 16:59:00 +02:00
sd = shader_data.sd
2016-12-13 01:09:17 +01:00
2017-03-14 20:43:54 +01:00
# Material
2016-12-19 01:25:22 +01:00
for rp in rpasses:
2020-12-30 01:06:54 +01:00
c = {
'name': rp,
'bind_constants': [] + bind_constants[rp],
'bind_textures': [] + bind_textures[rp],
}
2017-03-14 20:43:54 +01:00
mat_data['contexts'].append(c)
2016-12-17 15:34:43 +01:00
2016-12-19 01:25:22 +01:00
if rp == 'mesh':
2020-12-30 01:06:54 +01:00
c['bind_constants'].append({'name': 'receiveShadow', 'bool': material.arm_receive_shadow})
2016-12-13 01:09:17 +01:00
2017-11-25 20:09:55 +01:00
if material.arm_material_id != 0:
2020-12-30 01:06:54 +01:00
c['bind_constants'].append({'name': 'materialID', 'int': material.arm_material_id})
2017-11-25 20:09:55 +01:00
if material.arm_material_id == 2:
wrd.world_defs += '_Hair'
2020-12-30 01:06:54 +01:00
2017-11-25 20:09:55 +01:00
elif rpdat.rp_sss_state == 'On':
2017-06-27 10:55:46 +02:00
sss = False
2017-11-20 14:32:36 +01:00
sss_node = arm.node_utils.get_node_by_type(material.node_tree, 'SUBSURFACE_SCATTERING')
2020-12-30 01:06:54 +01:00
if sss_node is not None and sss_node.outputs[0].is_linked: # Check linked node
2017-06-27 10:55:46 +02:00
sss = True
2017-11-20 14:32:36 +01:00
sss_node = arm.node_utils.get_node_by_type(material.node_tree, 'BSDF_PRINCIPLED')
2020-12-30 01:06:54 +01:00
if sss_node is not None and sss_node.outputs[0].is_linked and (sss_node.inputs[1].is_linked or sss_node.inputs[1].default_value != 0.0):
2017-06-27 10:55:46 +02:00
sss = True
2017-11-20 14:32:36 +01:00
sss_node = arm.node_utils.get_node_armorypbr(material.node_tree)
2020-12-30 01:06:54 +01:00
if sss_node is not None and sss_node.outputs[0].is_linked and (sss_node.inputs[8].is_linked or sss_node.inputs[8].default_value != 0.0):
2017-07-07 18:21:44 +02:00
sss = True
2020-12-30 01:06:54 +01:00
const = {'name': 'materialID'}
2017-06-27 10:55:46 +02:00
if sss:
2017-05-23 15:01:56 +02:00
const['int'] = 2
2019-01-24 12:47:51 +01:00
else:
const['int'] = 0
c['bind_constants'].append(const)
2017-05-23 15:01:56 +02:00
2017-03-14 20:43:54 +01:00
# TODO: Mesh only material batching
if wrd.arm_batch_materials:
# Set textures uniforms
if len(c['bind_textures']) > 0:
c['bind_textures'] = []
for node in material.node_tree.nodes:
if node.type == 'TEX_IMAGE':
2017-05-13 17:17:43 +02:00
tex_name = arm.utils.safesrc(node.name)
2018-10-26 19:45:07 +02:00
tex = cycles.make_texture(node, tex_name)
2020-12-30 01:06:54 +01:00
# Empty texture
if tex is None:
tex = {'name': tex_name, 'file': ''}
2017-03-14 20:43:54 +01:00
c['bind_textures'].append(tex)
# Set marked inputs as uniforms
for node in material.node_tree.nodes:
for inp in node.inputs:
if inp.is_uniform:
2020-12-30 01:06:54 +01:00
uname = arm.utils.safesrc(inp.node.name) + arm.utils.safesrc(inp.name) # Merge with cycles module
c['bind_constants'].append({'name': uname, cycles.glsl_type(inp.type): glsl_value(inp.default_value)})
2016-12-15 00:18:59 +01:00
2016-12-19 01:25:22 +01:00
elif rp == 'translucent':
2020-12-30 01:06:54 +01:00
c['bind_constants'].append({'name': 'receiveShadow', 'bool': material.arm_receive_shadow})
2018-01-23 15:41:09 +01:00
2019-05-14 11:43:41 +02:00
if wrd.arm_single_data_file:
mat_data['shader'] = shader_data_name
else:
# Make sure that custom materials are not expected to be in .arm format
ext = '' if wrd.arm_minimize and material.arm_custom_material == "" else '.json'
2019-05-14 11:43:41 +02:00
mat_data['shader'] = shader_data_name + ext + '/' + shader_data_name
2016-12-17 15:34:43 +01:00
2017-09-17 16:59:00 +02:00
return sd, rpasses