New material builder progress

This commit is contained in:
Lubos Lenco 2016-12-19 01:25:22 +01:00
parent 19777385e5
commit e67172db9f
19 changed files with 683 additions and 482 deletions

View file

@ -217,6 +217,10 @@ void main() {
indirect = indirect * envmapStrength;// * lightColor;
vec4 premultipliedReflect = vec4(vec3(direct * visibility + indirect * occlusion), matColor.a);
#ifdef _OpacTex
@ -231,10 +235,6 @@ void main() {
float a = min(1.0, premultipliedReflect.a) * 8.0 + 0.01;
float b = -fragZ * 0.95 + 1.0;
float w = clamp(a * a * a * 1e8 * b * b * b, 1e-2, 3e2);
// accum = premultipliedReflect * w;
// revealage = premultipliedReflect.a;
// RT0 = vec4(C * w, a)
// RT1 = vec4(vec3(a * w), 1)
fragColor[0] = vec4(premultipliedReflect.rgb * w, premultipliedReflect.a);
fragColor[1] = vec4(premultipliedReflect.a * w, 0.0, 0.0, 1.0);
}

View file

@ -151,6 +151,23 @@ def check_camera(self):
def tess_enabled(target):
return target == 'krom' or target == 'native'
def is_object_animation_enabled(bobject):
# Checks if animation is present and enabled
if bobject.object_animation_enabled == False or bobject.type == 'ARMATURE' or bobject.type == 'BONE':
return False
if bobject.animation_data and bobject.animation_data.action:
return True
return False
def is_bone_animation_enabled(bobject):
# Checks if animation is present and enabled for parented armature
if bobject.parent and bobject.parent.type == 'ARMATURE':
if bobject.parent.bone_animation_enabled == False:
return False
if bobject.parent.animation_data and bobject.parent.animation_data.action:
return True
return False
def register():
global krom_found
global glslver

View file

@ -2122,8 +2122,6 @@ class ArmoryExporter:
wrd = bpy.data.worlds['Arm']
if material.skip_context != '':
o['skip_context'] = material.skip_context
elif not material.cast_shadow:
o['skip_context'] = ArmoryExporter.shadows_context
if material.override_cull or wrd.force_no_culling:
o['override_context'] = {}
@ -2137,7 +2135,7 @@ class ArmoryExporter:
if wrd.arm_material_level == 'Restricted':
self.post_export_material(material, o)
else:
sd = make_material_full.parse(material, o)
sd = make_material_full.parse(material, o, self.materialToObjectDict, ArmoryExporter.renderpath_id)
uv_export = False
tan_export = False
@ -2522,7 +2520,7 @@ class ArmoryExporter:
def post_export_object(self, bobject, o, type):
# Animation setup
if self.is_bone_animation_enabled(bobject) or self.is_object_animation_enabled(bobject):
if armutils.is_bone_animation_enabled(bobject) or armutils.is_object_animation_enabled(bobject):
x = {}
if len(bobject.my_cliptraitlist) > 0:
# Edit clips enabled
@ -2547,7 +2545,7 @@ class ArmoryExporter:
x['max_bones'] = bpy.data.worlds['Arm'].generate_gpu_skin_max_bones
else:
# Export default clip, taking full action
if self.is_bone_animation_enabled(bobject):
if armutils.is_bone_animation_enabled(bobject):
begin_frame, end_frame = self.get_action_framerange(bobject.parent.animation_data.action)
else:
begin_frame, end_frame = self.get_action_framerange(bobject.animation_data.action)
@ -2739,23 +2737,6 @@ class ArmoryExporter:
co['influence'] = constr.influence
o['constraints'].append(co)
def is_object_animation_enabled(self, bobject):
# Checks if animation is present and enabled
if bobject.object_animation_enabled == False or bobject.type == 'ARMATURE' or bobject.type == 'BONE':
return False
if bobject.animation_data and bobject.animation_data.action:
return True
return False
def is_bone_animation_enabled(self, bobject):
# Checks if animation is present and enabled for parented armature
if bobject.parent and bobject.parent.type == 'ARMATURE':
if bobject.parent.bone_animation_enabled == False:
return False
if bobject.parent.animation_data and bobject.parent.animation_data.action:
return True
return False
def post_export_material(self, material, o):
defs = []
@ -2947,7 +2928,7 @@ class ArmoryExporter:
if ob.instanced_children or len(ob.particle_systems) > 0:
defs.append('_Instancing')
# GPU Skinning
if ob.find_armature() and self.is_bone_animation_enabled(ob) and bpy.data.worlds['Arm'].generate_gpu_skin == True:
if ob.find_armature() and armutils.is_bone_animation_enabled(ob) and bpy.data.worlds['Arm'].generate_gpu_skin == True:
defs.append('_Skinning')
# Perform billboarding constraint in shader
if len(ob.constraints) > 0 and ob.constraints[0].type == 'TRACK_TO' and ob.constraints[0].target != None and \

View file

@ -16,10 +16,10 @@
#
import armutils
import assets
import material.make_texture as make_texture
import make_state
import material.mat_state as mat_state
import material.texture as texture
import material.functions
import make_state as state
def parse(nodes, vert, frag, geom, tesc, tese, parse_surface=True):
output_node = node_by_type(nodes, 'OUTPUT_MATERIAL')
@ -59,7 +59,7 @@ def parse_output(node, _vert, _frag, _geom, _tesc, _tese, parse_surface):
# parse_volume_input(node.inputs[1])
# Displacement
if armutils.tess_enabled(state.target) and node.inputs[2].is_linked and tese != None:
if armutils.tess_enabled(make_state.target) and node.inputs[2].is_linked and tese != None:
parsed = []
parents = []
normal_written = False
@ -128,10 +128,18 @@ def parse_shader(node, socket):
if node.type == 'GROUP':
if node.node_tree.name.startswith('Armory PBR'):
out_basecol = parse_vector_input(node.inputs[0])
# 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]))
else:
out_occlusion = parse_value_input(node.inputs[1])
if node.inputs[2].is_linked or node.inputs[2].default_value != 1.0:
out_occlusion = '({0} * {1})'.format(out_occlusion, parse_value_input(node.inputs[2]))
out_roughness = parse_value_input(node.inputs[3])
if node.inputs[4].is_linked or node.inputs[4].default_value != 1.0:
out_roughness = '({0} * {1})'.format(out_roughness, parse_value_input(node.inputs[4]))
out_metallic = parse_value_input(node.inputs[5])
out_occlusion = parse_value_input(node.inputs[1])
parse_normal_map_color_input(node.inputs[6])
parse_normal_map_color_input(node.inputs[6], node.inputs[7])
else:
return parse_group(node, socket)
@ -257,7 +265,11 @@ def write_result(l):
res = parse_vector(l.from_node, l.from_socket)
if res == None:
return None
curshader.write('vec3 {0} = {1};'.format(res_var, res))
size = 3
if isinstance(res, tuple):
size = res[1]
res = res[0]
curshader.write('vec{2} {0} = {1};'.format(res_var, res, size))
elif st == 'VALUE':
res = parse_value(l.from_node, l.from_socket)
if res == None:
@ -296,7 +308,7 @@ def parse_rgb(node, socket):
# Vcols only for now
# node.attribute_name
mat_state.data.add_elem('col', 3)
return 'color'
return 'vcolor'
elif node.type == 'RGB':
return tovec3(socket.default_value)
@ -344,12 +356,16 @@ def parse_rgb(node, socket):
elif node.type == 'TEX_IMAGE':
tex_name = armutils.safe_source_name(node.name)
tex = make_texture.make_texture(node, tex_name)
tex = texture.make_texture(node, tex_name)
if tex != None:
mat_state.mat_context['bind_textures'].append(tex)
mat_state.data.add_elem('tex', 2)
curshader.add_uniform('sampler2D {0}'.format(tex_name))
return 'texture({0}, texCoord).rgb'.format(tex_name)
if node.inputs[0].is_linked:
uv_name = parse_vector_input(node.inputs[0])
else:
uv_name = 'texCoord'
return 'texture({0}, {1}.xy).rgb'.format(tex_name, uv_name)
else:
return tovec3([0.0, 0.0, 0.0])
@ -560,8 +576,18 @@ def parse_vector(node, socket):
return parse_input_group(node, socket)
elif node.type == 'ATTRIBUTE':
# Vector
pass
# UVMaps only for now
mat = mat_state.material
mat_users = mat_state.mat_users
if mat in mat_users:
mat_user = mat_users[mat][0]
if hasattr(mat_user.data, 'uv_layers'): # No uvlayers for Curve
lays = mat_user.data.uv_layers
# Second uvmap referenced
if len(lays) > 1 and node.attribute_name == lays[1].name:
mat_state.data.add_elem('tex1', 2)
return 'texCoord1', 2
return 'texCoord', 2
elif node.type == 'CAMERA':
# View Vector
@ -683,7 +709,7 @@ def parse_vector(node, socket):
elif op == 'NORMALIZE':
return 'normalize({0})'.format(vec1)
def parse_normal_map_color_input(inp):
def parse_normal_map_color_input(inp, str_inp=None):
if inp.is_linked == False:
return
frag.write_pre = True
@ -714,7 +740,10 @@ def parse_value(node, socket):
if node.node_tree.name.startswith('Armory PBR'):
# Displacement
if socket == node.outputs[1]:
return parse_value_input(node.inputs[10])
res = parse_value_input(node.inputs[10])
if node.inputs[11].is_linked or node.inputs[11].default_value != 1.0:
res = "({0} * {1})".format(res, parse_value_input(node.inputs[11]))
return res
else:
return None
else:
@ -724,13 +753,12 @@ def parse_value(node, socket):
return parse_input_group(node, socket)
elif node.type == 'ATTRIBUTE':
# Fac
# Pass time till drivers are implemented
if node.attribute_name == 'time':
curshader.add_uniform('float time', link='_time')
return 'time'
else:
return '1.0'
return None
elif node.type == 'CAMERA':
# View Z Depth

View file

@ -1,103 +1,116 @@
import bpy
import armutils
import os
import exporter
import assets
from material.shader_data import ShaderData
import material.make_forward as make_forward
import material.make_deferred as make_deferred
import material.mat_state as state
import material.cycles as cycles
import material.mat_state as mat_state
import material.mat_utils as mat_utils
import material.make_mesh as make_mesh
import material.make_shadows as make_shadows
import material.make_transluc as make_transluc
def parse(material, mat_data):
state.material = material
state.nodes = material.node_tree.nodes
state.mat_data = mat_data
def parse(material, mat_data, mat_users, rid):
wrd = bpy.data.worlds['Arm']
mat_state.material = material
mat_state.nodes = material.node_tree.nodes
mat_state.mat_data = mat_data
mat_state.mat_users = mat_users
mat_state.output_node = cycles.node_by_type(mat_state.nodes, 'OUTPUT_MATERIAL')
if mat_state.output_node == None:
return None
mat_state.path = armutils.get_fp() + '/build/compiled/ShaderRaws/' + material.name
if not os.path.exists(mat_state.path):
os.makedirs(mat_state.path)
state.path = armutils.get_fp() + '/build/compiled/ShaderRaws/' + material.name
if not os.path.exists(state.path):
os.makedirs(state.path)
mat_state.data = ShaderData(material)
mat_state.data.add_elem('pos', 3)
mat_state.data.add_elem('nor', 3)
state.data = ShaderData(material)
state.data.add_elem('pos', 3)
state.data.add_elem('nor', 3)
for bo in mat_users[material]:
# GPU Skinning
if bo.find_armature() and armutils.is_bone_animation_enabled(bo) and wrd.generate_gpu_skin == True:
mat_state.data.add_elem('bone', 4)
mat_state.data.add_elem('weight', 4)
# Instancing
if bo.instanced_children or len(bo.particle_systems) > 0:
mat_state.data.add_elem('off', 3)
rid = exporter.ArmoryExporter.renderpath_id
if rid == 'forward':
make_context = make_forward
elif rid == 'deferred':
make_context = make_deferred
rpasses = exporter.ArmoryExporter.renderpath_passes
mesh_context_id = exporter.ArmoryExporter.mesh_context
shadows_context_id = exporter.ArmoryExporter.shadows_context
rpasses = mat_utils.get_rpasses(material)
for rp in rpasses:
if rp == mesh_context_id:
c = make_mat_context(rp)
c = {}
c['name'] = rp
c['bind_constants'] = []
c['bind_textures'] = []
mat_state.mat_data['contexts'].append(c)
mat_state.mat_context = c
if rp == 'mesh':
const = {}
const['name'] = 'receiveShadow'
const['bool'] = material.receive_shadow
c['bind_constants'].append(const)
state.mat_context = c
con = make_context.mesh(rp)
con = make_mesh.make(rp, rid)
elif rp == shadows_context_id:
c = make_mat_context(rp)
state.mat_context = c
con = make_context.shadows(rp)
elif rp == 'shadows':
con = make_shadows.make(rp)
else:
continue
elif rp == 'translucent':
const = {}
const['name'] = 'receiveShadow'
const['bool'] = material.receive_shadow
c['bind_constants'].append(const)
con = make_transluc.make(rp)
elif rp == 'overlay':
con = make_overlay.make(rp)
elif rp == 'decal':
con = make_decal.make(rp)
elif rp == 'depth':
con = make_depth.make(rp)
write_shaders(con, rp)
armutils.write_arm(state.path + '/' + material.name + '_data.arm', state.data.get())
armutils.write_arm(mat_state.path + '/' + material.name + '_data.arm', mat_state.data.get())
shader_data_name = material.name + '_data'
shader_data_path = 'build/compiled/ShaderRaws/' + material.name + '/' + shader_data_name + '.arm'
assets.add_shader_data(shader_data_path)
mat_data['shader'] = shader_data_name + '/' + shader_data_name
return state.data.sd
def make_mat_context(name):
c = {}
c['name'] = name
state.mat_data['contexts'].append(c)
c['bind_constants'] = []
c['bind_textures'] = []
return c
return mat_state.data.sd
def write_shaders(con, rpass):
if con.vert != None:
shader_path = state.path + '/' + state.material.name + '_' + rpass + '.vert.glsl'
shader_path = mat_state.path + '/' + mat_state.material.name + '_' + rpass + '.vert.glsl'
assets.add_shader(shader_path)
with open(shader_path, 'w') as f:
f.write(con.vert.get())
if con.frag != None:
shader_path = state.path + '/' + state.material.name + '_' + rpass + '.frag.glsl'
shader_path = mat_state.path + '/' + mat_state.material.name + '_' + rpass + '.frag.glsl'
assets.add_shader(shader_path)
with open(shader_path, 'w') as f:
f.write(con.frag.get())
if con.geom != None:
shader_path = state.path + '/' + state.material.name + '_' + rpass + '.geom.glsl'
shader_path = mat_state.path + '/' + mat_state.material.name + '_' + rpass + '.geom.glsl'
assets.add_shader(shader_path)
with open(shader_path, 'w') as f:
f.write(con.geom.get())
if con.tesc != None:
shader_path = state.path + '/' + state.material.name + '_' + rpass + '.tesc.glsl'
shader_path = mat_state.path + '/' + mat_state.material.name + '_' + rpass + '.tesc.glsl'
assets.add_shader(shader_path)
with open(shader_path, 'w') as f:
f.write(con.tesc.get())
if con.tese != None:
shader_path = state.path + '/' + state.material.name + '_' + rpass + '.tese.glsl'
shader_path = mat_state.path + '/' + mat_state.material.name + '_' + rpass + '.tese.glsl'
assets.add_shader(shader_path)
with open(shader_path, 'w') as f:
f.write(con.tese.get())

View file

@ -0,0 +1,5 @@
def make(context_id):
pass
# con_decal = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
# return con_transluc

View file

@ -1,251 +0,0 @@
import make_state as state
import material.mat_state as mat_state
import material.make_cycles as make_cycles
import armutils
def mesh(context_id):
con_mesh = mat_state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
vert = con_mesh.make_vert()
frag = con_mesh.make_frag(mrt=2)
geom = None
tesc = None
tese = None
# Displacement linked
tess_enabled = armutils.tess_enabled(state.target)
output_node = make_cycles.node_by_type(mat_state.nodes, 'OUTPUT_MATERIAL')
if output_node == None:
return None
if output_node.inputs[2].is_linked:
l = output_node.inputs[2].links[0]
if l.from_node.type == 'GROUP' and l.from_node.node_tree.name.startswith('Armory PBR') and l.from_node.inputs[10].is_linked == False:
tess_enabled = False
if tess_enabled and output_node.inputs[2].is_linked:
tesc = con_mesh.make_tesc()
tese = con_mesh.make_tese()
tesc.ins = vert.outs
tese.ins = tesc.outs
frag.ins = tese.outs
vert.add_out('vec3 wposition')
vert.add_uniform('mat4 W', '_worldMatrix')
vert.write('vec4 spos = vec4(pos, 1.0);')
vert.write('wposition = vec4(W * spos).xyz;')
const = {}
const['name'] = 'innerLevel'
const['float'] = mat_state.material.height_tess_inner
mat_state.mat_context['bind_constants'].append(const)
const = {}
const['name'] = 'outerLevel'
const['float'] = mat_state.material.height_tess_outer
mat_state.mat_context['bind_constants'].append(const)
tesc.add_uniform('float innerLevel')
tesc.add_uniform('float outerLevel')
tesc.write_tesc_levels()
tese.add_out('vec3 wposition')
tese.add_out('vec3 wnormal')
tese.add_out('vec3 eyeDir')
tese.write('vec3 p0 = gl_TessCoord.x * tc_wposition[0];')
tese.write('vec3 p1 = gl_TessCoord.y * tc_wposition[1];')
tese.write('vec3 p2 = gl_TessCoord.z * tc_wposition[2];')
tese.write('wposition = p0 + p1 + p2;')
tese.write('vec3 n0 = gl_TessCoord.x * tc_wnormal[0];')
tese.write('vec3 n1 = gl_TessCoord.y * tc_wnormal[1];')
tese.write('vec3 n2 = gl_TessCoord.z * tc_wnormal[2];')
tese.write('wnormal = normalize(n0 + n1 + n2);')
# No displacement
else:
frag.ins = vert.outs
vert.add_out('vec3 wposition')
vert.add_out('vec3 eyeDir')
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_uniform('mat4 N', '_normalMatrix')
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
vert.add_uniform('vec3 eye', '_cameraPosition')
vert.write('vec4 spos = vec4(pos, 1.0);')
vert.write('wposition = vec4(W * spos).xyz;')
vert.write('eyeDir = eye - wposition;')
vert.write('gl_Position = WVP * spos;')
frag.add_include('../../Shaders/compiled.glsl')
frag.add_include('../../Shaders/std/gbuffer.glsl')
frag.write('vec3 v = normalize(eyeDir);')
# frag.write('float dotNV = dot(n, v);')
frag.write('float dotNV = max(dot(n, v), 0.0);')
frag.write('vec3 basecol;')
frag.write('float roughness;')
frag.write('float metallic;')
frag.write('float occlusion;')
make_cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese)
if mat_state.data.is_elem('tex'):
vert.add_out('vec2 texCoord')
vert.write('texCoord = tex;')
if tese != None:
if 'texCoord' in frag.main or 'texCoord' in frag.main_pre:
tese.add_out('vec2 texCoord')
tese.write_pre = True
tese.write('vec2 tc0 = gl_TessCoord.x * tc_texCoord[0];')
tese.write('vec2 tc1 = gl_TessCoord.y * tc_texCoord[1];')
tese.write('vec2 tc2 = gl_TessCoord.z * tc_texCoord[2];')
tese.write('texCoord = tc0 + tc1 + tc2;')
tese.write_pre = False
elif 'texCoord' in tese.main or 'texCoord' in tese.main_pre:
tese.write_pre = True
tese.write('vec2 tc0 = gl_TessCoord.x * tc_texCoord[0];')
tese.write('vec2 tc1 = gl_TessCoord.y * tc_texCoord[1];')
tese.write('vec2 tc2 = gl_TessCoord.z * tc_texCoord[2];')
tese.write('vec2 texCoord = tc0 + tc1 + tc2;')
tese.write_pre = False
if mat_state.data.is_elem('col'):
vert.add_out('vec3 color')
vert.write('color = col;')
if tese != None:
tese.add_out('vec3 color')
tese.write('vec3 col0 = gl_TessCoord.x * tc_color[0];')
tese.write('vec3 col1 = gl_TessCoord.y * tc_color[1];')
tese.write('vec3 col2 = gl_TessCoord.z * tc_color[2];')
tese.write('color = col0 + col1 + col2;')
if mat_state.data.is_elem('tan'):
if tese != None:
vert.add_out('vec3 wnormal')
vert.add_out('vec3 wtangent')
vert.add_uniform('mat4 N', '_normalMatrix')
vert.write('wnormal = normalize(mat3(N) * nor);')
vert.write('wtangent = normalize(mat3(N) * tan);')
tese.add_out('mat3 TBN')
tese.write('vec3 tan0 = gl_TessCoord.x * tc_wtangent[0];')
tese.write('vec3 tan1 = gl_TessCoord.y * tc_wtangent[1];')
tese.write('vec3 tan2 = gl_TessCoord.z * tc_wtangent[2];')
tese.write('vec3 wtangent = normalize(tan0 + tan1 + tan2);')
tese.write('vec3 wbitangent = normalize(cross(wnormal, wtangent));')
tese.write('TBN = mat3(wtangent, wbitangent, wnormal);')
else:
vert.add_out('mat3 TBN')
vert.add_uniform('mat4 N', '_normalMatrix')
vert.write('vec3 wnormal = normalize(mat3(N) * nor);')
vert.write('vec3 tangent = normalize(mat3(N) * tan);')
vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));')
vert.write('TBN = mat3(tangent, bitangent, wnormal);')
else:
vert.add_uniform('mat4 N', '_normalMatrix')
vert.add_out('vec3 wnormal')
vert.write('wnormal = normalize(mat3(N) * nor);')
frag.write_pre = True
frag.write('vec3 n = normalize(wnormal);')
frag.write_pre = False
if tese != None:
tese.add_uniform('mat4 VP', '_viewProjectionMatrix')
# Sample disp at neightbour points to calc normal
tese.write('wposition += wnormal * disp * 0.2;')
tese.add_uniform('vec3 eye', '_cameraPosition')
tese.write('eyeDir = eye - wposition;')
tese.write('gl_Position = VP * vec4(wposition, 1.0);')
# Pack normal
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 - gl_FragCoord.z);')
frag.write('fragColor[1] = vec4(basecol.rgb, occlusion);')
return con_mesh
def shadows(context_id):
con_shadowmap = mat_state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
vert = con_shadowmap.make_vert()
frag = con_shadowmap.make_frag()
geom = None
tesc = None
tese = None
# Displacement linked
tess_enabled = armutils.tess_enabled(state.target)
tess_enabled_shadow = mat_state.material.height_tess_shadows
output_node = make_cycles.node_by_type(mat_state.nodes, 'OUTPUT_MATERIAL')
if output_node == None:
return None
if output_node.inputs[2].is_linked:
l = output_node.inputs[2].links[0]
if l.from_node.type == 'GROUP' and l.from_node.node_tree.name.startswith('Armory PBR') and l.from_node.inputs[10].is_linked == False:
tess_enabled = False
if tess_enabled and tess_enabled_shadow and output_node != None and output_node.inputs[2].is_linked:
tesc = con_shadowmap.make_tesc()
tese = con_shadowmap.make_tese()
tesc.ins = vert.outs
tese.ins = tesc.outs
frag.ins = tese.outs
vert.add_out('vec3 wposition')
vert.add_out('vec3 wnormal')
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_uniform('mat4 N', '_normalMatrix')
vert.write('vec4 spos = vec4(pos, 1.0);')
vert.write('wnormal = normalize(mat3(N) * nor);')
vert.write('wposition = vec4(W * spos).xyz;')
const = {}
const['name'] = 'innerLevel'
const['float'] = mat_state.material.height_tess_shadows_inner
mat_state.mat_context['bind_constants'].append(const)
const = {}
const['name'] = 'outerLevel'
const['float'] = mat_state.material.height_tess_shadows_outer
mat_state.mat_context['bind_constants'].append(const)
tesc.add_uniform('float innerLevel')
tesc.add_uniform('float outerLevel')
tesc.write_tesc_levels()
tese.write('vec3 p0 = gl_TessCoord.x * tc_wposition[0];')
tese.write('vec3 p1 = gl_TessCoord.y * tc_wposition[1];')
tese.write('vec3 p2 = gl_TessCoord.z * tc_wposition[2];')
tese.write('vec3 wposition = p0 + p1 + p2;')
tese.write('vec3 n0 = gl_TessCoord.x * tc_wnormal[0];')
tese.write('vec3 n1 = gl_TessCoord.y * tc_wnormal[1];')
tese.write('vec3 n2 = gl_TessCoord.z * tc_wnormal[2];')
tese.write('vec3 wnormal = normalize(n0 + n1 + n2);')
make_cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, parse_surface=False)
if mat_state.data.is_elem('tex'):
if tese != None and 'texCoord' in tese.main:
vert.add_out('vec2 texCoord')
vert.write('texCoord = tex;')
tese.write_pre = True
tese.write('vec2 tc0 = gl_TessCoord.x * tc_texCoord[0];')
tese.write('vec2 tc1 = gl_TessCoord.y * tc_texCoord[1];')
tese.write('vec2 tc2 = gl_TessCoord.z * tc_texCoord[2];')
tese.write('vec2 texCoord = tc0 + tc1 + tc2;')
tese.write_pre = False
tese.add_uniform('mat4 LVP', '_lampViewProjectionMatrix')
# tese.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix')
tese.write('wposition += wnormal * disp * 0.2;')
tese.write('gl_Position = LVP * vec4(wposition, 1.0);')
# tese.write('gl_Position = LWVP * vec4(wposition, 1.0);')
else:
frag.ins = vert.outs
vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix')
vert.write('gl_Position = LWVP * vec4(pos, 1.0);')
frag.write('fragColor = vec4(0.0);')
return con_shadowmap

