armory/blender/arm/material/make_mesh.py

723 lines
30 KiB
Python
Raw Normal View History

2016-12-19 01:25:22 +01:00
import bpy
2017-12-20 15:37:58 +01:00
import arm.assets as assets
2017-03-15 12:30:14 +01:00
import arm.material.mat_state as mat_state
import arm.material.mat_utils as mat_utils
import arm.material.cycles as cycles
import arm.material.make_tess as make_tess
2017-09-27 00:04:47 +02:00
import arm.material.make_particle as make_particle
2018-12-10 18:18:32 +01:00
import arm.material.make_cluster as make_cluster
2018-12-14 15:27:43 +01:00
import arm.material.make_finalize as make_finalize
import arm.material.make_attrib as make_attrib
2017-03-15 12:30:14 +01:00
import arm.utils
2016-12-19 01:25:22 +01:00
2017-03-14 20:43:54 +01:00
is_displacement = False
2017-04-22 15:08:44 +02:00
write_material_attribs = None
2017-05-11 23:09:26 +02:00
write_material_attribs_post = None
write_vertex_attribs = None
2016-12-20 00:39:18 +01:00
2019-01-24 12:47:51 +01:00
def make(context_id, rpasses):
2020-05-06 18:11:02 +02:00
wrd = bpy.data.worlds['Arm']
2017-10-24 13:13:26 +02:00
rpdat = arm.utils.get_rp()
rid = rpdat.rp_renderer
2017-09-21 23:47:49 +02:00
con = { 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' }
2020-05-06 18:11:02 +02:00
2018-08-08 22:43:14 +02:00
# Blend context
mat = mat_state.material
blend = mat.arm_blending
particle = mat_state.material.arm_particle_flag
2018-08-16 12:10:50 +02:00
dprepass = rid == 'Forward' and rpdat.rp_depthprepass
2017-09-29 01:18:57 +02:00
if blend:
con['name'] = 'blend'
2018-08-08 22:43:14 +02:00
con['blend_source'] = mat.arm_blending_source
con['blend_destination'] = mat.arm_blending_destination
con['blend_operation'] = mat.arm_blending_operation
con['alpha_blend_source'] = mat.arm_blending_source_alpha
con['alpha_blend_destination'] = mat.arm_blending_destination_alpha
con['alpha_blend_operation'] = mat.arm_blending_operation_alpha
2017-09-29 01:18:57 +02:00
con['depth_write'] = False
2018-08-16 12:10:50 +02:00
con['compare_mode'] = 'less'
elif particle:
2018-08-16 12:10:50 +02:00
pass
elif dprepass: # Depth prepass was performed
2017-10-24 13:13:26 +02:00
con['depth_write'] = False
con['compare_mode'] = 'equal'
attachment_format = 'RGBA32' if '_LDR' in wrd.world_defs else 'RGBA64'
con['color_attachments'] = [attachment_format, attachment_format]
if '_gbuffer2' in wrd.world_defs:
con['color_attachments'].append(attachment_format)
2020-05-06 21:30:59 +02:00
2017-09-21 23:47:49 +02:00
con_mesh = mat_state.data.add_context(con)
2017-10-10 09:57:23 +02:00
mat_state.con_mesh = con_mesh
2016-12-20 00:39:18 +01:00
2017-09-29 01:18:57 +02:00
if rid == 'Forward' or blend:
2017-10-01 19:42:47 +02:00
if rpdat.arm_material_model == 'Mobile':
2017-10-01 19:09:09 +02:00
make_forward_mobile(con_mesh)
2017-10-01 19:42:47 +02:00
elif rpdat.arm_material_model == 'Solid':
make_forward_solid(con_mesh)
else:
make_forward(con_mesh)
2017-08-21 15:36:21 +02:00
elif rid == 'Deferred':
2019-01-24 12:47:51 +01:00
make_deferred(con_mesh, rpasses)
2018-11-19 13:18:40 +01:00
elif rid == 'Raytracer':
make_raytracer(con_mesh)
2016-12-19 01:25:22 +01:00
2018-12-14 15:27:43 +01:00
make_finalize.make(con_mesh)
2017-03-21 03:06:38 +01:00
2018-01-04 11:37:27 +01:00
assets.vs_equal(con_mesh, assets.shader_cons['mesh_vert'])
2016-12-20 00:39:18 +01:00
return con_mesh
2016-12-19 01:25:22 +01:00
2016-12-21 00:51:04 +01:00
def make_base(con_mesh, parse_opacity):
2017-03-14 20:43:54 +01:00
global is_displacement
2017-04-22 15:08:44 +02:00
global write_material_attribs
2017-05-11 23:09:26 +02:00
global write_material_attribs_post
global write_vertex_attribs
2019-01-23 18:09:53 +01:00
wrd = bpy.data.worlds['Arm']
2017-03-14 20:43:54 +01:00
2016-12-19 01:25:22 +01:00
vert = con_mesh.make_vert()
2016-12-21 00:51:04 +01:00
frag = con_mesh.make_frag()
2016-12-19 01:25:22 +01:00
geom = None
tesc = None
tese = None
2017-03-11 01:50:47 +01:00
vert.add_uniform('mat3 N', '_normalMatrix')
2018-12-14 15:27:43 +01:00
vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);')
2016-12-19 01:25:22 +01:00
2017-10-04 18:24:13 +02:00
vattr_written = False
2018-05-07 23:09:38 +02:00
rpdat = arm.utils.get_rp()
2017-10-04 18:24:13 +02:00
is_displacement = mat_utils.disp_linked(mat_state.output_node)
if is_displacement:
2018-05-07 23:09:38 +02:00
if rpdat.arm_rp_displacement == 'Vertex':
frag.ins = vert.outs
else: # Tessellation
tesc = con_mesh.make_tesc()
tese = con_mesh.make_tese()
tesc.ins = vert.outs
tese.ins = tesc.outs
frag.ins = tese.outs
make_tess.tesc_levels(tesc, rpdat.arm_tess_mesh_inner, rpdat.arm_tess_mesh_outer)
make_tess.interpolate(tese, 'wposition', 3, declare_out=True)
make_tess.interpolate(tese, 'wnormal', 3, declare_out=True, normalize=True)
2016-12-19 01:25:22 +01:00
# No displacement
else:
frag.ins = vert.outs
2017-05-11 23:09:26 +02:00
if write_vertex_attribs != None:
2017-10-04 18:24:13 +02:00
vattr_written = write_vertex_attribs(vert)
2017-09-27 00:04:47 +02:00
frag.add_include('compiled.inc')
2016-12-19 01:25:22 +01:00
2017-05-01 22:25:36 +02:00
written = False
2017-04-22 15:08:44 +02:00
if write_material_attribs != None:
2017-05-25 20:14:53 +02:00
written = write_material_attribs(con_mesh, frag)
2017-05-01 22:25:36 +02:00
if written == False:
2017-04-22 15:08:44 +02:00
frag.write('vec3 basecol;')
frag.write('float roughness;')
frag.write('float metallic;')
frag.write('float occlusion;')
2018-05-19 19:29:14 +02:00
frag.write('float specular;')
2019-01-23 18:09:53 +01:00
if '_Emission' in wrd.world_defs:
frag.write('float emission;')
2017-04-22 15:08:44 +02:00
if parse_opacity:
frag.write('float opacity;')
2017-05-25 16:48:41 +02:00
cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity)
2017-05-11 23:09:26 +02:00
if write_material_attribs_post != None:
2017-05-25 20:14:53 +02:00
write_material_attribs_post(con_mesh, frag)
2016-12-19 01:25:22 +01:00
2017-10-04 18:24:13 +02:00
if not is_displacement and not vattr_written:
2018-12-14 15:27:43 +01:00
make_attrib.write_vertpos(vert)
2017-10-04 18:24:13 +02:00
2017-05-25 16:48:41 +02:00
if con_mesh.is_elem('tex'):
2016-12-19 01:25:22 +01:00
vert.add_out('vec2 texCoord')
2018-12-14 15:27:43 +01:00
vert.add_uniform('float texUnpack', link='_texUnpack')
2019-01-22 12:38:47 +01:00
if mat_state.material.arm_tilesheet_flag:
2019-04-06 14:30:11 +02:00
if mat_state.material.arm_particle_flag and rpdat.arm_particles == 'On':
2017-09-29 01:18:57 +02:00
make_particle.write_tilesheet(vert)
else:
vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset')
2018-12-14 15:27:43 +01:00
vert.write_attrib('texCoord = tex * texUnpack + tilesheetOffset;')
2017-09-21 18:30:02 +02:00
else:
2018-12-14 15:27:43 +01:00
vert.write_attrib('texCoord = tex * texUnpack;')
2017-09-21 18:30:02 +02:00
2016-12-19 01:25:22 +01:00
if tese != None:
tese.write_pre = True
2016-12-20 00:39:18 +01:00
make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord'))
2016-12-19 01:25:22 +01:00
tese.write_pre = False
2017-05-25 16:48:41 +02:00
if con_mesh.is_elem('tex1'):
2016-12-19 01:25:22 +01:00
vert.add_out('vec2 texCoord1')
2018-12-14 15:27:43 +01:00
vert.add_uniform('float texUnpack', link='_texUnpack')
vert.write_attrib('texCoord1 = tex1 * texUnpack;')
2016-12-19 01:25:22 +01:00
if tese != None:
tese.write_pre = True
2016-12-20 00:39:18 +01:00
make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1'))
2016-12-19 01:25:22 +01:00
tese.write_pre = False
2017-05-25 16:48:41 +02:00
if con_mesh.is_elem('col'):
2016-12-19 01:25:22 +01:00
vert.add_out('vec3 vcolor')
2019-01-07 10:42:45 +01:00
vert.write_attrib('vcolor = col.rgb;')
2016-12-19 01:25:22 +01:00
if tese != None:
tese.write_pre = True
2016-12-20 00:39:18 +01:00
make_tess.interpolate(tese, 'vcolor', 3, declare_out=frag.contains('vcolor'))
2016-12-19 01:25:22 +01:00
tese.write_pre = False
2017-05-25 16:48:41 +02:00
if con_mesh.is_elem('tang'):
2016-12-19 01:25:22 +01:00
if tese != None:
vert.add_out('vec3 wnormal')
2018-12-14 15:27:43 +01:00
make_attrib.write_norpos(con_mesh, vert)
2016-12-19 01:25:22 +01:00
tese.add_out('mat3 TBN')
tese.write('vec3 wbitangent = normalize(cross(wnormal, wtangent));')
tese.write('TBN = mat3(wtangent, wbitangent, wnormal);')
else:
vert.add_out('mat3 TBN')
2018-12-14 15:27:43 +01:00
make_attrib.write_norpos(con_mesh, vert, declare=True)
vert.write('vec3 tangent = normalize(N * tang.xyz);')
2016-12-19 01:25:22 +01:00
vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));')
vert.write('TBN = mat3(tangent, bitangent, wnormal);')
else:
vert.add_out('vec3 wnormal')
2018-12-14 15:27:43 +01:00
make_attrib.write_norpos(con_mesh, vert)
2018-03-27 10:10:12 +02:00
frag.write_attrib('vec3 n = normalize(wnormal);')
2016-12-19 01:25:22 +01:00
2018-05-07 23:09:38 +02:00
if is_displacement:
if rpdat.arm_rp_displacement == 'Vertex':
sh = vert
else:
sh = tese
sh.add_uniform('mat4 VP', '_viewProjectionMatrix')
2019-02-04 21:47:46 +01:00
sh.write('wposition += wnormal * disp;')
2018-05-07 23:09:38 +02:00
sh.write('gl_Position = VP * vec4(wposition, 1.0);')
2016-12-19 01:25:22 +01:00
2019-01-24 12:47:51 +01:00
def make_deferred(con_mesh, rpasses):
2016-12-21 00:51:04 +01:00
wrd = bpy.data.worlds['Arm']
2017-08-21 20:16:06 +02:00
rpdat = arm.utils.get_rp()
2017-07-08 15:12:37 +02:00
2017-08-21 12:17:55 +02:00
arm_discard = mat_state.material.arm_discard
2019-01-24 12:47:51 +01:00
parse_opacity = arm_discard or 'translucent' in rpasses
2017-07-08 15:12:37 +02:00
2017-08-13 20:28:06 +02:00
make_base(con_mesh, parse_opacity=parse_opacity)
2016-12-19 01:25:22 +01:00
2016-12-20 00:39:18 +01:00
frag = con_mesh.frag
2016-12-21 00:51:04 +01:00
vert = con_mesh.vert
2017-01-08 13:21:54 +01:00
tese = con_mesh.tese
2016-12-21 00:51:04 +01:00
2019-01-24 12:47:51 +01:00
if parse_opacity:
if arm_discard:
opac = mat_state.material.arm_discard_opacity
else:
2019-02-11 11:12:41 +01:00
opac = '0.9999' # 1.0 - eps
2017-07-08 15:12:37 +02:00
frag.write('if (opacity < {0}) discard;'.format(opac))
2017-07-05 23:26:13 +02:00
2017-06-23 15:47:51 +02:00
gapi = arm.utils.get_gapi()
2018-05-19 19:29:14 +02:00
if '_gbuffer2' in wrd.world_defs:
2019-01-30 17:45:54 +01:00
frag.add_out('vec4 fragColor[3]')
2018-05-19 19:29:14 +02:00
if '_Veloc' in wrd.world_defs:
if tese == None:
vert.add_uniform('mat4 prevWVP', link='_prevWorldViewProjectionMatrix')
vert.add_out('vec4 wvpposition')
vert.add_out('vec4 prevwvpposition')
vert.write('wvpposition = gl_Position;')
2018-08-09 18:17:15 +02:00
if is_displacement:
vert.add_uniform('mat4 invW', link='_inverseWorldMatrix')
2018-08-15 23:27:46 +02:00
vert.write('prevwvpposition = prevWVP * (invW * vec4(wposition, 1.0));')
2018-08-09 18:17:15 +02:00
else:
vert.write('prevwvpposition = prevWVP * spos;')
2018-05-19 19:29:14 +02:00
else:
tese.add_out('vec4 wvpposition')
tese.add_out('vec4 prevwvpposition')
tese.write('wvpposition = gl_Position;')
2018-08-16 09:07:44 +02:00
if is_displacement:
tese.add_uniform('mat4 invW', link='_inverseWorldMatrix')
tese.add_uniform('mat4 prevWVP', '_prevWorldViewProjectionMatrix')
tese.write('prevwvpposition = prevWVP * (invW * vec4(wposition, 1.0));')
else:
vert.add_uniform('mat4 prevW', link='_prevWorldMatrix')
vert.add_out('vec3 prevwposition')
vert.write('prevwposition = vec4(prevW * spos).xyz;')
tese.add_uniform('mat4 prevVP', '_prevViewProjectionMatrix')
make_tess.interpolate(tese, 'prevwposition', 3)
tese.write('prevwvpposition = prevVP * vec4(prevwposition, 1.0);')
2016-12-21 00:51:04 +01:00
else:
2019-01-30 17:45:54 +01:00
frag.add_out('vec4 fragColor[2]')
2016-12-21 00:51:04 +01:00
# Pack gbuffer
2017-12-20 10:19:44 +01:00
frag.add_include('std/gbuffer.glsl')
2017-07-05 23:26:13 +02:00
2017-08-21 12:17:55 +02:00
if mat_state.material.arm_two_sided:
2018-01-07 22:51:20 +01:00
frag.write('if (!gl_FrontFacing) n *= -1;') # Flip normal when drawing back-face
2017-07-05 23:26:13 +02:00
2016-12-20 00:39:18 +01:00
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);')
2020-05-06 18:11:02 +02:00
2019-01-24 12:47:51 +01:00
if '_Emission' in wrd.world_defs or '_SSS' in wrd.world_defs or '_Hair' in wrd.world_defs:
2019-07-07 22:02:07 +02:00
frag.write('uint matid = 0;')
2019-01-24 12:47:51 +01:00
if '_Emission' in wrd.world_defs:
2019-07-07 22:02:07 +02:00
frag.write('if (emission > 0) { basecol *= emission; matid = 1; }')
2019-01-24 12:47:51 +01:00
if '_SSS' in wrd.world_defs or '_Hair' in wrd.world_defs:
frag.add_uniform('int materialID')
2019-07-07 22:02:07 +02:00
frag.write('if (materialID == 2) matid = 2;')
2019-01-23 18:09:53 +01:00
else:
2019-07-07 22:02:07 +02:00
frag.write('const uint matid = 0;')
2019-01-24 12:47:51 +01:00
2019-07-14 16:45:34 +02:00
frag.write('fragColor[0] = vec4(n.xy, roughness, packFloatInt16(metallic, matid));')
2019-05-01 21:24:39 +02:00
frag.write('fragColor[1] = vec4(basecol, packFloat2(occlusion, specular));')
2018-05-19 19:29:14 +02:00
if '_gbuffer2' in wrd.world_defs:
if '_Veloc' in wrd.world_defs:
frag.write('vec2 posa = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;')
frag.write('vec2 posb = (prevwvpposition.xy / prevwvpposition.w) * 0.5 + 0.5;')
frag.write('fragColor[2].rg = vec2(posa - posb);')
2016-12-21 00:51:04 +01:00
2016-12-20 00:39:18 +01:00
return con_mesh
2016-12-19 01:25:22 +01:00
2018-11-19 13:18:40 +01:00
def make_raytracer(con_mesh):
2019-04-04 11:23:18 +02:00
con_mesh.data['vertex_elements'] = [{'name': 'pos', 'data': 'float3'}, {'name': 'nor', 'data': 'float3'}, {'name': 'tex', 'data': 'float2'}]
2018-07-29 11:39:54 +02:00
wrd = bpy.data.worlds['Arm']
vert = con_mesh.make_vert()
frag = con_mesh.make_frag()
vert.add_out('vec3 n')
2019-04-04 11:23:18 +02:00
vert.add_out('vec2 uv')
2018-07-29 11:39:54 +02:00
vert.write('n = nor;')
2019-04-04 11:23:18 +02:00
vert.write('uv = tex;')
2018-12-14 15:27:43 +01:00
vert.write('gl_Position = vec4(pos.xyz, 1.0);')
2017-03-23 13:18:13 +01:00
2017-10-01 19:09:09 +02:00
def make_forward_mobile(con_mesh):
2017-04-26 14:21:22 +02:00
wrd = bpy.data.worlds['Arm']
vert = con_mesh.make_vert()
frag = con_mesh.make_frag()
geom = None
tesc = None
tese = None
vert.add_uniform('mat3 N', '_normalMatrix')
2018-12-14 15:27:43 +01:00
vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);')
2017-04-26 14:21:22 +02:00
frag.ins = vert.outs
2018-11-14 21:51:30 +01:00
2018-12-14 15:27:43 +01:00
make_attrib.write_vertpos(vert)
2017-04-26 14:21:22 +02:00
frag.add_include('compiled.inc')
2017-04-26 14:21:22 +02:00
frag.write('vec3 basecol;')
2017-09-09 13:46:32 +02:00
frag.write('float roughness;')
frag.write('float metallic;')
frag.write('float occlusion;')
2018-05-19 19:29:14 +02:00
frag.write('float specular;')
2019-01-23 18:09:53 +01:00
if '_Emission' in wrd.world_defs:
frag.write('float emission;')
2018-11-14 22:28:19 +01:00
arm_discard = mat_state.material.arm_discard
blend = mat_state.material.arm_blending
is_transluc = mat_utils.is_transluc(mat_state.material)
parse_opacity = (blend and is_transluc) or arm_discard
if parse_opacity:
frag.write('float opacity;')
cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False)
if arm_discard:
opac = mat_state.material.arm_discard_opacity
frag.write('if (opacity < {0}) discard;'.format(opac))
2017-04-26 14:21:22 +02:00
2017-05-25 16:48:41 +02:00
if con_mesh.is_elem('tex'):
2017-04-26 14:21:22 +02:00
vert.add_out('vec2 texCoord')
2018-12-14 15:27:43 +01:00
vert.add_uniform('float texUnpack', link='_texUnpack')
2019-01-22 12:38:47 +01:00
if mat_state.material.arm_tilesheet_flag:
2018-11-14 22:28:19 +01:00
vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset')
2018-12-14 15:27:43 +01:00
vert.write('texCoord = tex * texUnpack + tilesheetOffset;')
2018-11-14 22:28:19 +01:00
else:
2018-12-14 15:27:43 +01:00
vert.write('texCoord = tex * texUnpack;')
2017-04-26 14:21:22 +02:00
2017-05-25 16:48:41 +02:00
if con_mesh.is_elem('col'):
2017-04-26 14:21:22 +02:00
vert.add_out('vec3 vcolor')
2019-01-07 10:42:45 +01:00
vert.write('vcolor = col.rgb;')
2017-04-26 14:21:22 +02:00
2018-08-01 11:46:38 +02:00
if con_mesh.is_elem('tang'):
vert.add_out('mat3 TBN')
2018-12-14 15:27:43 +01:00
make_attrib.write_norpos(con_mesh, vert, declare=True)
2019-04-04 11:23:53 +02:00
vert.write('vec3 tangent = normalize(N * tang.xyz);')
2018-08-01 11:46:38 +02:00
vert.write('vec3 bitangent = normalize(cross(wnormal, tangent));')
vert.write('TBN = mat3(tangent, bitangent, wnormal);')
else:
vert.add_out('vec3 wnormal')
2018-12-14 15:27:43 +01:00
make_attrib.write_norpos(con_mesh, vert)
2018-08-01 11:46:38 +02:00
frag.write_attrib('vec3 n = normalize(wnormal);')
2017-04-26 14:21:22 +02:00
2017-12-20 10:19:44 +01:00
frag.add_include('std/math.glsl')
frag.add_include('std/brdf.glsl')
2017-04-26 14:21:22 +02:00
2017-10-16 09:25:18 +02:00
frag.add_out('vec4 fragColor')
blend = mat_state.material.arm_blending
if blend:
2018-11-14 22:28:19 +01:00
if parse_opacity:
frag.write('fragColor = vec4(basecol, opacity);')
else:
frag.write('fragColor = vec4(basecol, 1.0);')
2017-10-16 09:25:18 +02:00
return
is_shadows = '_ShadowMap' in wrd.world_defs
frag.write('vec3 direct = vec3(0.0);')
if '_Sun' in wrd.world_defs:
frag.add_uniform('vec3 sunCol', '_sunColor')
frag.add_uniform('vec3 sunDir', '_sunDirection')
frag.write('float svisibility = 1.0;')
frag.write('float sdotNL = max(dot(n, sunDir), 0.0);')
if is_shadows:
vert.add_out('vec4 lightPosition')
vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrix')
2019-02-10 20:37:38 +01:00
vert.write('lightPosition = LWVP * spos;')
2018-12-15 15:07:30 +01:00
frag.add_uniform('sampler2DShadow shadowMap')
frag.add_uniform('float shadowsBias', '_sunShadowsBias')
2018-12-15 19:03:11 +01:00
if '_CSM' in wrd.world_defs:
frag.add_include('std/shadows.glsl')
frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True)
frag.add_uniform('vec3 eye', '_cameraPosition')
2019-01-09 21:25:09 +01:00
frag.write('svisibility = shadowTestCascade(shadowMap, eye, wposition + n * shadowsBias * 10, shadowsBias);')
2018-12-15 19:03:11 +01:00
else:
frag.write('if (lightPosition.w > 0.0) {')
frag.write(' vec3 lPos = lightPosition.xyz / lightPosition.w;')
2019-02-10 20:37:38 +01:00
if '_Legacy' in wrd.world_defs:
frag.write(' svisibility = float(texture(shadowMap, vec2(lPos.xy)).r > lPos.z - shadowsBias);')
else:
frag.write(' svisibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r;')
2018-12-15 19:03:11 +01:00
frag.write('}')
frag.write('direct += basecol * sdotNL * sunCol * svisibility;')
2018-12-10 17:25:29 +01:00
if '_SinglePoint' in wrd.world_defs:
frag.add_uniform('vec3 pointPos', '_pointPosition')
frag.add_uniform('vec3 pointCol', '_pointColor')
2019-01-09 21:25:09 +01:00
if '_Spot' in wrd.world_defs:
frag.add_uniform('vec3 spotDir', link='_spotDirection')
frag.add_uniform('vec2 spotData', link='_spotData')
frag.write('float visibility = 1.0;')
2018-12-10 23:29:04 +01:00
frag.write('vec3 ld = pointPos - wposition;')
frag.write('vec3 l = normalize(ld);')
frag.write('float dotNL = max(dot(n, l), 0.0);')
2019-01-09 21:25:09 +01:00
if is_shadows:
frag.add_uniform('float pointBias', link='_pointShadowsBias')
frag.add_include('std/shadows.glsl')
if '_Spot' in wrd.world_defs:
2018-12-11 23:05:18 +01:00
vert.add_out('vec4 spotPosition')
2019-01-09 21:25:09 +01:00
vert.add_uniform('mat4 LWVPSpot0', link='_biasLightWorldViewProjectionMatrixSpot0')
2020-05-06 18:11:02 +02:00
vert.write('spotPosition = LWVPSpot0 * spos;')
2018-12-15 15:07:30 +01:00
frag.add_uniform('sampler2DShadow shadowMapSpot[1]')
2018-12-11 23:05:18 +01:00
frag.write('if (spotPosition.w > 0.0) {')
frag.write(' vec3 lPos = spotPosition.xyz / spotPosition.w;')
2019-02-10 20:37:38 +01:00
if '_Legacy' in wrd.world_defs:
frag.write(' visibility = float(texture(shadowMapSpot[0], vec2(lPos.xy)).r > lPos.z - pointBias);')
else:
frag.write(' visibility = texture(shadowMapSpot[0], vec3(lPos.xy, lPos.z - pointBias)).r;')
2018-12-11 23:05:18 +01:00
frag.write('}')
2019-01-09 21:25:09 +01:00
else:
frag.add_uniform('vec2 lightProj', link='_lightPlaneProj')
frag.add_uniform('samplerCubeShadow shadowMapPoint[1]')
frag.write('const float s = shadowmapCubePcfSize;') # TODO: incorrect...
2019-02-12 17:17:46 +01:00
frag.write('float compare = lpToDepth(ld, lightProj) - pointBias * 1.5;')
2020-05-11 09:03:13 +02:00
frag.write('#ifdef _InvY')
2019-02-12 12:39:41 +01:00
frag.write('l.y = -l.y;')
frag.write('#endif')
2019-02-10 20:37:38 +01:00
if '_Legacy' in wrd.world_defs:
2019-02-12 12:39:41 +01:00
frag.write('visibility = float(texture(shadowMapPoint[0], vec3(-l + n * pointBias * 20)).r > compare);')
2019-02-10 20:37:38 +01:00
else:
2019-02-12 12:39:41 +01:00
frag.write('visibility = texture(shadowMapPoint[0], vec4(-l + n * pointBias * 20, compare)).r;')
2018-12-10 23:29:04 +01:00
2018-12-10 17:25:29 +01:00
frag.write('direct += basecol * dotNL * pointCol * attenuate(distance(wposition, pointPos)) * visibility;')
2018-12-10 18:18:32 +01:00
if '_Clusters' in wrd.world_defs:
frag.add_include('std/light_mobile.glsl')
frag.write('vec3 albedo = basecol;')
frag.write('vec3 f0 = surfaceF0(basecol, metallic);')
make_cluster.write(vert, frag)
2017-04-26 14:21:22 +02:00
2017-11-13 10:19:07 +01:00
if '_Irr' in wrd.world_defs:
2017-12-20 10:19:44 +01:00
frag.add_include('std/shirr.glsl')
2020-05-10 19:43:02 +02:00
frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance')
env_str = 'shIrradiance(n, shirr)'
2017-11-13 10:19:07 +01:00
else:
env_str = '0.5'
frag.add_uniform('float envmapStrength', link='_envmapStrength')
frag.write('fragColor = vec4(direct + basecol * {0} * envmapStrength, 1.0);'.format(env_str))
2017-09-08 16:43:48 +02:00
2017-08-21 15:36:21 +02:00
if '_LDR' in wrd.world_defs:
2017-04-26 14:21:22 +02:00
frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')
2017-10-01 19:42:47 +02:00
def make_forward_solid(con_mesh):
wrd = bpy.data.worlds['Arm']
vert = con_mesh.make_vert()
frag = con_mesh.make_frag()
geom = None
tesc = None
tese = None
2018-12-14 15:27:43 +01:00
for e in con_mesh.data['vertex_elements']:
2018-11-24 20:01:35 +01:00
if e['name'] == 'nor':
2018-12-14 15:27:43 +01:00
con_mesh.data['vertex_elements'].remove(e)
2018-11-24 20:01:35 +01:00
break
2018-12-14 15:27:43 +01:00
vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);')
2017-10-01 19:42:47 +02:00
frag.ins = vert.outs
2018-11-14 21:51:30 +01:00
2018-12-14 15:27:43 +01:00
make_attrib.write_vertpos(vert)
2017-10-01 19:42:47 +02:00
frag.add_include('compiled.inc')
2017-10-01 19:42:47 +02:00
frag.write('vec3 basecol;')
frag.write('float roughness;')
frag.write('float metallic;')
frag.write('float occlusion;')
2018-05-19 19:29:14 +02:00
frag.write('float specular;')
2019-01-23 18:09:53 +01:00
if '_Emission' in wrd.world_defs:
frag.write('float emission;')
2018-11-14 21:34:53 +01:00
arm_discard = mat_state.material.arm_discard
blend = mat_state.material.arm_blending
is_transluc = mat_utils.is_transluc(mat_state.material)
parse_opacity = (blend and is_transluc) or arm_discard
if parse_opacity:
frag.write('float opacity;')
2020-05-06 18:11:02 +02:00
2018-11-14 21:34:53 +01:00
cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True)
if arm_discard:
opac = mat_state.material.arm_discard_opacity
frag.write('if (opacity < {0}) discard;'.format(opac))
2017-10-01 19:42:47 +02:00
if con_mesh.is_elem('tex'):
vert.add_out('vec2 texCoord')
2018-12-14 15:27:43 +01:00
vert.add_uniform('float texUnpack', link='_texUnpack')
2019-01-22 12:38:47 +01:00
if mat_state.material.arm_tilesheet_flag:
2018-11-14 22:28:19 +01:00
vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset')
2018-12-14 15:27:43 +01:00
vert.write('texCoord = tex * texUnpack + tilesheetOffset;')
2018-11-14 22:28:19 +01:00
else:
2018-12-14 15:27:43 +01:00
vert.write('texCoord = tex * texUnpack;')
2017-10-01 19:42:47 +02:00
if con_mesh.is_elem('col'):
vert.add_out('vec3 vcolor')
2019-01-07 10:42:45 +01:00
vert.write('vcolor = col.rgb;')
2017-10-01 19:42:47 +02:00
2018-12-14 15:27:43 +01:00
make_attrib.write_norpos(con_mesh, vert, write_nor=False)
2017-10-01 19:42:47 +02:00
frag.add_out('vec4 fragColor')
2018-11-14 21:34:53 +01:00
if blend and parse_opacity:
frag.write('fragColor = vec4(basecol, opacity);')
else:
frag.write('fragColor = vec4(basecol, 1.0);')
2017-10-01 19:42:47 +02:00
if '_LDR' in wrd.world_defs:
frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')
2016-12-21 00:51:04 +01:00
def make_forward(con_mesh):
2017-08-21 15:36:21 +02:00
wrd = bpy.data.worlds['Arm']
2019-01-23 13:45:58 +01:00
rpdat = arm.utils.get_rp()
2018-08-08 22:43:14 +02:00
blend = mat_state.material.arm_blending
2019-01-24 12:47:51 +01:00
parse_opacity = blend or mat_utils.is_transluc(mat_state.material)
2019-01-23 13:45:58 +01:00
2018-08-08 22:43:14 +02:00
make_forward_base(con_mesh, parse_opacity=parse_opacity)
2016-12-21 00:51:04 +01:00
2016-12-21 19:15:51 +01:00
frag = con_mesh.frag
2016-12-21 00:51:04 +01:00
2019-01-27 20:13:21 +01:00
if '_LTC' in wrd.world_defs:
frag.add_uniform('vec3 lightArea0', '_lightArea0', included=True)
frag.add_uniform('vec3 lightArea1', '_lightArea1', included=True)
frag.add_uniform('vec3 lightArea2', '_lightArea2', included=True)
frag.add_uniform('vec3 lightArea3', '_lightArea3', included=True)
frag.add_uniform('sampler2D sltcMat', '_ltcMat', included=True)
frag.add_uniform('sampler2D sltcMag', '_ltcMag', included=True)
2019-01-27 23:48:54 +01:00
if '_ShadowMap' in wrd.world_defs:
if '_SinglePoint' in wrd.world_defs:
frag.add_uniform('mat4 LWVPSpot0', link='_biasLightViewProjectionMatrixSpot0', included=True)
frag.add_uniform('sampler2DShadow shadowMapSpot[1]', included=True)
if '_Clusters' in wrd.world_defs:
frag.add_uniform('mat4 LWVPSpot0', link='_biasLightWorldViewProjectionMatrixSpot0', included=True)
frag.add_uniform('mat4 LWVPSpot1', link='_biasLightWorldViewProjectionMatrixSpot1', included=True)
frag.add_uniform('mat4 LWVPSpot2', link='_biasLightWorldViewProjectionMatrixSpot2', included=True)
frag.add_uniform('mat4 LWVPSpot3', link='_biasLightWorldViewProjectionMatrixSpot3', included=True)
frag.add_uniform('sampler2DShadow shadowMapSpot[4]', included=True)
2019-01-27 20:13:21 +01:00
2017-10-16 09:25:18 +02:00
if not blend:
2019-01-23 13:45:58 +01:00
mrt = rpdat.rp_ssr
if mrt:
# Store light gbuffer for post-processing
frag.add_out('vec4 fragColor[2]')
frag.add_include('std/gbuffer.glsl')
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(direct + indirect, packFloat2(occlusion, specular));')
2019-07-07 22:02:07 +02:00
frag.write('fragColor[1] = vec4(n.xy, roughness, metallic);')
2019-01-23 13:45:58 +01:00
else:
frag.add_out('vec4 fragColor[1]')
frag.write('fragColor[0] = vec4(direct + indirect, 1.0);')
2017-10-16 09:25:18 +02:00
if '_LDR' in wrd.world_defs:
2017-12-20 10:19:44 +01:00
frag.add_include('std/tonemap.glsl')
2019-01-23 13:54:16 +01:00
frag.write('fragColor[0].rgb = tonemapFilmic(fragColor[0].rgb);')
2016-12-21 00:51:04 +01:00
2017-09-29 17:00:21 +02:00
# Particle opacity
2019-04-06 14:30:11 +02:00
if mat_state.material.arm_particle_flag and arm.utils.get_rp().arm_particles == 'On' and mat_state.material.arm_particle_fade:
2019-01-23 13:54:16 +01:00
frag.write('fragColor[0].rgb *= p_fade;')
2017-09-29 17:00:21 +02:00
2019-01-27 15:01:39 +01:00
def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False):
2018-06-13 12:20:20 +02:00
global is_displacement
2016-12-21 00:51:04 +01:00
wrd = bpy.data.worlds['Arm']
2017-09-29 17:00:21 +02:00
arm_discard = mat_state.material.arm_discard
make_base(con_mesh, parse_opacity=(parse_opacity or arm_discard))
2017-07-26 20:49:16 +02:00
2016-12-20 00:39:18 +01:00
vert = con_mesh.vert
frag = con_mesh.frag
tese = con_mesh.tese
2016-12-19 01:25:22 +01:00
2019-01-24 12:47:51 +01:00
if parse_opacity or arm_discard:
if arm_discard:
opac = mat_state.material.arm_discard_opacity
2019-01-27 15:01:39 +01:00
frag.write('if (opacity < {0}) discard;'.format(opac))
elif transluc_pass:
frag.write('if (opacity == 1.0) discard;')
2019-01-24 12:47:51 +01:00
else:
2019-02-11 11:12:41 +01:00
opac = '0.9999' # 1.0 - eps
frag.write('if (opacity < {0}) discard;'.format(opac))
2017-09-29 17:00:21 +02:00
blend = mat_state.material.arm_blending
if blend:
2019-01-23 13:54:16 +01:00
frag.add_out('vec4 fragColor[1]')
if parse_opacity:
2019-01-23 13:54:16 +01:00
frag.write('fragColor[0] = vec4(basecol, opacity);')
else:
2019-01-23 13:54:16 +01:00
# frag.write('fragColor[0] = vec4(basecol * lightCol * visibility, 1.0);')
frag.write('fragColor[0] = vec4(basecol, 1.0);')
# TODO: Fade out fragments near depth buffer here
return
2018-03-27 12:09:21 +02:00
frag.write_init("""
2017-07-26 20:49:16 +02:00
vec3 vVec = normalize(eyeDir);
float dotNV = max(dot(n, vVec), 0.0);
2018-03-27 12:09:21 +02:00
""")
2017-07-26 20:49:16 +02:00
2018-06-02 13:53:39 +02:00
sh = tese if tese != None else vert
sh.add_out('vec3 eyeDir')
sh.add_uniform('vec3 eye', '_cameraPosition')
sh.write('eyeDir = eye - wposition;')
2017-03-14 20:43:54 +01:00
2018-12-10 17:25:29 +01:00
frag.add_include('std/light.glsl')
is_shadows = '_ShadowMap' in wrd.world_defs
2017-10-16 09:25:18 +02:00
2016-12-19 01:25:22 +01:00
frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);')
frag.write('vec3 f0 = surfaceF0(basecol, metallic);')
2019-01-27 19:12:00 +01:00
if '_Brdf' in wrd.world_defs:
2019-04-26 11:12:09 +02:00
frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png')
2019-01-27 19:12:00 +01:00
frag.write('vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;')
if '_Irr' in wrd.world_defs:
frag.add_include('std/shirr.glsl')
2020-05-10 19:43:02 +02:00
frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance')
frag.write('vec3 indirect = shIrradiance(n, shirr);')
2019-01-27 19:12:00 +01:00
if '_EnvTex' in wrd.world_defs:
frag.write('indirect /= PI;')
frag.write('indirect *= albedo;')
if '_Rad' in wrd.world_defs:
frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance')
frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps')
frag.write('vec3 reflectionWorld = reflect(-vVec, n);')
frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);')
frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;')
if '_EnvLDR' in wrd.world_defs:
frag.write('prefilteredColor = pow(prefilteredColor, vec3(2.2));')
frag.write('indirect += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5;')
elif '_EnvCol' in wrd.world_defs:
frag.add_uniform('vec3 backgroundCol', link='_backgroundCol')
frag.write('indirect += backgroundCol * f0;')
else:
frag.write('vec3 indirect = albedo;')
frag.write('indirect *= occlusion;')
frag.add_uniform('float envmapStrength', link='_envmapStrength')
frag.write('indirect *= envmapStrength;')
if '_VoxelAOvar' in wrd.world_defs:
2019-01-27 19:12:00 +01:00
frag.add_include('std/conetrace.glsl')
frag.add_uniform('sampler3D voxels')
if '_VoxelGICam' in wrd.world_defs:
frag.add_uniform('vec3 eyeSnap', link='_cameraPositionSnap')
frag.write('vec3 voxpos = (wposition - eyeSnap) / voxelgiHalfExtents;')
else:
frag.write('vec3 voxpos = wposition / voxelgiHalfExtents;')
frag.write('indirect *= vec3(1.0 - traceAO(voxpos, n, voxels));')
2019-01-27 19:12:00 +01:00
frag.write('vec3 direct = vec3(0.0);')
frag.add_uniform('bool receiveShadow')
if '_Sun' in wrd.world_defs:
2018-11-22 22:47:14 +01:00
frag.add_uniform('vec3 sunCol', '_sunColor')
frag.add_uniform('vec3 sunDir', '_sunDirection')
2018-11-22 23:22:56 +01:00
frag.write('float svisibility = 1.0;')
frag.write('vec3 sh = normalize(vVec + sunDir);')
frag.write('float sdotNL = dot(n, sunDir);')
frag.write('float sdotNH = dot(n, sh);')
frag.write('float sdotVH = dot(vVec, sh);')
if is_shadows:
2018-12-15 15:07:30 +01:00
frag.add_uniform('sampler2DShadow shadowMap')
frag.add_uniform('float shadowsBias', '_sunShadowsBias')
frag.write('if (receiveShadow) {')
if '_CSM' in wrd.world_defs:
2018-12-15 19:03:11 +01:00
frag.add_include('std/shadows.glsl')
frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True)
frag.add_uniform('vec3 eye', '_cameraPosition')
2019-01-09 21:25:09 +01:00
frag.write('svisibility = shadowTestCascade(shadowMap, eye, wposition + n * shadowsBias * 10, shadowsBias);')
else:
if tese != None:
tese.add_out('vec4 lightPosition')
tese.add_uniform('mat4 LVP', '_biasLightViewProjectionMatrix')
tese.write('lightPosition = LVP * vec4(wposition, 1.0);')
else:
if is_displacement:
vert.add_out('vec4 lightPosition')
vert.add_uniform('mat4 LVP', '_biasLightViewProjectionMatrix')
vert.write('lightPosition = LVP * vec4(wposition, 1.0);')
else:
vert.add_out('vec4 lightPosition')
vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrix')
vert.write('lightPosition = LWVP * spos;')
frag.write('vec3 lPos = lightPosition.xyz / lightPosition.w;')
frag.write('const vec2 smSize = shadowmapSize;')
2018-12-15 19:03:11 +01:00
frag.write('svisibility = PCF(shadowMap, lPos.xy, lPos.z - shadowsBias, smSize);')
frag.write('}') # receiveShadow
2019-01-27 23:48:54 +01:00
if '_VoxelShadow' in wrd.world_defs and '_VoxelAOvar' in wrd.world_defs:
2019-02-09 15:34:16 +01:00
frag.write('svisibility *= 1.0 - traceShadow(voxels, voxpos, sunDir);')
2018-11-22 22:47:14 +01:00
frag.write('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;')
# sun
2018-12-10 17:25:29 +01:00
if '_SinglePoint' in wrd.world_defs:
frag.add_uniform('vec3 pointPos', link='_pointPosition')
frag.add_uniform('vec3 pointCol', link='_pointColor')
if '_Spot' in wrd.world_defs:
frag.add_uniform('vec3 spotDir', link='_spotDirection')
frag.add_uniform('vec2 spotData', link='_spotData')
2019-01-09 21:25:09 +01:00
if is_shadows:
frag.add_uniform('float pointBias', link='_pointShadowsBias')
if '_Spot' in wrd.world_defs:
# Skip world matrix, already in world-space
frag.add_uniform('mat4 LWVPSpot0', link='_biasLightViewProjectionMatrixSpot0', included=True)
2018-12-15 15:07:30 +01:00
frag.add_uniform('sampler2DShadow shadowMapSpot[1]', included=True)
2019-01-09 21:25:09 +01:00
else:
frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True)
frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True)
2018-12-10 17:25:29 +01:00
frag.write('direct += sampleLight(')
frag.write(' wposition, n, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0')
if is_shadows:
2018-12-10 23:29:04 +01:00
frag.write(' , 0, pointBias')
2018-12-10 17:25:29 +01:00
if '_Spot' in wrd.world_defs:
frag.write(' , true, spotData.x, spotData.y, spotDir')
2019-01-27 23:48:54 +01:00
if '_VoxelShadow' in wrd.world_defs and '_VoxelAOvar' in wrd.world_defs:
2019-01-27 19:12:00 +01:00
frag.write(' , voxels, voxpos')
2018-12-10 17:25:29 +01:00
frag.write(');')
2018-12-10 18:18:32 +01:00
if '_Clusters' in wrd.world_defs:
make_cluster.write(vert, frag)
2019-01-23 18:09:53 +01:00
if '_Emission' in wrd.world_defs:
frag.write('if (emission > 0.0) {')
frag.write(' direct = vec3(0.0);')
2019-05-01 21:27:19 +02:00
frag.write(' indirect += basecol * emission;')
2019-01-23 18:09:53 +01:00
frag.write('}')