New material bind system
This commit is contained in:
parent
59c043ea22
commit
9d9f39aeb4
|
@ -34,14 +34,9 @@ def add(file):
|
|||
|
||||
def add_khafile_def(d):
|
||||
global khafile_defs
|
||||
global khafile_defs_last
|
||||
if d not in khafile_defs:
|
||||
khafile_defs.append(d)
|
||||
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
if not wrd.arm_recompile_trigger and d not in khafile_defs_last:
|
||||
wrd.arm_recompile_trigger = True
|
||||
|
||||
def add_embedded_data(file):
|
||||
global embedded_data
|
||||
if file not in embedded_data:
|
||||
|
|
|
@ -2068,8 +2068,6 @@ class ArmoryExporter:
|
|||
|
||||
o['cast_shadow'] = objref.cycles.cast_shadow
|
||||
o['near_plane'] = objref.lamp_clip_start
|
||||
if (o['near_plane'] <= 0.11 and o['type'] == 'point'):
|
||||
o['near_plane'] /= 10 # Prevent acne on close surfaces
|
||||
o['far_plane'] = objref.lamp_clip_end
|
||||
o['fov'] = objref.lamp_fov
|
||||
o['shadows_bias'] = objref.lamp_shadows_bias
|
||||
|
@ -2090,6 +2088,8 @@ class ArmoryExporter:
|
|||
if objref.lamp_omni_shadows_cubemap:
|
||||
o['shadowmap_cube'] = True
|
||||
o['shadows_bias'] *= 4.0
|
||||
# if (o['near_plane'] <= 0.11:
|
||||
# o['near_plane'] /= 10 # Prevent acne on close surfaces
|
||||
|
||||
# Parse nodes
|
||||
# Emission only for now
|
||||
|
@ -2265,17 +2265,18 @@ class ArmoryExporter:
|
|||
tang_export = False
|
||||
vcol_export = False
|
||||
vs_str = ''
|
||||
for elem in sd['vertex_structure']:
|
||||
if len(vs_str) > 0:
|
||||
vs_str += ','
|
||||
vs_str += elem['name']
|
||||
|
||||
if elem['name'] == 'tang':
|
||||
tang_export = True
|
||||
elif elem['name'] == 'tex':
|
||||
uv_export = True
|
||||
elif elem['name'] == 'col':
|
||||
vcol_export = True
|
||||
for con in sd['contexts']:
|
||||
for elem in con['vertex_structure']:
|
||||
if len(vs_str) > 0:
|
||||
vs_str += ','
|
||||
vs_str += elem['name']
|
||||
if elem['name'] == 'tang':
|
||||
tang_export = True
|
||||
elif elem['name'] == 'tex':
|
||||
uv_export = True
|
||||
elif elem['name'] == 'col':
|
||||
vcol_export = True
|
||||
# TODO: use array and remove duplis to ensure correctness
|
||||
material.vertex_structure = vs_str
|
||||
|
||||
if (material.export_tangents != tang_export) or \
|
||||
|
@ -2495,19 +2496,20 @@ class ArmoryExporter:
|
|||
self.export_materials()
|
||||
|
||||
# Ensure same vertex structure for object materials
|
||||
for bobject in self.scene.objects:
|
||||
if len(bobject.material_slots) > 1:
|
||||
mat = bobject.material_slots[0].material
|
||||
if mat == None:
|
||||
continue
|
||||
vs = mat.vertex_structure
|
||||
for i in range(len(bobject.material_slots)):
|
||||
nmat = bobject.material_slots[i].material
|
||||
if nmat == None:
|
||||
if not bpy.data.worlds['Arm'].arm_deinterleaved_buffers:
|
||||
for bobject in self.scene.objects:
|
||||
if len(bobject.material_slots) > 1:
|
||||
mat = bobject.material_slots[0].material
|
||||
if mat == None:
|
||||
continue
|
||||
if vs != nmat.vertex_structure:
|
||||
log.warn('Object ' + bobject.name + ' - unable to bind materials to vertex data, please separate object by material for now (select object - edit mode - P - By Material)')
|
||||
break
|
||||
vs = mat.vertex_structure
|
||||
for i in range(len(bobject.material_slots)):
|
||||
nmat = bobject.material_slots[i].material
|
||||
if nmat == None:
|
||||
continue
|
||||
if vs != nmat.vertex_structure:
|
||||
log.warn('Object ' + bobject.name + ' - unable to bind materials to vertex data, please separate object by material (select object - edit mode - P - By Material) or enable Deinterleaved Buffers in Armory Player')
|
||||
break
|
||||
|
||||
self.output['particle_datas'] = []
|
||||
self.export_particle_systems()
|
||||
|
|
|
@ -153,6 +153,16 @@ def on_scene_update_post(context):
|
|||
else:
|
||||
obj.active_material.is_cached = False
|
||||
|
||||
if hasattr(bpy.context, 'window') and bpy.context.window != None:
|
||||
# Invalidate logic node tree cache if it is being edited..
|
||||
areas = bpy.context.window.screen.areas
|
||||
for area in areas:
|
||||
if area.type == 'NODE_EDITOR':
|
||||
for space in area.spaces:
|
||||
if space.type == 'NODE_EDITOR':
|
||||
if space.node_tree != None and space.node_tree.bl_idname == 'ArmLogicTreeType': # and space.node_tree.is_updated:
|
||||
space.node_tree.is_cached = False
|
||||
|
||||
def recache(edit_obj):
|
||||
if edit_obj.type == 'MESH':
|
||||
edit_obj.data.mesh_cached = False
|
||||
|
|
|
@ -11,7 +11,6 @@ def write_data(res, defs, json_data, base_name):
|
|||
shader_id += s
|
||||
|
||||
sres['name'] = shader_id
|
||||
sres['vertex_structure'] = []
|
||||
sres['contexts'] = []
|
||||
|
||||
# Parse
|
||||
|
@ -21,6 +20,7 @@ def write_data(res, defs, json_data, base_name):
|
|||
con['name'] = c['name']
|
||||
con['constants'] = []
|
||||
con['texture_units'] = []
|
||||
con['vertex_structure'] = []
|
||||
|
||||
# Names
|
||||
vert_name = c['vertex_shader'].split('.')[0]
|
||||
|
@ -78,7 +78,7 @@ def write_data(res, defs, json_data, base_name):
|
|||
with open(c['fragment_shader']) as f:
|
||||
frag = f.read().splitlines()
|
||||
|
||||
parse_shader(sres, c, con, defs, vert, len(sres['contexts']) == 1) # Parse attribs for the first vertex shader
|
||||
parse_shader(sres, c, con, defs, vert, True) # Parse attribs for vertex shader
|
||||
parse_shader(sres, c, con, defs, frag, False)
|
||||
|
||||
if 'geometry_shader' in c:
|
||||
|
@ -158,7 +158,7 @@ def parse_shader(sres, c, con, defs, lines, parse_attributes):
|
|||
s = line.split(' ')
|
||||
vd['size'] = int(s[1][-1:])
|
||||
vd['name'] = s[2][:-1]
|
||||
sres['vertex_structure'].append(vd)
|
||||
con['vertex_structure'].append(vd)
|
||||
if vertex_structure_parsing == True and len(line) > 0 and line.startswith('//') == False and line.startswith('in ') == False:
|
||||
vertex_structure_parsed = True
|
||||
|
||||
|
|
|
@ -358,6 +358,7 @@ def play_project(in_viewport):
|
|||
khajs_path = get_khajs_path(in_viewport, state.target)
|
||||
if not wrd.arm_cache_compiler or \
|
||||
not os.path.isfile(khajs_path) or \
|
||||
assets.khafile_defs_last != assets.khafile_defs or \
|
||||
state.last_target != state.target or \
|
||||
state.last_in_viewport != state.in_viewport or \
|
||||
state.target == 'native':
|
||||
|
|
|
@ -31,8 +31,12 @@ def build_node_tree(node_group):
|
|||
pack_path = arm.utils.safestr(bpy.data.worlds['Arm'].arm_project_package)
|
||||
path = 'Sources/' + pack_path.replace('.', '/') + '/node/'
|
||||
group_name = arm.utils.safesrc(node_group.name)
|
||||
file = path + group_name + '.hx'
|
||||
|
||||
with open(path + group_name + '.hx', 'w') as f:
|
||||
if node_group.is_cached and os.path.isfile(file):
|
||||
return
|
||||
|
||||
with open(file, 'w') as f:
|
||||
f.write('package ' + pack_path + '.node;\n\n')
|
||||
f.write('import armory.logicnode.*;\n\n')
|
||||
f.write('@:keep class ' + group_name + ' extends armory.logicnode.LogicTree {\n\n')
|
||||
|
@ -42,6 +46,7 @@ def build_node_tree(node_group):
|
|||
build_node(node, f)
|
||||
f.write('\t}\n')
|
||||
f.write('}\n')
|
||||
node_group.is_cached = True
|
||||
|
||||
def build_node(node, f):
|
||||
global parsed_nodes
|
||||
|
|
|
@ -92,6 +92,7 @@ def build_node_tree(world):
|
|||
wrd.world_defs += '_Probes'
|
||||
if cam.rp_shadowmap == 'None':
|
||||
wrd.world_defs += '_NoShadows'
|
||||
assets.add_khafile_def('arm_no_shadows')
|
||||
if cam.rp_voxelgi:
|
||||
voxelgi = True
|
||||
|
||||
|
|
|
@ -19,16 +19,17 @@ import arm.material.cycles_state as c_state
|
|||
|
||||
basecol_texname = ''
|
||||
|
||||
def parse(nodes, vert, frag, geom, tesc, tese, parse_surface=True, parse_opacity=True, parse_displacement=True, basecol_only=False):
|
||||
def parse(nodes, con, vert, frag, geom, tesc, tese, parse_surface=True, parse_opacity=True, parse_displacement=True, basecol_only=False):
|
||||
output_node = node_by_type(nodes, 'OUTPUT_MATERIAL')
|
||||
if output_node != None:
|
||||
parse_output(output_node, vert, frag, geom, tesc, tese, parse_surface, parse_opacity, parse_displacement, basecol_only)
|
||||
parse_output(output_node, con, vert, frag, geom, tesc, tese, parse_surface, parse_opacity, parse_displacement, basecol_only)
|
||||
|
||||
def parse_output(node, _vert, _frag, _geom, _tesc, _tese, _parse_surface, _parse_opacity, _parse_displacement, _basecol_only):
|
||||
def parse_output(node, _con, _vert, _frag, _geom, _tesc, _tese, _parse_surface, _parse_opacity, _parse_displacement, _basecol_only):
|
||||
global parsed # Compute nodes only once
|
||||
global parents
|
||||
global normal_written # Normal socket is linked on shader node - overwrite fs normal
|
||||
global curshader # Active shader - frag for surface / tese for displacement
|
||||
global con
|
||||
global vert
|
||||
global frag
|
||||
global geom
|
||||
|
@ -40,6 +41,7 @@ def parse_output(node, _vert, _frag, _geom, _tesc, _tese, _parse_surface, _parse
|
|||
global parse_teximage_vector
|
||||
global basecol_only
|
||||
global basecol_texname
|
||||
con = _con
|
||||
vert = _vert
|
||||
frag = _frag
|
||||
geom = _geom
|
||||
|
@ -417,7 +419,7 @@ def parse_rgb(node, socket):
|
|||
elif node.type == 'ATTRIBUTE':
|
||||
# Vcols only for now
|
||||
# node.attribute_name
|
||||
c_state.mat_add_elem('col', 3)
|
||||
con.add_elem('col', 3)
|
||||
return 'vcolor'
|
||||
|
||||
elif node.type == 'RGB':
|
||||
|
@ -686,7 +688,7 @@ def texture_store(node, tex, tex_name, to_linear=False):
|
|||
global parsing_basecol
|
||||
global basecol_texname
|
||||
c_state.mat_bind_texture(tex)
|
||||
c_state.mat_add_elem('tex', 2)
|
||||
con.add_elem('tex', 2)
|
||||
curshader.add_uniform('sampler2D {0}'.format(tex_name))
|
||||
if node.inputs[0].is_linked and parse_teximage_vector:
|
||||
uv_name = parse_vector_input(node.inputs[0])
|
||||
|
@ -713,7 +715,7 @@ def parse_vector(node, socket):
|
|||
|
||||
elif node.type == 'ATTRIBUTE':
|
||||
# UVMaps only for now
|
||||
c_state.mat_add_elem('tex', 2)
|
||||
con.add_elem('tex', 2)
|
||||
mat = c_state.mat_get_material()
|
||||
mat_users = c_state.mat_get_material_users()
|
||||
if mat_users != None and mat in mat_users:
|
||||
|
@ -722,7 +724,7 @@ def parse_vector(node, socket):
|
|||
lays = mat_user.data.uv_layers
|
||||
# Second uvmap referenced
|
||||
if len(lays) > 1 and node.attribute_name == lays[1].name:
|
||||
c_state.mat_add_elem('tex1', 2)
|
||||
con.add_elem('tex1', 2)
|
||||
return 'texCoord1', 2
|
||||
return 'texCoord', 2
|
||||
|
||||
|
@ -769,7 +771,7 @@ def parse_vector(node, socket):
|
|||
elif socket == node.outputs[1]: # Normal
|
||||
return 'vec2(0.0)', 2
|
||||
elif socket == node.outputs[2]: # UV
|
||||
c_state.mat_add_elem('tex', 2)
|
||||
con.add_elem('tex', 2)
|
||||
return 'texCoord', 2
|
||||
elif socket == node.outputs[3]: # Object
|
||||
return 'vec2(0.0)', 2
|
||||
|
@ -868,7 +870,7 @@ def parse_normal_map_color_input(inp, str_inp=None):
|
|||
frag.write('vec3 n = ({0}) * 2.0 - 1.0;'.format(parse_vector_input(inp)))
|
||||
# frag.write('n = normalize(TBN * normalize(n));')
|
||||
frag.write('n = TBN * normalize(n);')
|
||||
c_state.mat_add_elem('tang', 3)
|
||||
con.add_elem('tang', 3)
|
||||
|
||||
parse_teximage_vector = True
|
||||
frag.write_pre = False
|
||||
|
|
|
@ -39,9 +39,6 @@ def mat_name():
|
|||
def mat_batch():
|
||||
return mat_state.batch
|
||||
|
||||
def mat_add_elem(name, size):
|
||||
mat_state.data.add_elem(name, size)
|
||||
|
||||
def mat_bind_texture(tex):
|
||||
mat_state.bind_textures.append(tex)
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ def make(context_id):
|
|||
frag.write('float roughness;')
|
||||
frag.write('float metallic;')
|
||||
frag.write('float occlusion;')
|
||||
cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, parse_opacity=False)
|
||||
cycles.parse(mat_state.nodes, con_decal, vert, frag, geom, tesc, tese, parse_opacity=False)
|
||||
|
||||
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);')
|
||||
|
|
|
@ -130,11 +130,11 @@ def make_base(con_mesh, parse_opacity):
|
|||
frag.write('float occlusion;')
|
||||
if parse_opacity:
|
||||
frag.write('float opacity;')
|
||||
cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity)
|
||||
cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity)
|
||||
if write_material_attribs_post != None:
|
||||
write_material_attribs_post(frag)
|
||||
|
||||
if mat_state.data.is_elem('tex'):
|
||||
if con_mesh.is_elem('tex'):
|
||||
vert.add_out('vec2 texCoord')
|
||||
vert.write('texCoord = tex;')
|
||||
if tese != None:
|
||||
|
@ -143,7 +143,7 @@ def make_base(con_mesh, parse_opacity):
|
|||
make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord'))
|
||||
tese.write_pre = False
|
||||
|
||||
if mat_state.data.is_elem('tex1'):
|
||||
if con_mesh.is_elem('tex1'):
|
||||
vert.add_out('vec2 texCoord1')
|
||||
vert.write('texCoord1 = tex1;')
|
||||
if tese != None:
|
||||
|
@ -151,7 +151,7 @@ def make_base(con_mesh, parse_opacity):
|
|||
make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1'))
|
||||
tese.write_pre = False
|
||||
|
||||
if mat_state.data.is_elem('col'):
|
||||
if con_mesh.is_elem('col'):
|
||||
vert.add_out('vec3 vcolor')
|
||||
vert.write('vcolor = col;')
|
||||
if tese != None:
|
||||
|
@ -159,11 +159,11 @@ def make_base(con_mesh, parse_opacity):
|
|||
make_tess.interpolate(tese, 'vcolor', 3, declare_out=frag.contains('vcolor'))
|
||||
tese.write_pre = False
|
||||
|
||||
if mat_state.data.is_elem('tang'):
|
||||
if con_mesh.is_elem('tang'):
|
||||
if tese != None:
|
||||
vert.add_out('vec3 wnormal')
|
||||
vert.add_out('vec3 wtangent')
|
||||
write_norpos(vert)
|
||||
write_norpos(con_mesh, vert)
|
||||
vert.write('wtangent = normalize(N * tang);')
|
||||
tese.add_out('mat3 TBN')
|
||||
make_tess.interpolate(tese, 'wtangent', 3, normalize=True)
|
||||
|
@ -171,13 +171,13 @@ def make_base(con_mesh, parse_opacity):
|
|||
tese.write('TBN = mat3(wtangent, wbitangent, wnormal);')
|
||||
else:
|
||||
vert.add_out('mat3 TBN')
|
||||
write_norpos(vert, declare=True)
|
||||
write_norpos(con_mesh, vert, declare=True)
|
||||
vert.write('vec3 tangent = normalize(N * tang);')
|
||||
vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));')
|
||||
vert.write('TBN = mat3(tangent, bitangent, wnormal);')
|
||||
else:
|
||||
vert.add_out('vec3 wnormal')
|
||||
write_norpos(vert)
|
||||
write_norpos(con_mesh, vert)
|
||||
frag.write_pre = True
|
||||
frag.write_main_header('vec3 n = normalize(wnormal);')
|
||||
frag.write_pre = False
|
||||
|
@ -188,17 +188,17 @@ def make_base(con_mesh, parse_opacity):
|
|||
tese.write('wposition += wnormal * disp * 0.2;')
|
||||
tese.write('gl_Position = VP * vec4(wposition, 1.0);')
|
||||
|
||||
def write_norpos(vert, declare=False):
|
||||
def write_norpos(con_mesh, vert, declare=False):
|
||||
prep = ''
|
||||
if declare:
|
||||
prep = 'vec3 '
|
||||
vert.write_pre = True
|
||||
if mat_state.data.is_elem('bone'):
|
||||
if con_mesh.is_elem('bone'):
|
||||
make_skin.skin_pos(vert)
|
||||
vert.write(prep + 'wnormal = normalize(N * (nor + 2.0 * cross(skinA.xyz, cross(skinA.xyz, nor) + skinA.w * nor)));')
|
||||
else:
|
||||
vert.write(prep + 'wnormal = normalize(N * nor);')
|
||||
if mat_state.data.is_elem('off'):
|
||||
if con_mesh.is_elem('off'):
|
||||
vert.write('spos.xyz += off;')
|
||||
vert.write_pre = False
|
||||
|
||||
|
@ -269,13 +269,13 @@ def make_deferred_plus(con_mesh):
|
|||
vert.add_out('vec2 texCoord')
|
||||
|
||||
mat_state.data.add_elem('tex', 2) #### Add using cycles.py
|
||||
if mat_state.data.is_elem('tex'):
|
||||
if con_mesh.is_elem('tex'):
|
||||
vert.write('texCoord = tex;')
|
||||
else:
|
||||
vert.write('texCoord = vec2(0.0);')
|
||||
|
||||
vert.add_out('vec3 wnormal')
|
||||
write_norpos(vert)
|
||||
write_norpos(con_mesh, vert)
|
||||
frag.write_pre = True
|
||||
frag.write_main_header('vec3 n = normalize(wnormal);')
|
||||
frag.write_pre = False
|
||||
|
@ -307,18 +307,18 @@ def make_forward_restricted(con_mesh):
|
|||
|
||||
frag.add_include('../../Shaders/compiled.glsl')
|
||||
frag.write('vec3 basecol;')
|
||||
cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, basecol_only=True, parse_opacity=False, parse_displacement=False)
|
||||
cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, basecol_only=True, parse_opacity=False, parse_displacement=False)
|
||||
|
||||
if mat_state.data.is_elem('tex'):
|
||||
if con_mesh.is_elem('tex'):
|
||||
vert.add_out('vec2 texCoord')
|
||||
vert.write('texCoord = tex;')
|
||||
|
||||
if mat_state.data.is_elem('col'):
|
||||
if con_mesh.is_elem('col'):
|
||||
vert.add_out('vec3 vcolor')
|
||||
vert.write('vcolor = col;')
|
||||
|
||||
vert.add_out('vec3 wnormal')
|
||||
write_norpos(vert)
|
||||
write_norpos(con_mesh, vert)
|
||||
frag.write_pre = True
|
||||
frag.write_main_header('vec3 n = normalize(wnormal);')
|
||||
frag.write_pre = False
|
||||
|
|
|
@ -98,7 +98,7 @@ def make_rect(con_rect):
|
|||
frag.write('float occlusion;')
|
||||
|
||||
mat_state.texture_grad = True
|
||||
cycles.parse(mat_state.nodes, vert, frag, None, None, None, parse_opacity=False, parse_displacement=False)
|
||||
cycles.parse(mat_state.nodes, con_rect, vert, frag, None, None, None, parse_opacity=False, parse_displacement=False)
|
||||
mat_state.texture_grad = False
|
||||
|
||||
frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);')
|
||||
|
|
|
@ -24,8 +24,6 @@ def build(material, mat_users, mat_armusers, rid):
|
|||
mat_state.material = material
|
||||
mat_state.nodes = material.node_tree.nodes
|
||||
mat_state.data = ShaderData(material)
|
||||
mat_state.data.add_elem('pos', 3)
|
||||
mat_state.data.add_elem('nor', 3)
|
||||
mat_state.output_node = cycles.node_by_type(mat_state.nodes, 'OUTPUT_MATERIAL')
|
||||
if mat_state.output_node == None:
|
||||
# Place empty material output to keep compiler happy..
|
||||
|
@ -39,15 +37,17 @@ def build(material, mat_users, mat_armusers, rid):
|
|||
if not os.path.exists(full_path):
|
||||
os.makedirs(full_path)
|
||||
|
||||
global_elems = []
|
||||
if mat_users != None:
|
||||
for bo in mat_users[material]:
|
||||
# GPU Skinning
|
||||
if arm.utils.export_bone_data(bo):
|
||||
mat_state.data.add_elem('bone', 4)
|
||||
mat_state.data.add_elem('weight', 4)
|
||||
global_elems.append({'name': 'bone', 'size': 4})
|
||||
global_elems.append({'name': 'weight', 'size': 4})
|
||||
# Instancing
|
||||
if bo.instanced_children or len(bo.particle_systems) > 0:
|
||||
mat_state.data.add_elem('off', 3)
|
||||
global_elems.append({'name': 'off', 'size': 3})
|
||||
mat_state.data.global_elems = global_elems
|
||||
|
||||
bind_constants = dict()
|
||||
bind_textures = dict()
|
||||
|
@ -90,7 +90,7 @@ def build(material, mat_users, mat_armusers, rid):
|
|||
|
||||
elif rpass_hook != None:
|
||||
con = rpass_hook(rp)
|
||||
|
||||
|
||||
write_shaders(rel_path, con, rp)
|
||||
|
||||
arm.utils.write_arm(full_path + '/' + matname + '_data.arm', mat_state.data.get())
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import bpy
|
||||
import arm.material.cycles as cycles
|
||||
import arm.material.mat_state as mat_state
|
||||
import arm.material.mat_utils as mat_utils
|
||||
|
@ -7,7 +8,19 @@ import arm.material.make_mesh as make_mesh
|
|||
import arm.utils
|
||||
|
||||
def make(context_id, rpasses):
|
||||
con_shadowmap = mat_state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False })
|
||||
|
||||
is_disp = mat_utils.disp_linked(mat_state.output_node) and mat_state.material.height_tess_shadows
|
||||
|
||||
vs = [{'name': 'pos', 'size': 3}]
|
||||
if is_disp:
|
||||
vs.append({'name': 'nor', 'size': 3})
|
||||
|
||||
# TODO: interleaved buffer has to match vertex structure of mesh context
|
||||
if not bpy.data.worlds['Arm'].arm_deinterleaved_buffers:
|
||||
vs.append({'name': 'nor', 'size': 3})
|
||||
# vs.append({'name': 'tex', 'size': 2})
|
||||
|
||||
con_shadowmap = mat_state.data.add_context({ 'name': context_id, 'vertex_structure': vs, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False })
|
||||
|
||||
vert = con_shadowmap.make_vert()
|
||||
frag = con_shadowmap.make_frag()
|
||||
|
@ -23,7 +36,7 @@ def make(context_id, rpasses):
|
|||
# TODO: pass vbuf with proper struct
|
||||
if gapi.startswith('direct3d'):
|
||||
vert.write('vec3 t1 = nor; // TODO: Temp for d3d')
|
||||
if mat_state.data.is_elem('tex'):
|
||||
if con_shadowmap.is_elem('tex'):
|
||||
vert.write('vec2 t2 = tex; // TODO: Temp for d3d')
|
||||
|
||||
parse_opacity = 'translucent' in rpasses
|
||||
|
@ -32,13 +45,13 @@ def make(context_id, rpasses):
|
|||
frag.write('float dotNV;')
|
||||
frag.write('float opacity;')
|
||||
|
||||
if mat_state.data.is_elem('bone'):
|
||||
if con_shadowmap.is_elem('bone'):
|
||||
make_skin.skin_pos(vert)
|
||||
|
||||
if mat_state.data.is_elem('off'):
|
||||
if con_shadowmap.is_elem('off'):
|
||||
vert.write('spos.xyz += off;')
|
||||
|
||||
if mat_utils.disp_linked(mat_state.output_node) and mat_state.material.height_tess_shadows:
|
||||
if is_disp:
|
||||
tesc = con_shadowmap.make_tesc()
|
||||
tese = con_shadowmap.make_tese()
|
||||
tesc.ins = vert.outs
|
||||
|
@ -62,23 +75,23 @@ def make(context_id, rpasses):
|
|||
make_tess.interpolate(tese, 'wposition', 3)
|
||||
make_tess.interpolate(tese, 'wnormal', 3, normalize=True)
|
||||
|
||||
cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity)
|
||||
cycles.parse(mat_state.nodes, con_shadowmap, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity)
|
||||
|
||||
if mat_state.data.is_elem('tex'):
|
||||
if con_shadowmap.is_elem('tex'):
|
||||
vert.add_out('vec2 texCoord')
|
||||
vert.write('texCoord = tex;')
|
||||
tese.write_pre = True
|
||||
make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord'))
|
||||
tese.write_pre = False
|
||||
|
||||
if mat_state.data.is_elem('tex1'):
|
||||
if con_shadowmap.is_elem('tex1'):
|
||||
vert.add_out('vec2 texCoord1')
|
||||
vert.write('texCoord1 = tex1;')
|
||||
tese.write_pre = True
|
||||
make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1'))
|
||||
tese.write_pre = False
|
||||
|
||||
if mat_state.data.is_elem('col'):
|
||||
if con_shadowmap.is_elem('col'):
|
||||
vert.add_out('vec3 vcolor')
|
||||
vert.write('vcolor = col;')
|
||||
tese.write_pre = True
|
||||
|
@ -95,17 +108,17 @@ def make(context_id, rpasses):
|
|||
vert.write('gl_Position = LWVP * spos;')
|
||||
|
||||
if parse_opacity:
|
||||
cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=True)
|
||||
cycles.parse(mat_state.nodes, con_shadowmap, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=True)
|
||||
|
||||
if mat_state.data.is_elem('tex'):
|
||||
if con_shadowmap.is_elem('tex'):
|
||||
vert.add_out('vec2 texCoord')
|
||||
vert.write('texCoord = tex;')
|
||||
|
||||
if mat_state.data.is_elem('tex1'):
|
||||
if con_shadowmap.is_elem('tex1'):
|
||||
vert.add_out('vec2 texCoord1')
|
||||
vert.write('texCoord1 = tex1;')
|
||||
|
||||
if mat_state.data.is_elem('col'):
|
||||
if con_shadowmap.is_elem('col'):
|
||||
vert.add_out('vec3 vcolor')
|
||||
vert.write('vcolor = col;')
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ def make(context_id):
|
|||
|
||||
vert.add_include('../../Shaders/compiled.glsl')
|
||||
|
||||
if mat_state.data.is_elem('tex'):
|
||||
if con_voxel.is_elem('tex'):
|
||||
vert.add_out('vec2 texCoordGeom')
|
||||
vert.write('texCoordGeom = tex;')
|
||||
|
||||
|
@ -46,7 +46,7 @@ def make(context_id):
|
|||
geom.add_out('vec3 wnormal')
|
||||
if is_shadows:
|
||||
geom.add_out('vec4 lampPos')
|
||||
if mat_state.data.is_elem('tex'):
|
||||
if con_voxel.is_elem('tex'):
|
||||
geom.add_out('vec2 texCoord')
|
||||
|
||||
geom.write('const vec3 p1 = wpositionGeom[1] - wpositionGeom[0];')
|
||||
|
@ -57,7 +57,7 @@ def make(context_id):
|
|||
geom.write(' wnormal = wnormalGeom[i];')
|
||||
if is_shadows:
|
||||
geom.write(' lampPos = lampPosGeom[i];')
|
||||
if mat_state.data.is_elem('tex'):
|
||||
if con_voxel.is_elem('tex'):
|
||||
geom.write(' texCoord = texCoordGeom[i];')
|
||||
geom.write(' if (p.z > p.x && p.z > p.y) {')
|
||||
geom.write(' gl_Position = vec4(wposition.x, wposition.y, 0.0, 1.0);')
|
||||
|
@ -110,7 +110,7 @@ def make(context_id):
|
|||
frag.write_pre = False
|
||||
frag.write('float dotNV = 0.0;')
|
||||
frag.write('float dotNL = max(dot(wnormal, l), 0.0);')
|
||||
cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, parse_opacity=False, parse_displacement=False)
|
||||
cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=False, parse_displacement=False)
|
||||
frag.write('vec3 color;')
|
||||
frag.write('if (lightShadow > 0) color = basecol * visibility * lightColor * dotNL * attenuate(distance(wposition * voxelgiDimensions.x, lightPos));')
|
||||
frag.write('else color = (basecol - 1.0);') # Emission only when no lamp or shadowmap is present
|
||||
|
|
|
@ -24,7 +24,7 @@ def make(context_id):
|
|||
|
||||
vert.add_include('../../Shaders/compiled.glsl')
|
||||
|
||||
if mat_state.data.is_elem('tex'):
|
||||
if con_voxel.is_elem('tex'):
|
||||
vert.add_out('vec2 texCoordGeom')
|
||||
vert.write('texCoordGeom = tex;')
|
||||
|
||||
|
@ -35,7 +35,7 @@ def make(context_id):
|
|||
geom.add_out('vec3 wposition')
|
||||
geom.add_out('vec3 wnormal')
|
||||
|
||||
if mat_state.data.is_elem('tex'):
|
||||
if con_voxel.is_elem('tex'):
|
||||
geom.add_out('vec2 texCoord')
|
||||
|
||||
geom.write('const vec3 p1 = wpositionGeom[1] - wpositionGeom[0];')
|
||||
|
@ -44,7 +44,7 @@ def make(context_id):
|
|||
geom.write('for (uint i = 0; i < 3; ++i) {')
|
||||
geom.write(' wposition = wpositionGeom[i];')
|
||||
geom.write(' wnormal = wnormalGeom[i];')
|
||||
if mat_state.data.is_elem('tex'):
|
||||
if con_voxel.is_elem('tex'):
|
||||
geom.write(' texCoord = texCoordGeom[i];')
|
||||
geom.write(' if (p.z > p.x && p.z > p.y) {')
|
||||
geom.write(' gl_Position = vec4(wposition.x, wposition.y, 0.0, 1.0);')
|
||||
|
@ -82,7 +82,7 @@ def make(context_id):
|
|||
frag.write_pre = False
|
||||
frag.write('float dotNV = 0.0;')
|
||||
# frag.write('float dotNL = max(dot(wnormal, l), 0.0);')
|
||||
cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, parse_opacity=False, parse_displacement=False)
|
||||
cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=False, parse_displacement=False)
|
||||
|
||||
|
||||
# frag.write('vec3 color = texture(voxels, voxel).rgb / 2.0 + indirectDiffuseLight(wnormal, wposition / voxelgiDimensions.x).rgb * basecol;')
|
||||
|
|
|
@ -88,7 +88,7 @@ class Shader:
|
|||
out_ext = ''
|
||||
|
||||
if self.shader_type == 'vert' and self.vertex_structure_as_vsinput: # Vertex structure as vertex shader input
|
||||
vs = self.context.shader_data['vertex_structure']
|
||||
vs = self.context.data['vertex_structure']
|
||||
for e in vs:
|
||||
self.add_in('vec' + str(e['size']) + ' ' + e['name'])
|
||||
|
||||
|
|
|
@ -6,47 +6,23 @@ class ShaderData:
|
|||
def __init__(self, material):
|
||||
self.material = material
|
||||
self.contexts = []
|
||||
self.global_elems = [] # bone, weight, off
|
||||
self.sd = {}
|
||||
self.data = {}
|
||||
self.data['shader_datas'] = [self.sd]
|
||||
self.matname = arm.utils.safesrc(material.name)
|
||||
self.sd['name'] = self.matname + '_data'
|
||||
self.sd['vertex_structure'] = []
|
||||
self.sd['contexts'] = []
|
||||
|
||||
def add_elem(self, name, size):
|
||||
elem = { 'name': name, 'size': size }
|
||||
if elem not in self.sd['vertex_structure']:
|
||||
self.sd['vertex_structure'].append(elem)
|
||||
|
||||
def is_elem(self, name):
|
||||
for elem in self.sd['vertex_structure']:
|
||||
if elem['name'] == name:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_elem(self, name):
|
||||
for elem in self.sd['vertex_structure']:
|
||||
if elem['name'] == name:
|
||||
return elem
|
||||
return None
|
||||
|
||||
def add_context(self, props):
|
||||
con = ShaderContext(self.material, self.sd, props)
|
||||
if con not in self.sd['contexts']:
|
||||
for elem in self.global_elems:
|
||||
con.add_elem(elem['name'], elem['size'])
|
||||
self.sd['contexts'].append(con.get())
|
||||
return con
|
||||
|
||||
def get(self):
|
||||
# TODO: temporary, Sort vertex data
|
||||
for sd in self.data['shader_datas']:
|
||||
vs = []
|
||||
ar = ['pos', 'nor', 'tex', 'tex1', 'col', 'tang', 'bone', 'weight', 'off']
|
||||
for ename in ar:
|
||||
elem = self.get_elem(ename)
|
||||
if elem != None:
|
||||
vs.append(elem)
|
||||
sd['vertex_structure'] = vs
|
||||
return self.data
|
||||
|
||||
class ShaderContext:
|
||||
|
@ -65,6 +41,10 @@ class ShaderContext:
|
|||
self.data['depth_write'] = props['depth_write']
|
||||
self.data['compare_mode'] = props['compare_mode']
|
||||
self.data['cull_mode'] = props['cull_mode']
|
||||
if 'vertex_structure' in props:
|
||||
self.data['vertex_structure'] = props['vertex_structure']
|
||||
else:
|
||||
self.data['vertex_structure'] = [{'name': 'pos', 'size': 3}, {'name': 'nor', 'size': 3}]
|
||||
if 'blend_source' in props:
|
||||
self.data['blend_source'] = props['blend_source']
|
||||
if 'blend_destination' in props:
|
||||
|
@ -91,6 +71,34 @@ class ShaderContext:
|
|||
self.data['constants'] = []
|
||||
self.constants = self.data['constants']
|
||||
|
||||
def add_elem(self, name, size):
|
||||
elem = { 'name': name, 'size': size }
|
||||
if elem not in self.data['vertex_structure']:
|
||||
self.data['vertex_structure'].append(elem)
|
||||
self.sort_vs()
|
||||
|
||||
def sort_vs(self):
|
||||
# TODO: sort vertex data
|
||||
vs = []
|
||||
ar = ['pos', 'nor', 'tex', 'tex1', 'col', 'tang', 'bone', 'weight', 'off']
|
||||
for ename in ar:
|
||||
elem = self.get_elem(ename)
|
||||
if elem != None:
|
||||
vs.append(elem)
|
||||
self.data['vertex_structure'] = vs
|
||||
|
||||
def is_elem(self, name):
|
||||
for elem in self.data['vertex_structure']:
|
||||
if elem['name'] == name:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_elem(self, name):
|
||||
for elem in self.data['vertex_structure']:
|
||||
if elem['name'] == name:
|
||||
return elem
|
||||
return None
|
||||
|
||||
def get(self):
|
||||
return self.data
|
||||
|
||||
|
|
|
@ -493,6 +493,7 @@ def init_properties():
|
|||
bpy.types.World.generate_voxelgi_dimensions = bpy.props.FloatVectorProperty(name="Dimensions", description="Voxelization bounds", size=3, default=[16, 16, 16], update=assets.invalidate_shader_cache)
|
||||
# For material
|
||||
bpy.types.NodeSocket.is_uniform = bpy.props.BoolProperty(name="Is Uniform", description="Mark node sockets to be processed as material uniforms", default=False)
|
||||
bpy.types.NodeTree.is_cached = bpy.props.BoolProperty(name="Node Tree Cached", description="No need to reexport node tree", default=False)
|
||||
# bpy.types.Node.is_uniform = bpy.props.BoolProperty(name="Is Uniform", description="Mark node values to be processed as material uniforms", default=False)
|
||||
bpy.types.Material.signature = bpy.props.StringProperty(name="Signature", description="Unique string generated from material nodes", default="")
|
||||
bpy.types.Material.is_cached = bpy.props.BoolProperty(name="Material Cached", description="No need to reexport material data", default=False, update=update_mat_cache)
|
||||
|
|
|
@ -42,9 +42,6 @@ let project = new Project('""" + arm.utils.safestr(wrd.arm_project_name) + """')
|
|||
project.addSources('Sources');
|
||||
""")
|
||||
|
||||
# TODO: Move to khamake
|
||||
f.write("project.addDefine('arm_" + arm.utils.get_gapi() + "');\n")
|
||||
|
||||
# TODO: Khamake bug workaround - assets & shaders located in folder starting with '.' get discarded - copy them to project
|
||||
check_dot_path = False
|
||||
if '/.' in sdk_path:
|
||||
|
@ -74,7 +71,7 @@ project.addSources('Sources');
|
|||
f.write('project.addLibrary("{0}");\n'.format(lib.name))
|
||||
|
||||
if export_physics:
|
||||
f.write("project.addDefine('arm_physics');\n")
|
||||
assets.add_khafile_def('arm_physics')
|
||||
f.write(add_armory_library(sdk_path + '/lib/', 'haxebullet'))
|
||||
if state.target == 'krom' or state.target == 'html5':
|
||||
ammojs_path = sdk_path + '/lib/haxebullet/js/ammo/ammo.js'
|
||||
|
@ -82,7 +79,7 @@ project.addSources('Sources');
|
|||
f.write(add_assets(ammojs_path))
|
||||
|
||||
if export_navigation:
|
||||
f.write("project.addDefine('arm_navigation');\n")
|
||||
assets.add_khafile_def('arm_navigation')
|
||||
f.write(add_armory_library(sdk_path + '/lib/', 'haxerecast'))
|
||||
if state.target == 'krom' or state.target == 'html5':
|
||||
recastjs_path = sdk_path + '/lib/haxerecast/js/recast/recast.js'
|
||||
|
@ -94,7 +91,7 @@ project.addSources('Sources');
|
|||
|
||||
if wrd.arm_cache_compiler and (is_play or (state.target == 'html5' and not is_publish)):
|
||||
# Load shaders manually
|
||||
f.write("project.addDefine('arm_debug');\n")
|
||||
assets.add_khafile_def('arm_debug')
|
||||
|
||||
for ref in shader_references:
|
||||
f.write("project.addShaders('" + ref + "');\n")
|
||||
|
@ -108,7 +105,7 @@ project.addSources('Sources');
|
|||
f.write(add_assets(ref))
|
||||
|
||||
if wrd.arm_play_console:
|
||||
f.write("project.addDefine('arm_profile');\n")
|
||||
assets.add_khafile_def('arm_profile')
|
||||
|
||||
if wrd.arm_play_console or wrd.arm_ui:
|
||||
f.write(add_armory_library(sdk_path, 'lib/zui'))
|
||||
|
@ -119,19 +116,19 @@ project.addSources('Sources');
|
|||
f.write(add_armory_library(sdk_path, 'lib/hscript'))
|
||||
|
||||
if wrd.arm_minimize == False:
|
||||
f.write("project.addDefine('arm_json');\n")
|
||||
assets.add_khafile_def('arm_json')
|
||||
|
||||
if wrd.arm_deinterleaved_buffers == True:
|
||||
f.write("project.addDefine('arm_deinterleaved');\n")
|
||||
assets.add_khafile_def('arm_deinterleaved')
|
||||
|
||||
if wrd.arm_batch_meshes == True:
|
||||
f.write("project.addDefine('arm_batch');\n")
|
||||
assets.add_khafile_def('arm_batch')
|
||||
|
||||
if wrd.arm_stream_scene:
|
||||
f.write("project.addDefine('arm_stream');\n")
|
||||
assets.add_khafile_def('arm_stream')
|
||||
|
||||
if wrd.generate_gpu_skin == False:
|
||||
f.write("project.addDefine('arm_cpu_skin');\n")
|
||||
assets.add_khafile_def('arm_cpu_skin')
|
||||
|
||||
for d in assets.khafile_defs:
|
||||
f.write("project.addDefine('" + d + "');\n")
|
||||
|
|
Loading…
Reference in a new issue