View file

@ -0,0 +1,5 @@
def make(context_id):
pass
# con_transluc = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
# return con_transluc

View file

@ -1,137 +0,0 @@
import bpy
import material.mat_state as state
import material.make_cycles as make_cycles
import armutils
import assets
def mesh(context_id):
wrd = bpy.data.worlds['Arm']
if '_PCSS' in wrd.world_defs:
is_pcss = True
else:
is_pcss = False
con_mesh = state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
vert = con_mesh.make_vert()
frag = con_mesh.make_frag()
geom = None
tesc = None
tese = None
frag.ins = vert.outs
vert.add_out('vec3 wnormal')
vert.add_out('vec3 wposition')
vert.add_out('vec3 eyeDir')
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_uniform('mat4 N', '_normalMatrix')
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
vert.add_uniform('vec3 eye', '_cameraPosition')
vert.write('vec4 spos = vec4(pos, 1.0);')
vert.write('wnormal = normalize(mat3(N) * nor);')
vert.write('wposition = vec4(W * spos).xyz;')
vert.write('eyeDir = eye - wposition;')
vert.write('gl_Position = WVP * spos;')
frag.add_include('../../Shaders/compiled.glsl')
frag.add_include('../../Shaders/std/brdf.glsl')
frag.add_include('../../Shaders/std/math.glsl')
frag.add_include('../../Shaders/std/shirr.glsl')
frag.add_uniform('vec3 lightColor', '_lampColor')
frag.add_uniform('vec3 lightDir', '_lampDirection')
frag.add_uniform('vec3 lightPos', '_lampPosition')
frag.add_uniform('int lightType', '_lampType')
frag.add_uniform('float shirr[27]', link='_envmapIrradiance', included=True)
frag.add_uniform('float envmapStrength', link='_envmapStrength')
frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance')
frag.add_uniform('sampler2D senvmapBrdf', link='_envmapBrdf')
frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps')
frag.write('vec3 n = normalize(wnormal);')
frag.write('vec3 l = lightType == 0 ? lightDir : normalize(lightPos - wposition);')
frag.write('vec3 v = normalize(eyeDir);')
frag.write('vec3 h = normalize(v + l);')
frag.write('float dotNL = dot(n, l);')
# frag.write('float dotNV = dot(n, v);')
frag.write('float dotNV = max(dot(n, v), 0.0);')
frag.write('float dotNH = dot(n, h);')
frag.write('float dotVH = dot(v, h);')
vert.add_out('vec4 lampPos')
vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix')
vert.write('lampPos = LWVP * spos;')
if is_pcss:
frag.add_include('../../Shaders/std/shadows_pcss.glsl')
frag.add_uniform('sampler2D snoise', link='_noise64', included=True)
else:
frag.add_include('../../Shaders/std/shadows.glsl')
frag.add_uniform('sampler2D shadowMap', included=True)
frag.add_uniform('float lampSizeUV', link='_lampSizeUV', included=True)
frag.add_uniform('bool receiveShadow')
frag.add_uniform('float shadowsBias', '_lampShadowsBias')
frag.write('float visibility = 1.0;')
frag.write('if (receiveShadow && lampPos.w > 0.0) {')
frag.tab += 1
frag.write('vec3 lpos = lampPos.xyz / lampPos.w;')
frag.write('lpos.xy = lpos.xy * 0.5 + 0.5;')
if is_pcss:
frag.write('visibility = PCSS(lpos.xy, lpos.z - shadowsBias);')
else:
frag.write('visibility = PCF(lpos.xy, lpos.z - shadowsBias);')
frag.tab -= 1
frag.write('}')
frag.add_uniform('float spotlightCutoff', '_spotlampCutoff')
frag.add_uniform('float spotlightExponent', '_spotlampExponent')
frag.write('if (lightType == 2) {')
frag.tab += 1
frag.write('float spotEffect = dot(lightDir, l);')
frag.write('if (spotEffect < spotlightCutoff) {')
frag.tab += 1
frag.write('spotEffect = smoothstep(spotlightCutoff - spotlightExponent, spotlightCutoff, spotEffect);')
frag.write('visibility *= spotEffect;')
frag.tab -= 1
frag.write('}')
frag.tab -= 1
frag.write('}')
frag.write('vec3 basecol;')
frag.write('float roughness;')
frag.write('float metallic;')
frag.write('float occlusion;')
make_cycles.parse(state.nodes, vert, frag, geom, tesc, tese)
frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);')
frag.write('vec3 f0 = surfaceF0(basecol, metallic);')
frag.write('vec3 direct = lambertDiffuseBRDF(albedo, dotNL);')
frag.write('direct += specularBRDF(f0, roughness, dotNL, dotNH, dotNV, dotVH);')
frag.write('vec3 indirect = (shIrradiance(n, 2.2) / PI) * albedo;')
frag.write('vec3 reflectionWorld = reflect(-v, n);')
frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);')
frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;')
frag.write('vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;')
frag.write('indirect += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);')
frag.write('fragColor = vec4(direct * lightColor * visibility + indirect * occlusion * envmapStrength, 1.0);')
return con_mesh
def shadows(context_id):
con_shadowmap = state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
vert = con_shadowmap.make_vert()
frag = con_shadowmap.make_frag()
geom = None
tesc = None
tese = None
vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix')
vert.write('gl_Position = LWVP * vec4(pos, 1.0);')
frag.write('fragColor = vec4(0.0);')
return con_shadowmap

