2017-03-14 20:43:54 +01:00
|
|
|
import os
|
|
|
|
import bpy
|
2017-03-15 12:30:14 +01:00
|
|
|
import arm.utils
|
|
|
|
import arm.assets as assets
|
|
|
|
import arm.material.mat_utils as mat_utils
|
|
|
|
import arm.material.mat_state as mat_state
|
|
|
|
from arm.material.shader_data import ShaderData
|
|
|
|
import arm.material.cycles as cycles
|
|
|
|
import arm.material.make_mesh as make_mesh
|
2017-03-28 14:30:51 +02:00
|
|
|
import arm.material.make_rect as make_rect
|
2017-03-15 12:30:14 +01:00
|
|
|
import arm.material.make_transluc as make_transluc
|
|
|
|
import arm.material.make_overlay as make_overlay
|
|
|
|
import arm.material.make_depth as make_depth
|
|
|
|
import arm.material.make_decal as make_decal
|
|
|
|
import arm.material.make_voxel as make_voxel
|
2018-01-04 16:22:16 +01:00
|
|
|
import arm.api
|
2017-03-14 20:43:54 +01:00
|
|
|
|
|
|
|
rpass_hook = None
|
|
|
|
|
2017-08-21 15:36:21 +02:00
|
|
|
def build(material, mat_users, mat_armusers):
|
2017-03-14 20:43:54 +01:00
|
|
|
mat_state.mat_users = mat_users
|
|
|
|
mat_state.mat_armusers = mat_armusers
|
|
|
|
mat_state.material = material
|
|
|
|
mat_state.nodes = material.node_tree.nodes
|
|
|
|
mat_state.data = ShaderData(material)
|
|
|
|
mat_state.output_node = cycles.node_by_type(mat_state.nodes, 'OUTPUT_MATERIAL')
|
|
|
|
if mat_state.output_node == None:
|
2017-04-21 11:10:49 +02:00
|
|
|
# Place empty material output to keep compiler happy..
|
|
|
|
mat_state.output_node = mat_state.nodes.new('ShaderNodeOutputMaterial')
|
2017-03-14 20:43:54 +01:00
|
|
|
|
|
|
|
wrd = bpy.data.worlds['Arm']
|
2018-01-04 16:22:16 +01:00
|
|
|
rpdat = arm.utils.get_rp()
|
2017-03-14 20:43:54 +01:00
|
|
|
rpasses = mat_utils.get_rpasses(material)
|
2017-10-06 11:16:29 +02:00
|
|
|
matname = arm.utils.safesrc(arm.utils.asset_name(material))
|
2017-12-20 10:19:44 +01:00
|
|
|
rel_path = arm.utils.build_dir() + '/compiled/Shaders/'
|
2017-03-15 12:30:14 +01:00
|
|
|
full_path = arm.utils.get_fp() + '/' + rel_path
|
2017-03-14 20:43:54 +01:00
|
|
|
if not os.path.exists(full_path):
|
|
|
|
os.makedirs(full_path)
|
|
|
|
|
2017-05-25 16:48:41 +02:00
|
|
|
global_elems = []
|
2018-02-16 19:57:27 +01:00
|
|
|
if mat_users != None and material in mat_users:
|
2017-03-14 20:43:54 +01:00
|
|
|
for bo in mat_users[material]:
|
|
|
|
# GPU Skinning
|
2017-04-04 23:11:31 +02:00
|
|
|
if arm.utils.export_bone_data(bo):
|
2017-05-25 16:48:41 +02:00
|
|
|
global_elems.append({'name': 'bone', 'size': 4})
|
|
|
|
global_elems.append({'name': 'weight', 'size': 4})
|
2017-03-14 20:43:54 +01:00
|
|
|
# Instancing
|
2018-08-29 09:35:48 +02:00
|
|
|
if bo.arm_instanced != 'Off' or material.arm_particle_flag:
|
|
|
|
global_elems.append({'name': 'ipos', 'size': 3})
|
|
|
|
if bo.arm_instanced == 'Loc + Rot' or bo.arm_instanced == 'Loc + Rot + Scale':
|
|
|
|
global_elems.append({'name': 'irot', 'size': 3})
|
|
|
|
if bo.arm_instanced == 'Loc + Scale' or bo.arm_instanced == 'Loc + Rot + Scale':
|
|
|
|
global_elems.append({'name': 'iscl', 'size': 3})
|
2017-09-29 01:18:57 +02:00
|
|
|
|
2017-05-25 16:48:41 +02:00
|
|
|
mat_state.data.global_elems = global_elems
|
2017-03-14 20:43:54 +01:00
|
|
|
|
2017-03-21 03:06:38 +01:00
|
|
|
bind_constants = dict()
|
2017-03-14 20:43:54 +01:00
|
|
|
bind_textures = dict()
|
|
|
|
|
|
|
|
for rp in rpasses:
|
|
|
|
|
|
|
|
car = []
|
2017-03-21 03:06:38 +01:00
|
|
|
bind_constants[rp] = car
|
|
|
|
mat_state.bind_constants = car
|
2017-03-14 20:43:54 +01:00
|
|
|
tar = []
|
|
|
|
bind_textures[rp] = tar
|
|
|
|
mat_state.bind_textures = tar
|
|
|
|
|
2018-01-03 15:09:55 +01:00
|
|
|
con = None
|
|
|
|
|
2018-01-04 16:22:16 +01:00
|
|
|
if rpdat.rp_driver != 'Armory' and arm.api.drivers[rpdat.rp_driver]['make_rpass'] != None:
|
|
|
|
con = arm.api.drivers[rpdat.rp_driver]['make_rpass'](rp)
|
2018-01-03 15:09:55 +01:00
|
|
|
|
|
|
|
if con != None:
|
|
|
|
pass
|
|
|
|
|
|
|
|
elif rp == 'mesh':
|
2017-08-21 15:36:21 +02:00
|
|
|
con = make_mesh.make(rp)
|
2017-03-14 20:43:54 +01:00
|
|
|
|
2017-03-28 14:30:51 +02:00
|
|
|
elif rp == 'rect':
|
|
|
|
con = make_rect.make(rp)
|
|
|
|
|
2017-03-14 20:43:54 +01:00
|
|
|
elif rp == 'shadowmap':
|
2017-10-24 13:13:26 +02:00
|
|
|
con = make_depth.make(rp, rpasses, shadowmap=True)
|
2017-03-14 20:43:54 +01:00
|
|
|
|
|
|
|
elif rp == 'translucent':
|
|
|
|
con = make_transluc.make(rp)
|
|
|
|
|
|
|
|
elif rp == 'overlay':
|
|
|
|
con = make_overlay.make(rp)
|
|
|
|
|
|
|
|
elif rp == 'decal':
|
|
|
|
con = make_decal.make(rp)
|
|
|
|
|
|
|
|
elif rp == 'depth':
|
2017-10-24 13:13:26 +02:00
|
|
|
con = make_depth.make(rp, rpasses)
|
2017-03-14 20:43:54 +01:00
|
|
|
|
|
|
|
elif rp == 'voxel':
|
|
|
|
con = make_voxel.make(rp)
|
|
|
|
|
|
|
|
elif rpass_hook != None:
|
|
|
|
con = rpass_hook(rp)
|
2017-05-25 16:48:41 +02:00
|
|
|
|
2017-10-06 11:16:29 +02:00
|
|
|
write_shaders(rel_path, con, rp, matname)
|
2017-03-14 20:43:54 +01:00
|
|
|
|
2017-03-15 12:30:14 +01:00
|
|
|
arm.utils.write_arm(full_path + '/' + matname + '_data.arm', mat_state.data.get())
|
2017-03-14 20:43:54 +01:00
|
|
|
shader_data_name = matname + '_data'
|
2018-08-16 20:48:00 +02:00
|
|
|
shader_data_path = arm.utils.get_fp_build() + '/compiled/Shaders/' + shader_data_name + '.arm'
|
2017-03-14 20:43:54 +01:00
|
|
|
assets.add_shader_data(shader_data_path)
|
|
|
|
|
2017-03-21 03:06:38 +01:00
|
|
|
return rpasses, mat_state.data, shader_data_name, bind_constants, bind_textures
|
2017-03-14 20:43:54 +01:00
|
|
|
|
2017-10-06 11:16:29 +02:00
|
|
|
def write_shaders(rel_path, con, rpass, matname):
|
2017-03-14 20:43:54 +01:00
|
|
|
keep_cache = mat_state.material.is_cached
|
2017-10-06 11:16:29 +02:00
|
|
|
write_shader(rel_path, con.vert, 'vert', rpass, matname, keep_cache=keep_cache)
|
|
|
|
write_shader(rel_path, con.frag, 'frag', rpass, matname, keep_cache=keep_cache)
|
|
|
|
write_shader(rel_path, con.geom, 'geom', rpass, matname, keep_cache=keep_cache)
|
|
|
|
write_shader(rel_path, con.tesc, 'tesc', rpass, matname, keep_cache=keep_cache)
|
|
|
|
write_shader(rel_path, con.tese, 'tese', rpass, matname, keep_cache=keep_cache)
|
2017-03-14 20:43:54 +01:00
|
|
|
|
2017-10-06 11:16:29 +02:00
|
|
|
def write_shader(rel_path, shader, ext, rpass, matname, keep_cache=True):
|
2017-12-20 15:37:58 +01:00
|
|
|
if shader == None or shader.is_linked:
|
2017-03-14 20:43:54 +01:00
|
|
|
return
|
2017-09-29 01:18:57 +02:00
|
|
|
|
|
|
|
# TODO: blend context
|
|
|
|
if mat_state.material.arm_blending and rpass == 'mesh':
|
|
|
|
rpass = 'blend'
|
|
|
|
|
2017-10-06 11:16:29 +02:00
|
|
|
shader_rel_path = rel_path + '/' + matname + '_' + rpass + '.' + ext + '.glsl'
|
2017-03-15 12:30:14 +01:00
|
|
|
shader_path = arm.utils.get_fp() + '/' + shader_rel_path
|
2018-08-16 20:48:00 +02:00
|
|
|
assets.add_shader(shader_path)
|
2017-03-14 20:43:54 +01:00
|
|
|
if not os.path.isfile(shader_path) or not keep_cache:
|
|
|
|
with open(shader_path, 'w') as f:
|
|
|
|
f.write(shader.get())
|