View file

@ -0,0 +1,303 @@
import bpy
import make_state as state
import material.mat_state as mat_state
import material.mat_utils as mat_utils
import material.cycles as cycles
import material.make_shadows as make_shadows
import material.make_skin as make_skin
import armutils
import assets
def make(context_id, rid):
if rid == 'forward':
return make_forward(context_id)
elif rid == 'deferred':
return make_deferred(context_id)
def make_deferred(context_id):
con_mesh = mat_state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
vert = con_mesh.make_vert()
frag = con_mesh.make_frag(mrt=2)
geom = None
tesc = None
tese = None
vert.add_out('vec3 wposition')
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_uniform('mat4 N', '_normalMatrix')
vert.write_pre = True
vert.write('vec4 spos = vec4(pos, 1.0);')
if mat_state.data.is_elem('off'):
vert.write('spos.xyz += off;')
vert.write_pre = False
if mat_utils.disp_linked(mat_state.output_node):
tesc = con_mesh.make_tesc()
tese = con_mesh.make_tese()
tesc.ins = vert.outs
tese.ins = tesc.outs
frag.ins = tese.outs
const = {}
const['name'] = 'innerLevel'
const['float'] = mat_state.material.height_tess_inner
mat_state.mat_context['bind_constants'].append(const)
const = {}
const['name'] = 'outerLevel'
const['float'] = mat_state.material.height_tess_outer
mat_state.mat_context['bind_constants'].append(const)
tesc.add_uniform('float innerLevel')
tesc.add_uniform('float outerLevel')
tesc.write_tesc_levels()
tese.add_out('vec3 wposition')
tese.add_out('vec3 wnormal')
tese.add_out('vec3 eyeDir')
tese.write('vec3 p0 = gl_TessCoord.x * tc_wposition[0];')
tese.write('vec3 p1 = gl_TessCoord.y * tc_wposition[1];')
tese.write('vec3 p2 = gl_TessCoord.z * tc_wposition[2];')
tese.write('wposition = p0 + p1 + p2;')
tese.write('vec3 n0 = gl_TessCoord.x * tc_wnormal[0];')
tese.write('vec3 n1 = gl_TessCoord.y * tc_wnormal[1];')
tese.write('vec3 n2 = gl_TessCoord.z * tc_wnormal[2];')
tese.write('wnormal = normalize(n0 + n1 + n2);')
# No displacement
else:
frag.ins = vert.outs
vert.add_out('vec3 eyeDir')
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
vert.add_uniform('vec3 eye', '_cameraPosition')
vert.write('eyeDir = eye - wposition;')
vert.write('gl_Position = WVP * spos;')
frag.add_include('../../Shaders/compiled.glsl')
frag.add_include('../../Shaders/std/gbuffer.glsl')
frag.write('vec3 v = normalize(eyeDir);')
frag.write('float dotNV = max(dot(n, v), 0.0);') # frag.write('float dotNV = dot(n, v);')
frag.write('vec3 basecol;')
frag.write('float roughness;')
frag.write('float metallic;')
frag.write('float occlusion;')
cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese)
if mat_state.data.is_elem('tex'):
vert.add_out('vec2 texCoord')
vert.write('texCoord = tex;')
if tese != None:
# TODO: also includes texCoord1
tese.write_pre = True
if frag.contains('texCoord'):
tese.add_out('vec2 texCoord')
tese.write('vec2 tc0 = gl_TessCoord.x * tc_texCoord[0];')
tese.write('vec2 tc1 = gl_TessCoord.y * tc_texCoord[1];')
tese.write('vec2 tc2 = gl_TessCoord.z * tc_texCoord[2];')
tese.write('texCoord = tc0 + tc1 + tc2;')
elif tese.contains('texCoord'):
tese.write('vec2 tc0 = gl_TessCoord.x * tc_texCoord[0];')
tese.write('vec2 tc1 = gl_TessCoord.y * tc_texCoord[1];')
tese.write('vec2 tc2 = gl_TessCoord.z * tc_texCoord[2];')
tese.write('vec2 texCoord = tc0 + tc1 + tc2;')
tese.write_pre = False
if mat_state.data.is_elem('tex1'):
vert.add_out('vec2 texCoord1')
vert.write('texCoord1 = tex1;')
if tese != None:
tese.write_pre = True
if frag.contains('texCoord1'):
tese.add_out('vec2 texCoord1')
tese.write('vec2 tc01 = gl_TessCoord.x * tc_texCoord1[0];')
tese.write('vec2 tc11 = gl_TessCoord.y * tc_texCoord1[1];')
tese.write('vec2 tc21 = gl_TessCoord.z * tc_texCoord1[2];')
tese.write('texCoord1 = tc01 + tc11 + tc21;')
elif tese.contains('texCoord1'):
tese.write('vec2 tc01 = gl_TessCoord.x * tc_texCoord1[0];')
tese.write('vec2 tc11 = gl_TessCoord.y * tc_texCoord1[1];')
tese.write('vec2 tc21 = gl_TessCoord.z * tc_texCoord1[2];')
tese.write('vec2 texCoord1 = tc01 + tc11 + tc21;')
tese.write_pre = False
if mat_state.data.is_elem('col'):
vert.add_out('vec3 vcolor')
vert.write('vcolor = col;')
if tese != None:
tese.write_pre = True
tese.add_out('vec3 vcolor')
tese.write('vec3 vcol0 = gl_TessCoord.x * tc_vcolor[0];')
tese.write('vec3 vcol1 = gl_TessCoord.y * tc_vcolor[1];')
tese.write('vec3 vcol2 = gl_TessCoord.z * tc_vcolor[2];')
tese.write('vcolor = vcol0 + vcol1 + vcol2;')
tese.write_pre = False
if mat_state.data.is_elem('tan'):
if tese != None:
vert.add_out('vec3 wnormal')
vert.add_out('vec3 wtangent')
write_norpos(vert)
vert.write('wtangent = normalize(mat3(N) * tan);')
tese.add_out('mat3 TBN')
tese.write('vec3 tan0 = gl_TessCoord.x * tc_wtangent[0];')
tese.write('vec3 tan1 = gl_TessCoord.y * tc_wtangent[1];')
tese.write('vec3 tan2 = gl_TessCoord.z * tc_wtangent[2];')
tese.write('vec3 wtangent = normalize(tan0 + tan1 + tan2);')
tese.write('vec3 wbitangent = normalize(cross(wnormal, wtangent));')
tese.write('TBN = mat3(wtangent, wbitangent, wnormal);')
else:
vert.add_out('mat3 TBN')
write_norpos(vert, declare=True)
vert.write('vec3 tangent = normalize(mat3(N) * tan);')
vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));')
vert.write('TBN = mat3(tangent, bitangent, wnormal);')
else:
vert.add_out('vec3 wnormal')
write_norpos(vert)
frag.write_pre = True
frag.write('vec3 n = normalize(wnormal);')
frag.write_pre = False
if tese != None:
tese.add_uniform('mat4 VP', '_viewProjectionMatrix')
# TODO: Sample disp at neightbour points to calc normal
tese.write('wposition += wnormal * disp * 0.2;')
tese.add_uniform('vec3 eye', '_cameraPosition')
tese.write('eyeDir = eye - wposition;')
tese.write('gl_Position = VP * vec4(wposition, 1.0);')
# Pack gbuffer
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 - gl_FragCoord.z);')
frag.write('fragColor[1] = vec4(basecol.rgb, occlusion);')
return con_mesh
def write_norpos(vert, declare=False):
prep = ''
if declare:
prep = 'vec3 '
vert.write_pre = True
if mat_state.data.is_elem('bone'):
make_skin.skin_pos(vert)
vert.write(prep + 'wnormal = normalize(mat3(N) * (nor + 2.0 * cross(skinA.xyz, cross(skinA.xyz, nor) + skinA.w * nor)));')
else:
vert.write(prep + 'wnormal = normalize(mat3(N) * nor);')
vert.write('wposition = vec4(W * spos).xyz;')
vert.write_pre = False
def make_forward(context_id):
con_mesh = mat_state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
forward(con_mesh)
return con_mesh
def forward(con_mesh, mrt=1):
wrd = bpy.data.worlds['Arm']
if '_PCSS' in wrd.world_defs:
is_pcss = True
else:
is_pcss = False
vert = con_mesh.make_vert()
frag = con_mesh.make_frag(mrt=mrt)
geom = None
tesc = None
tese = None
frag.ins = vert.outs
vert.add_out('vec3 wnormal')
vert.add_out('vec3 wposition')
vert.add_out('vec3 eyeDir')
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_uniform('mat4 N', '_normalMatrix')
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
vert.add_uniform('vec3 eye', '_cameraPosition')
vert.write('vec4 spos = vec4(pos, 1.0);')
vert.write('wnormal = normalize(mat3(N) * nor);')
vert.write('wposition = vec4(W * spos).xyz;')
vert.write('eyeDir = eye - wposition;')
vert.write('gl_Position = WVP * spos;')
frag.add_include('../../Shaders/compiled.glsl')
frag.add_include('../../Shaders/std/brdf.glsl')
frag.add_include('../../Shaders/std/math.glsl')
frag.add_include('../../Shaders/std/shirr.glsl')
frag.add_uniform('vec3 lightColor', '_lampColor')
frag.add_uniform('vec3 lightDir', '_lampDirection')
frag.add_uniform('vec3 lightPos', '_lampPosition')
frag.add_uniform('int lightType', '_lampType')
frag.add_uniform('float shirr[27]', link='_envmapIrradiance', included=True)
frag.add_uniform('float envmapStrength', link='_envmapStrength')
frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance')
frag.add_uniform('sampler2D senvmapBrdf', link='_envmapBrdf')
frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps')
frag.write('vec3 n = normalize(wnormal);')
frag.write('vec3 l = lightType == 0 ? lightDir : normalize(lightPos - wposition);')
frag.write('vec3 v = normalize(eyeDir);')
frag.write('vec3 h = normalize(v + l);')
frag.write('float dotNL = dot(n, l);')
# frag.write('float dotNV = dot(n, v);')
frag.write('float dotNV = max(dot(n, v), 0.0);')
frag.write('float dotNH = dot(n, h);')
frag.write('float dotVH = dot(v, h);')
vert.add_out('vec4 lampPos')
vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix')
vert.write('lampPos = LWVP * spos;')
if is_pcss:
frag.add_include('../../Shaders/std/shadows_pcss.glsl')
frag.add_uniform('sampler2D snoise', link='_noise64', included=True)
else:
frag.add_include('../../Shaders/std/shadows.glsl')
frag.add_uniform('sampler2D shadowMap', included=True)
frag.add_uniform('float lampSizeUV', link='_lampSizeUV', included=True)
frag.add_uniform('bool receiveShadow')
frag.add_uniform('float shadowsBias', '_lampShadowsBias')
frag.write('float visibility = 1.0;')
frag.write('if (receiveShadow && lampPos.w > 0.0) {')
frag.tab += 1
frag.write('vec3 lpos = lampPos.xyz / lampPos.w;')
frag.write('lpos.xy = lpos.xy * 0.5 + 0.5;')
if is_pcss:
frag.write('visibility = PCSS(lpos.xy, lpos.z - shadowsBias);')
else:
frag.write('visibility = PCF(lpos.xy, lpos.z - shadowsBias);')
frag.tab -= 1
frag.write('}')
frag.add_uniform('float spotlightCutoff', '_spotlampCutoff')
frag.add_uniform('float spotlightExponent', '_spotlampExponent')
frag.write('if (lightType == 2) {')
frag.tab += 1
frag.write('float spotEffect = dot(lightDir, l);')
frag.write('if (spotEffect < spotlightCutoff) {')
frag.tab += 1
frag.write('spotEffect = smoothstep(spotlightCutoff - spotlightExponent, spotlightCutoff, spotEffect);')
frag.write('visibility *= spotEffect;')
frag.tab -= 1
frag.write('}')
frag.tab -= 1
frag.write('}')
frag.write('vec3 basecol;')
frag.write('float roughness;')
frag.write('float metallic;')
frag.write('float occlusion;')
cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese)
frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);')
frag.write('vec3 f0 = surfaceF0(basecol, metallic);')
frag.write('vec3 direct = lambertDiffuseBRDF(albedo, dotNL);')
frag.write('direct += specularBRDF(f0, roughness, dotNL, dotNH, dotNV, dotVH);')
frag.write('vec3 indirect = (shIrradiance(n, 2.2) / PI) * albedo;')
frag.write('vec3 reflectionWorld = reflect(-v, n);')
frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);')
frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;')
frag.write('vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;')
frag.write('indirect += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);')
frag.write('fragColor = vec4(direct * lightColor * visibility + indirect * occlusion * envmapStrength, 1.0);')

View file

@ -0,0 +1,5 @@
def make(context_id):
pass
# con_transluc = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
# return con_transluc

View file

@ -0,0 +1,98 @@
import material.cycles as cycles
import material.mat_state as mat_state
import material.mat_utils as mat_utils
import material.make_skin as make_skin
def make(context_id):
con_shadowmap = mat_state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
vert = con_shadowmap.make_vert()
frag = con_shadowmap.make_frag()
geom = None
tesc = None
tese = None
vert.write('vec4 spos = vec4(pos, 1.0);')
if mat_state.data.is_elem('bone'):
make_skin.skin_pos(vert)
if mat_utils.disp_linked(mat_state.output_node) and mat_state.material.height_tess_shadows:
tesc = con_shadowmap.make_tesc()
tese = con_shadowmap.make_tese()
tesc.ins = vert.outs
tese.ins = tesc.outs
frag.ins = tese.outs
vert.add_out('vec3 wposition')
vert.add_out('vec3 wnormal')
vert.add_uniform('mat4 W', '_worldMatrix')
vert.add_uniform('mat4 N', '_normalMatrix')
vert.write('wnormal = normalize(mat3(N) * nor);')
vert.write('wposition = vec4(W * spos).xyz;')
const = {}
const['name'] = 'innerLevel'
const['float'] = mat_state.material.height_tess_shadows_inner
mat_state.mat_context['bind_constants'].append(const)
const = {}
const['name'] = 'outerLevel'
const['float'] = mat_state.material.height_tess_shadows_outer
mat_state.mat_context['bind_constants'].append(const)
tesc.add_uniform('float innerLevel')
tesc.add_uniform('float outerLevel')
tesc.write_tesc_levels()
tese.write('vec3 p0 = gl_TessCoord.x * tc_wposition[0];')
tese.write('vec3 p1 = gl_TessCoord.y * tc_wposition[1];')
tese.write('vec3 p2 = gl_TessCoord.z * tc_wposition[2];')
tese.write('vec3 wposition = p0 + p1 + p2;')
tese.write('vec3 n0 = gl_TessCoord.x * tc_wnormal[0];')
tese.write('vec3 n1 = gl_TessCoord.y * tc_wnormal[1];')
tese.write('vec3 n2 = gl_TessCoord.z * tc_wnormal[2];')
tese.write('vec3 wnormal = normalize(n0 + n1 + n2);')
cycles.parse(mat_state.nodes, vert, frag, geom, tesc, tese, parse_surface=False)
if mat_state.data.is_elem('tex') and tese.contains('texCoord'):
vert.add_out('vec2 texCoord')
vert.write('texCoord = tex;')
tese.write_pre = True
tese.write('vec2 tc0 = gl_TessCoord.x * tc_texCoord[0];')
tese.write('vec2 tc1 = gl_TessCoord.y * tc_texCoord[1];')
tese.write('vec2 tc2 = gl_TessCoord.z * tc_texCoord[2];')
tese.write('vec2 texCoord = tc0 + tc1 + tc2;')
tese.write_pre = False
if mat_state.data.is_elem('tex1') and tese.contains('texCoord1'):
vert.add_out('vec2 texCoord1')
vert.write('texCoord1 = tex1;')
tese.write_pre = True
tese.write('vec2 tc01 = gl_TessCoord.x * tc_texCoord1[0];')
tese.write('vec2 tc11 = gl_TessCoord.y * tc_texCoord1[1];')
tese.write('vec2 tc21 = gl_TessCoord.z * tc_texCoord1[2];')
tese.write('vec2 texCoord1 = tc01 + tc11 + tc21;')
tese.write_pre = False
if mat_state.data.is_elem('col') and tese.contains('vcolor'):
vert.add_out('vec3 vcolor')
vert.write('vcolor = col;')
tese.write_pre = True
tese.write('vec3 vcol0 = gl_TessCoord.x * tc_vcolor[0];')
tese.write('vec3 vcol1 = gl_TessCoord.y * tc_vcolor[1];')
tese.write('vec3 vcol2 = gl_TessCoord.z * tc_vcolor[2];')
tese.write('vec3 vcolor = vcol0 + vcol1 + vcol2;')
tese.write_pre = False
tese.add_uniform('mat4 LVP', '_lampViewProjectionMatrix')
tese.write('wposition += wnormal * disp * 0.2;')
tese.write('gl_Position = LVP * vec4(wposition, 1.0);')
# No displacement
else:
frag.ins = vert.outs
vert.add_uniform('mat4 LWVP', '_lampWorldViewProjectionMatrix')
vert.write('gl_Position = LWVP * spos;')
frag.write('fragColor = vec4(0.0);')
return con_shadowmap

View file

@ -0,0 +1,10 @@
def skin_pos(vert):
vert.add_include('../../Shaders/compiled.glsl')
vert.add_include('../../Shaders/std/skinning.glsl')
vert.add_uniform('float skinBones[skinMaxBones * 8]', link='_skinBones', included=True)
vert.write('vec4 skinA;')
vert.write('vec4 skinB;')
vert.write('getSkinningDualQuat(ivec4(bone), weight, skinA, skinB);')
vert.write('spos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, spos.xyz) + skinA.w * spos.xyz); // Rotate')
vert.write('spos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate')

View file

@ -0,0 +1,40 @@
import material.cycles as cycles
import material.mat_state as mat_state
import material.make_mesh as make_mesh
def make(context_id):
con_transluc = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'less', 'cull_mode': 'clockwise', \
'blend_source': 'blend_one', 'blend_destination': 'blend_one', 'blend_operation': 'add', \
'alpha_blend_source': 'blend_zero', 'alpha_blend_destination': 'inverse_source_alpha', 'alpha_blend_operation': 'add' })
make_mesh.forward(con_transluc, mrt=2)
vert = con_transluc.vert
frag = con_transluc.frag
vert.add_out('vec4 wvpposition')
vert.write('wvpposition = gl_Position;')
# Remove fragColor = ...;
frag.main = frag.main[:frag.main.rfind('fragColor')]
frag.write('vec4 premultipliedReflect = vec4(vec3(direct * visibility + indirect * occlusion), 0.1);')
#ifdef _OpacTex
# premultipliedReflect.a *= texture(sopacity, texCoord).r;
#else
#ifdef _BaseTex
# premultipliedReflect.a *= texel.a; // Base color alpha
#endif
#endif
frag.write('float fragZ = wvpposition.z / wvpposition.w;')
frag.write('float a = min(1.0, premultipliedReflect.a) * 8.0 + 0.01;')
frag.write('float b = -fragZ * 0.95 + 1.0;')
frag.write('float w = clamp(a * a * a * 1e8 * b * b * b, 1e-2, 3e2);')
frag.write('fragColor[0] = vec4(premultipliedReflect.rgb * w, premultipliedReflect.a);')
frag.write('fragColor[1] = vec4(premultipliedReflect.a * w, 0.0, 0.0, 1.0);')
return con_transluc

View file

@ -2,5 +2,6 @@ data = None
material = None
nodes = None
mat_data = None
mat_users = None
mat_context = None
path = None

View file

@ -0,0 +1,59 @@
import armutils
import make_state as state
import material.cycles as cycles
def disp_linked(output_node):
# Armory PBR with unlinked height socket
if output_node.inputs[2].is_linked:
l = output_node.inputs[2].links[0]
if l.from_node.type == 'GROUP' and l.from_node.node_tree.name.startswith('Armory PBR') and l.from_node.inputs[10].is_linked == False:
return False
return armutils.tess_enabled(state.target) and output_node.inputs[2].is_linked
def get_rpasses(material):
ar = []
if material.cast_shadow:
ar.append('shadows')
if material.overlay:
ar.append('overlay')
# elif material.decal:
# ar.append('decal')
elif is_transluc(material):
ar.append('translucent')
else:
ar.append('mesh')
# if material.depthpass:
# ar.append('depth')
return ar
def is_transluc(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_transluc_traverse(surface_node)
def is_transluc_traverse(node):
if is_transluc_type(node):
return True
for inp in node.inputs:
if inp.is_linked:
res = is_transluc_traverse(inp.links[0].from_node)
if res:
return True
return False
def is_transluc_type(node):
if node.type == 'BSDF_GLASS' or \
node.type == 'BSDF_TRANSPARENT' or \
node.type == 'BSDF_TRANSLUCENT' or \
(node.type == 'GROUP' and node.node_tree.name.startswith('Armory PBR') and (node.inputs[12].is_linked or node.inputs[12].default_value != 1.0)):
return True
return False

View file

@ -41,6 +41,9 @@ class Shader:
return
self.functions[fname] = s
def contains(self, s):
return (s in self.main or s in self.main_pre)
def write(self, s):
if self.write_pre:
self.main_pre += '\t' * 1 + s + '\n'

View file

@ -39,7 +39,8 @@ class ShaderData:
# TODO: temporary, Sort vertex data
for sd in self.data['shader_datas']:
vs = []
ar = ['pos', 'nor', 'tex', 'col', 'tan', 'bone', 'weight', 'off']
ar = ['pos', 'nor', 'tex', 'tex1', 'col', 'tan', 'bone', 'weight']
# 'off' is discarded and recreated in instanced vertex structure
for ename in ar:
elem = self.get_elem(ename)
if elem != None:
@ -62,6 +63,26 @@ class ShaderContext:
self.data['depth_write'] = props['depth_write']
self.data['compare_mode'] = props['compare_mode']
self.data['cull_mode'] = props['cull_mode']
if 'blend_source' in props:
self.data['blend_source'] = props['blend_source']
if 'blend_destination' in props:
self.data['blend_destination'] = props['blend_destination']
if 'blend_operation' in props:
self.data['blend_operation'] = props['blend_operation']
if 'alpha_blend_source' in props:
self.data['alpha_blend_source'] = props['alpha_blend_source']
if 'alpha_blend_destination' in props:
self.data['alpha_blend_destination'] = props['alpha_blend_destination']
if 'alpha_blend_operation' in props:
self.data['alpha_blend_operation'] = props['alpha_blend_operation']
if 'color_write_red' in props:
self.data['color_write_red'] = props['color_write_red']
if 'color_write_green' in props:
self.data['color_write_green'] = props['color_write_green']
if 'color_write_blue' in props:
self.data['color_write_blue'] = props['color_write_blue']
if 'color_write_alpha' in props:
self.data['color_write_alpha'] = props['color_write_alpha']
self.data['texture_units'] = []
self.tunits = self.data['texture_units']