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_skin as make_skin
|
2018-08-29 09:35:48 +02:00
|
|
|
import arm.material.make_inst as make_inst
|
2017-03-15 12:30:14 +01:00
|
|
|
import arm.material.make_tess as make_tess
|
2017-09-27 00:04:47 +02:00
|
|
|
import arm.material.make_particle as make_particle
|
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
|
|
|
|
2017-08-21 15:36:21 +02:00
|
|
|
def make(context_id):
|
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' }
|
2017-09-29 01:18:57 +02:00
|
|
|
|
2018-08-08 22:43:14 +02:00
|
|
|
# Blend context
|
|
|
|
mat = mat_state.material
|
|
|
|
blend = mat.arm_blending
|
2018-08-16 17:16:35 +02:00
|
|
|
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'
|
2018-08-16 17:16:35 +02:00
|
|
|
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'
|
|
|
|
|
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':
|
2016-12-20 00:39:18 +01:00
|
|
|
make_deferred(con_mesh)
|
2018-07-29 11:39:54 +02:00
|
|
|
# elif rid == 'Deferred Plus':
|
|
|
|
# make_deferred_plus(con_mesh)
|
|
|
|
elif rid == 'Pathtracer':
|
|
|
|
make_pathtracer(con_mesh)
|
2016-12-19 01:25:22 +01:00
|
|
|
|
2017-03-21 03:06:38 +01:00
|
|
|
make_finalize(con_mesh)
|
|
|
|
|
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
|
|
|
|
2017-03-14 20:43:54 +01:00
|
|
|
def make_finalize(con_mesh):
|
|
|
|
vert = con_mesh.vert
|
|
|
|
frag = con_mesh.frag
|
|
|
|
geom = con_mesh.geom
|
|
|
|
tesc = con_mesh.tesc
|
|
|
|
tese = con_mesh.tese
|
|
|
|
|
|
|
|
# Additional values referenced in cycles
|
2017-03-21 03:06:38 +01:00
|
|
|
# TODO: enable from cycles.py
|
2017-03-14 20:43:54 +01:00
|
|
|
if frag.contains('dotNV') and not frag.contains('float dotNV'):
|
2018-03-27 10:10:12 +02:00
|
|
|
frag.write_init('float dotNV = max(dot(n, vVec), 0.0);')
|
2017-03-14 20:43:54 +01:00
|
|
|
|
2017-03-23 12:01:25 +01:00
|
|
|
write_wpos = False
|
2017-03-14 20:43:54 +01:00
|
|
|
if frag.contains('vVec') and not frag.contains('vec3 vVec'):
|
2018-05-07 23:09:38 +02:00
|
|
|
if tese != None:
|
2017-03-14 20:43:54 +01:00
|
|
|
tese.add_out('vec3 eyeDir')
|
|
|
|
tese.add_uniform('vec3 eye', '_cameraPosition')
|
|
|
|
tese.write('eyeDir = eye - wposition;')
|
2017-03-23 12:01:25 +01:00
|
|
|
|
2017-03-14 20:43:54 +01:00
|
|
|
else:
|
2017-09-09 13:46:32 +02:00
|
|
|
if not vert.contains('wposition'):
|
|
|
|
write_wpos = True
|
2017-03-14 20:43:54 +01:00
|
|
|
vert.add_out('vec3 eyeDir')
|
|
|
|
vert.add_uniform('vec3 eye', '_cameraPosition')
|
|
|
|
vert.write('eyeDir = eye - wposition;')
|
2018-03-27 10:10:12 +02:00
|
|
|
frag.write_attrib('vec3 vVec = normalize(eyeDir);')
|
2017-03-14 20:43:54 +01:00
|
|
|
|
2017-03-23 12:01:25 +01:00
|
|
|
export_wpos = False
|
2017-03-14 20:43:54 +01:00
|
|
|
if frag.contains('wposition') and not frag.contains('vec3 wposition'):
|
2018-06-13 12:20:20 +02:00
|
|
|
export_wpos = True
|
|
|
|
if tese != None:
|
|
|
|
export_wpos = True
|
|
|
|
if vert.contains('wposition'):
|
|
|
|
write_wpos = True
|
2017-03-23 12:01:25 +01:00
|
|
|
|
|
|
|
if export_wpos:
|
|
|
|
vert.add_uniform('mat4 W', '_worldMatrix')
|
|
|
|
vert.add_out('vec3 wposition')
|
2018-05-07 23:09:38 +02:00
|
|
|
vert.write_attrib('wposition = vec4(W * spos).xyz;')
|
2017-03-23 12:01:25 +01:00
|
|
|
elif write_wpos:
|
|
|
|
vert.add_uniform('mat4 W', '_worldMatrix')
|
2018-05-07 23:09:38 +02:00
|
|
|
vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;')
|
2017-03-14 20:43:54 +01:00
|
|
|
|
2018-08-07 14:14:12 +02:00
|
|
|
frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition')
|
2018-01-29 11:21:43 +01:00
|
|
|
if frag_mpos:
|
2017-09-01 23:34:29 +02:00
|
|
|
vert.add_out('vec3 mposition')
|
2018-05-21 17:55:26 +02:00
|
|
|
vert.write_attrib('mposition = spos.xyz;')
|
2018-01-28 20:02:41 +01:00
|
|
|
|
|
|
|
if tese != None:
|
2018-01-29 11:21:43 +01:00
|
|
|
if frag_mpos:
|
|
|
|
make_tess.interpolate(tese, 'mposition', 3, declare_out=True)
|
|
|
|
elif tese.contains('mposition') and not tese.contains('vec3 mposition'):
|
2018-01-28 20:02:41 +01:00
|
|
|
vert.add_out('vec3 mposition')
|
|
|
|
vert.write_pre = True
|
|
|
|
vert.write('mposition = spos.xyz;')
|
|
|
|
vert.write_pre = False
|
|
|
|
make_tess.interpolate(tese, 'mposition', 3, declare_out=False)
|
2017-09-01 23:34:29 +02:00
|
|
|
|
2018-08-07 14:14:12 +02:00
|
|
|
frag_bpos = (frag.contains('bposition') and not frag.contains('vec3 bposition')) or vert.contains('bposition')
|
2018-05-21 17:55:26 +02:00
|
|
|
if frag_bpos:
|
|
|
|
vert.add_out('vec3 bposition')
|
|
|
|
vert.add_uniform('vec3 dim', link='_dim')
|
|
|
|
vert.add_uniform('vec3 hdim', link='_halfDim')
|
|
|
|
vert.write_pre = True
|
|
|
|
vert.write('bposition = (spos.xyz + hdim) / dim;')
|
|
|
|
vert.write_pre = False
|
|
|
|
|
|
|
|
if tese != None:
|
|
|
|
if frag_bpos:
|
|
|
|
make_tess.interpolate(tese, 'bposition', 3, declare_out=True)
|
|
|
|
elif tese.contains('bposition') and not tese.contains('vec3 bposition'):
|
|
|
|
vert.add_out('vec3 bposition')
|
|
|
|
vert.write_pre = True
|
|
|
|
vert.write('bposition = spos.xyz;')
|
|
|
|
vert.write_pre = False
|
|
|
|
make_tess.interpolate(tese, 'bposition', 3, declare_out=False)
|
|
|
|
|
2018-08-07 14:14:12 +02:00
|
|
|
frag_wtan = (frag.contains('wtangent') and not frag.contains('vec3 wtangent')) or vert.contains('wtangent')
|
|
|
|
if frag_wtan:
|
|
|
|
# Indicate we want tang attrib in finalizer to prevent TBN generation
|
2018-08-07 16:34:14 +02:00
|
|
|
con_mesh.add_elem('tex', 2)
|
2018-08-07 14:14:12 +02:00
|
|
|
con_mesh.add_elem('tang', 3)
|
|
|
|
vert.add_out('vec3 wtangent')
|
|
|
|
vert.write_pre = True
|
|
|
|
vert.write('wtangent = normalize(N * tang);')
|
|
|
|
vert.write_pre = False
|
|
|
|
|
|
|
|
if tese != None:
|
|
|
|
if frag_wtan:
|
|
|
|
make_tess.interpolate(tese, 'wtangent', 3, declare_out=True)
|
|
|
|
elif tese.contains('wtangent') and not tese.contains('vec3 wtangent'):
|
|
|
|
vert.add_out('vec3 wtangent')
|
|
|
|
vert.write_pre = True
|
|
|
|
vert.write('wtangent = normalize(N * tang);')
|
|
|
|
vert.write_pre = False
|
|
|
|
make_tess.interpolate(tese, 'wtangent', 3, declare_out=False)
|
|
|
|
|
|
|
|
if frag.contains('vVecCam'):
|
|
|
|
vert.add_out('vec3 eyeDirCam')
|
|
|
|
vert.add_uniform('mat4 WV', '_worldViewMatrix')
|
|
|
|
vert.write('eyeDirCam = vec4(WV * spos).xyz; eyeDirCam.z *= -1;')
|
|
|
|
frag.write_attrib('vec3 vVecCam = normalize(eyeDirCam);')
|
|
|
|
|
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
|
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-03-26 18:15:02 +02:00
|
|
|
vert.write_attrib(' vec4 spos = vec4(pos, 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
|
|
|
|
2018-08-30 15:42:25 +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;')
|
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-01-07 20:01:43 +01:00
|
|
|
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')
|
2017-09-21 18:30:02 +02:00
|
|
|
if mat_state.material.arm_tilesheet_mat:
|
2018-08-16 17:16:35 +02:00
|
|
|
if mat_state.material.arm_particle_flag and rpdat.arm_particles == 'GPU':
|
2017-09-29 01:18:57 +02:00
|
|
|
make_particle.write_tilesheet(vert)
|
|
|
|
else:
|
|
|
|
vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset')
|
2018-05-07 23:09:38 +02:00
|
|
|
vert.write_attrib('texCoord = tex + tilesheetOffset;')
|
2017-09-21 18:30:02 +02:00
|
|
|
else:
|
2018-05-07 23:09:38 +02:00
|
|
|
vert.write_attrib('texCoord = tex;')
|
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-06-13 14:14:09 +02:00
|
|
|
vert.write_attrib('texCoord1 = tex1;')
|
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')
|
2018-06-13 14:14:09 +02:00
|
|
|
vert.write_attrib('vcolor = col;')
|
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')
|
2017-05-25 16:48:41 +02:00
|
|
|
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')
|
2017-05-25 16:48:41 +02:00
|
|
|
write_norpos(con_mesh, vert, declare=True)
|
2017-03-11 01:50:47 +01:00
|
|
|
vert.write('vec3 tangent = normalize(N * tang);')
|
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')
|
2017-05-25 16:48:41 +02:00
|
|
|
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')
|
2018-05-10 13:52:07 +02:00
|
|
|
sh.write('wposition += wnormal * disp * 0.1;')
|
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
|
|
|
|
2018-01-07 20:01:43 +01:00
|
|
|
def write_vertpos(vert):
|
|
|
|
billboard = mat_state.material.arm_billboard
|
2018-08-16 17:16:35 +02:00
|
|
|
particle = mat_state.material.arm_particle_flag
|
2018-01-07 20:01:43 +01:00
|
|
|
# Particles
|
2018-08-16 17:16:35 +02:00
|
|
|
if particle:
|
|
|
|
if arm.utils.get_rp().arm_particles == 'GPU':
|
2018-01-07 20:01:43 +01:00
|
|
|
make_particle.write(vert, particle_info=cycles.particle_info)
|
|
|
|
# Billboards
|
|
|
|
if billboard == 'spherical':
|
|
|
|
vert.add_uniform('mat4 WV', '_worldViewMatrix')
|
|
|
|
vert.add_uniform('mat4 P', '_projectionMatrix')
|
|
|
|
vert.write('gl_Position = P * (WV * vec4(0.0, 0.0, spos.z, 1.0) + vec4(spos.x, spos.y, 0.0, 0.0));')
|
|
|
|
else:
|
|
|
|
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
|
|
|
|
vert.write('gl_Position = WVP * spos;')
|
|
|
|
else:
|
|
|
|
# Billboards
|
|
|
|
if billboard == 'spherical':
|
|
|
|
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrixSphere')
|
|
|
|
elif billboard == 'cylindrical':
|
|
|
|
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrixCylinder')
|
|
|
|
else: # off
|
|
|
|
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
|
|
|
|
vert.write('gl_Position = WVP * spos;')
|
|
|
|
|
2017-10-01 19:49:15 +02:00
|
|
|
def write_norpos(con_mesh, vert, declare=False, write_nor=True):
|
2016-12-19 01:25:22 +01:00
|
|
|
prep = ''
|
|
|
|
if declare:
|
|
|
|
prep = 'vec3 '
|
|
|
|
vert.write_pre = True
|
2017-10-01 19:49:15 +02:00
|
|
|
is_bone = con_mesh.is_elem('bone')
|
|
|
|
if is_bone:
|
2016-12-19 01:25:22 +01:00
|
|
|
make_skin.skin_pos(vert)
|
2017-10-01 19:49:15 +02:00
|
|
|
if write_nor:
|
|
|
|
if is_bone:
|
2017-10-10 09:57:23 +02:00
|
|
|
make_skin.skin_nor(vert, prep)
|
2017-10-01 19:49:15 +02:00
|
|
|
else:
|
|
|
|
vert.write(prep + 'wnormal = normalize(N * nor);')
|
2018-08-29 09:35:48 +02:00
|
|
|
if con_mesh.is_elem('ipos'):
|
|
|
|
make_inst.inst_pos(con_mesh, vert)
|
2016-12-19 01:25:22 +01:00
|
|
|
vert.write_pre = False
|
|
|
|
|
2016-12-20 00:39:18 +01:00
|
|
|
def make_deferred(con_mesh):
|
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
|
2017-08-21 20:16:06 +02:00
|
|
|
parse_opacity = arm_discard or rpdat.arm_voxelgi_refraction
|
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
|
|
|
|
2017-08-21 12:17:55 +02:00
|
|
|
if arm_discard:
|
2017-08-23 22:53:39 +02:00
|
|
|
opac = mat_state.material.arm_discard_opacity
|
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:
|
2016-12-21 00:51:04 +01:00
|
|
|
frag.add_out('vec4[3] fragColor')
|
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);')
|
|
|
|
|
2017-06-23 15:47:51 +02:00
|
|
|
elif gapi.startswith('direct3d'):
|
|
|
|
vert.add_out('vec4 wvpposition')
|
|
|
|
vert.write('wvpposition = gl_Position;')
|
|
|
|
frag.add_out('vec4[2] fragColor')
|
2016-12-21 00:51:04 +01:00
|
|
|
else:
|
|
|
|
frag.add_out('vec4[2] fragColor')
|
|
|
|
|
|
|
|
# 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);')
|
2017-03-11 01:50:47 +01:00
|
|
|
# TODO: store_depth
|
2017-06-23 15:47:51 +02:00
|
|
|
if gapi.startswith('direct3d'):
|
|
|
|
frag.write('fragColor[0] = vec4(n.xy, packFloat(metallic, roughness), 1.0 - ((wvpposition.z / wvpposition.w) * 0.5 + 0.5));')
|
|
|
|
else:
|
|
|
|
frag.write('fragColor[0] = vec4(n.xy, packFloat(metallic, roughness), 1.0 - gl_FragCoord.z);')
|
2018-05-26 16:39:10 +02:00
|
|
|
frag.write('fragColor[1] = vec4(basecol.rgb, 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);')
|
|
|
|
if rpdat.arm_voxelgi_refraction:
|
|
|
|
frag.write('fragColor[2].b = opacity;')
|
|
|
|
if '_SSS' in wrd.world_defs or '_Hair' in wrd.world_defs:
|
|
|
|
frag.add_uniform('int materialID')
|
|
|
|
frag.write('fragColor[2].a = materialID;')
|
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-07-29 11:39:54 +02:00
|
|
|
# def make_deferred_plus(con_mesh):
|
|
|
|
# vert = con_mesh.make_vert()
|
|
|
|
# frag = con_mesh.make_frag()
|
2017-03-23 13:18:13 +01:00
|
|
|
|
2018-07-29 11:39:54 +02:00
|
|
|
# frag.add_out('vec4[3] fragColor')
|
2017-03-23 13:18:13 +01:00
|
|
|
|
2018-07-29 11:39:54 +02:00
|
|
|
# vert.add_uniform('mat3 N', '_normalMatrix')
|
|
|
|
# vert.write_attrib('vec4 spos = vec4(pos, 1.0);')
|
2017-03-23 13:18:13 +01:00
|
|
|
|
2018-07-29 11:39:54 +02:00
|
|
|
# frag.ins = vert.outs
|
|
|
|
# vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
|
|
|
|
# vert.write('gl_Position = WVP * spos;')
|
2017-03-23 13:18:13 +01:00
|
|
|
|
2018-08-30 15:42:25 +02:00
|
|
|
# frag.add_include('compiled.inc')
|
2017-03-23 13:18:13 +01:00
|
|
|
|
2018-07-29 11:39:54 +02:00
|
|
|
# vert.add_out('vec2 texCoord')
|
2017-03-28 14:30:51 +02:00
|
|
|
|
2018-07-29 11:39:54 +02:00
|
|
|
# con_mesh.add_elem('tex', 2) #### Add using cycles.py
|
|
|
|
# if con_mesh.is_elem('tex'):
|
|
|
|
# vert.write_attrib('texCoord = tex;')
|
|
|
|
# else:
|
|
|
|
# vert.write_attrib('texCoord = vec2(0.0);')
|
2017-03-23 13:18:13 +01:00
|
|
|
|
2018-07-29 11:39:54 +02:00
|
|
|
# vert.add_out('vec3 wnormal')
|
|
|
|
# write_norpos(con_mesh, vert)
|
|
|
|
# frag.write_attrib('vec3 n = normalize(wnormal);')
|
2017-03-23 13:18:13 +01:00
|
|
|
|
2018-07-29 11:39:54 +02:00
|
|
|
# frag.add_uniform('float materialID', link='_objectInfoMaterialIndex')
|
2017-03-28 14:30:51 +02:00
|
|
|
|
2018-07-29 11:39:54 +02:00
|
|
|
# # Pack gbuffer
|
|
|
|
# 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(n.xy, fract(texCoord));')
|
|
|
|
# frag.write('fragColor[1] = vec4(materialID, 0.0, 0.0, 0.0);')
|
|
|
|
# frag.write('fragColor[2] = vec4(dFdx(texCoord), dFdy(texCoord));')
|
|
|
|
# # + tangent space
|
|
|
|
|
|
|
|
def make_pathtracer(con_mesh):
|
|
|
|
wrd = bpy.data.worlds['Arm']
|
|
|
|
vert = con_mesh.make_vert()
|
|
|
|
frag = con_mesh.make_frag()
|
|
|
|
vert.add_out('vec3 n')
|
|
|
|
vert.write('n = nor;')
|
|
|
|
vert.write('gl_Position = vec4(pos, 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-03-26 18:15:02 +02:00
|
|
|
vert.write_attrib('vec4 spos = vec4(pos, 1.0);')
|
2017-04-26 14:21:22 +02:00
|
|
|
frag.ins = vert.outs
|
|
|
|
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
|
2018-07-16 17:27:35 +02:00
|
|
|
# Written in finalizer
|
|
|
|
# vert.add_uniform('mat4 W', '_worldMatrix')
|
|
|
|
# vert.add_out('vec3 wposition')
|
|
|
|
# vert.write_attrib('wposition = vec4(W * spos).xyz;')
|
2017-04-26 14:21:22 +02:00
|
|
|
vert.write('gl_Position = WVP * spos;')
|
|
|
|
|
2018-08-30 15:42:25 +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;')
|
2017-09-09 13:46:32 +02:00
|
|
|
cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=False, parse_displacement=False)
|
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-05-07 23:09:38 +02:00
|
|
|
vert.write_attrib('texCoord = tex;')
|
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')
|
|
|
|
vert.write('vcolor = col;')
|
|
|
|
|
2018-08-01 11:46:38 +02:00
|
|
|
if con_mesh.is_elem('tang'):
|
|
|
|
vert.add_out('mat3 TBN')
|
|
|
|
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(con_mesh, vert)
|
|
|
|
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')
|
2018-08-28 15:10:28 +02:00
|
|
|
frag.add_uniform('vec3 lightColor', '_lightColor')
|
|
|
|
frag.add_uniform('vec3 lightDir', '_lightDirection')
|
|
|
|
frag.add_uniform('vec3 lightPos', '_lightPosition')
|
2017-04-26 14:21:22 +02:00
|
|
|
frag.add_uniform('float envmapStrength', link='_envmapStrength')
|
|
|
|
|
2017-10-12 12:12:48 +02:00
|
|
|
is_shadows = not '_NoShadows' in wrd.world_defs
|
2017-04-26 14:21:22 +02:00
|
|
|
|
|
|
|
frag.write('float visibility = 1.0;')
|
2017-09-08 16:43:48 +02:00
|
|
|
frag.write('float dotNL = max(dot(n, lightDir), 0.0);')
|
2017-04-26 14:21:22 +02:00
|
|
|
|
|
|
|
if is_shadows:
|
2018-08-28 15:10:28 +02:00
|
|
|
vert.add_out('vec4 lightPosition')
|
|
|
|
vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrix')
|
|
|
|
vert.write('lightPosition = LWVP * spos;')
|
2017-12-20 10:19:44 +01:00
|
|
|
frag.add_include('std/shadows.glsl')
|
2018-01-29 23:52:42 +01:00
|
|
|
frag.add_uniform('sampler2D shadowMap')
|
2018-08-28 15:10:28 +02:00
|
|
|
frag.add_uniform('float shadowsBias', '_lightShadowsBias')
|
|
|
|
frag.write(' if (lightPosition.w > 0.0) {')
|
|
|
|
frag.write(' vec3 lPos = lightPosition.xyz / lightPosition.w;')
|
2017-04-26 14:21:22 +02:00
|
|
|
frag.write(' const float texelSize = 1.0 / shadowmapSize.x;')
|
|
|
|
frag.write(' visibility = 0.0;')
|
2017-11-15 13:34:51 +01:00
|
|
|
# TODO: CSM
|
2017-11-20 12:38:35 +01:00
|
|
|
frag.write(' visibility += float(texture(shadowMap, lPos.xy).r + shadowsBias > lPos.z);')
|
|
|
|
frag.write(' visibility += float(texture(shadowMap, lPos.xy + vec2(texelSize, 0.0)).r + shadowsBias > lPos.z) * 0.5;')
|
|
|
|
frag.write(' visibility += float(texture(shadowMap, lPos.xy + vec2(-texelSize, 0.0)).r + shadowsBias > lPos.z) * 0.25;')
|
|
|
|
frag.write(' visibility += float(texture(shadowMap, lPos.xy + vec2(0.0, texelSize)).r + shadowsBias > lPos.z) * 0.5;')
|
|
|
|
frag.write(' visibility += float(texture(shadowMap, lPos.xy + vec2(0.0, -texelSize)).r + shadowsBias > lPos.z) * 0.25;')
|
2017-04-26 14:21:22 +02:00
|
|
|
frag.write(' visibility /= 2.5;')
|
2018-01-30 13:16:32 +01:00
|
|
|
frag.write(' visibility = max(visibility, 0.2);')
|
2017-11-20 12:38:35 +01:00
|
|
|
# frag.write(' visibility = max(float(texture(shadowMap, lPos.xy).r + shadowsBias > lPos.z), 0.5);')
|
2017-04-26 14:21:22 +02:00
|
|
|
frag.write(' }')
|
|
|
|
|
2017-10-16 09:25:18 +02:00
|
|
|
frag.add_out('vec4 fragColor')
|
|
|
|
blend = mat_state.material.arm_blending
|
|
|
|
if blend:
|
|
|
|
# frag.write('fragColor = vec4(basecol * visibility, 1.0);')
|
|
|
|
frag.write('fragColor = vec4(basecol, 1.0);')
|
|
|
|
return
|
|
|
|
|
2017-09-08 16:43:48 +02:00
|
|
|
frag.write('vec3 direct = basecol * dotNL * lightColor;')
|
2017-10-16 23:11:07 +02:00
|
|
|
# frag.write('direct += vec3(D_Approx(max(roughness, 0.3), dot(reflect(-vVec, n), lightDir)));')
|
2017-09-08 16:43:48 +02:00
|
|
|
frag.write('direct *= attenuate(distance(wposition, lightPos));')
|
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')
|
2017-11-13 10:19:07 +01:00
|
|
|
frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance', included=True)
|
|
|
|
env_str = 'shIrradiance(n)'
|
|
|
|
else:
|
|
|
|
env_str = '0.5'
|
|
|
|
frag.write('fragColor = vec4(direct * visibility + 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-03-26 18:15:02 +02:00
|
|
|
vert.write_attrib('vec4 spos = vec4(pos, 1.0);')
|
2017-10-01 19:42:47 +02:00
|
|
|
frag.ins = vert.outs
|
|
|
|
vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix')
|
|
|
|
vert.write('gl_Position = WVP * spos;')
|
|
|
|
|
2018-08-30 15:42:25 +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;')
|
2018-06-02 17:00:54 +02:00
|
|
|
cycles.parse(mat_state.nodes, con_mesh, vert, frag, geom, tesc, tese, parse_opacity=False, parse_displacement=False, basecol_only=True)
|
2017-10-01 19:42:47 +02:00
|
|
|
|
|
|
|
if con_mesh.is_elem('tex'):
|
|
|
|
vert.add_out('vec2 texCoord')
|
2018-05-07 23:09:38 +02:00
|
|
|
vert.write_attrib('texCoord = tex;')
|
2017-10-01 19:42:47 +02:00
|
|
|
|
|
|
|
if con_mesh.is_elem('col'):
|
|
|
|
vert.add_out('vec3 vcolor')
|
|
|
|
vert.write('vcolor = col;')
|
|
|
|
|
2017-10-01 19:49:15 +02:00
|
|
|
write_norpos(con_mesh, vert, write_nor=False)
|
2017-10-01 19:42:47 +02:00
|
|
|
|
|
|
|
frag.add_out('vec4 fragColor')
|
|
|
|
frag.write('fragColor = vec4(basecol, 1.0);')
|
|
|
|
|
|
|
|
if '_LDR' in wrd.world_defs:
|
|
|
|
frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')
|
|
|
|
|
2018-07-15 19:55:36 +02:00
|
|
|
if arm.utils.get_gapi().startswith('direct3d'):
|
|
|
|
vert.add_out('vec3 normal') # Prevent discard
|
|
|
|
vert.write('normal = nor;')
|
|
|
|
|
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']
|
2018-08-08 22:43:14 +02:00
|
|
|
blend = mat_state.material.arm_blending
|
|
|
|
parse_opacity = blend and mat_utils.is_transluc(mat_state.material)
|
|
|
|
|
|
|
|
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
|
|
|
|
2017-10-16 09:25:18 +02:00
|
|
|
if not blend:
|
|
|
|
frag.add_out('vec4 fragColor')
|
2018-03-27 12:29:12 +02:00
|
|
|
frag.write('fragColor = vec4(direct * lightColor * visibility + indirect * occlusion, 1.0);')
|
2016-12-21 00:51:04 +01:00
|
|
|
|
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')
|
2017-10-16 09:25:18 +02:00
|
|
|
frag.write('fragColor.rgb = tonemapFilmic(fragColor.rgb);')
|
|
|
|
# frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')
|
2016-12-21 00:51:04 +01:00
|
|
|
|
2017-09-29 17:00:21 +02:00
|
|
|
# Particle opacity
|
2018-08-16 17:16:35 +02:00
|
|
|
if mat_state.material.arm_particle_flag and arm.utils.get_rp().arm_particles == 'GPU' and mat_state.material.arm_particle_fade:
|
2017-10-04 18:24:13 +02:00
|
|
|
frag.write('fragColor.rgb *= p_fade;')
|
2017-09-29 17:00:21 +02:00
|
|
|
|
2016-12-21 00:51:04 +01:00
|
|
|
def make_forward_base(con_mesh, parse_opacity=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
|
|
|
|
2017-09-29 17:00:21 +02:00
|
|
|
if arm_discard:
|
|
|
|
opac = mat_state.material.arm_discard_opacity
|
|
|
|
frag.write('if (opacity < {0}) discard;'.format(opac))
|
|
|
|
|
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
|
|
|
|
2017-12-20 10:19:44 +01:00
|
|
|
frag.add_include('std/brdf.glsl')
|
|
|
|
frag.add_include('std/math.glsl')
|
2018-08-28 15:10:28 +02:00
|
|
|
frag.add_uniform('vec3 lightColor', '_lightColor')
|
|
|
|
frag.add_uniform('vec3 lightDir', '_lightDirection')
|
|
|
|
frag.add_uniform('vec3 lightPos', '_lightPosition')
|
|
|
|
frag.add_uniform('int lightType', '_lightType')
|
|
|
|
frag.add_uniform('vec2 spotlightData', '_spotlightData') # cutoff, cutoff - exponent
|
2016-12-19 01:25:22 +01:00
|
|
|
frag.add_uniform('float envmapStrength', link='_envmapStrength')
|
2017-01-23 20:41:45 +01:00
|
|
|
|
2018-01-29 19:06:57 +01:00
|
|
|
if '_Brdf' in wrd.world_defs:
|
|
|
|
frag.add_uniform('sampler2D senvmapBrdf', link='_envmapBrdf')
|
2017-01-23 20:41:45 +01:00
|
|
|
if '_Irr' in wrd.world_defs:
|
2017-12-20 10:19:44 +01:00
|
|
|
frag.add_include('std/shirr.glsl')
|
2017-02-07 11:50:21 +01:00
|
|
|
frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance', included=True)
|
2017-01-23 20:41:45 +01:00
|
|
|
if '_Rad' in wrd.world_defs:
|
|
|
|
frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance')
|
|
|
|
frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps')
|
2016-12-20 00:39:18 +01:00
|
|
|
|
2017-10-12 12:12:48 +02:00
|
|
|
is_shadows = not '_NoShadows' in wrd.world_defs
|
2016-12-20 00:39:18 +01:00
|
|
|
|
2016-12-19 01:25:22 +01:00
|
|
|
frag.write('float visibility = 1.0;')
|
2017-03-20 21:02:23 +01:00
|
|
|
frag.write('vec3 lp = lightPos - wposition;')
|
2017-03-02 10:15:22 +01:00
|
|
|
frag.write('vec3 l;')
|
|
|
|
frag.write('if (lightType == 0) l = lightDir;')
|
2017-03-20 21:02:23 +01:00
|
|
|
frag.write('else { l = normalize(lp); visibility *= attenuate(distance(wposition, lightPos)); }')
|
2017-03-14 20:43:54 +01:00
|
|
|
frag.write('vec3 h = normalize(vVec + l);')
|
2017-03-02 10:15:22 +01:00
|
|
|
frag.write('float dotNL = dot(n, l);')
|
|
|
|
frag.write('float dotNH = dot(n, h);')
|
2017-03-14 20:43:54 +01:00
|
|
|
frag.write('float dotVH = dot(vVec, h);')
|
2017-03-02 10:15:22 +01:00
|
|
|
|
2017-01-23 00:48:59 +01:00
|
|
|
if is_shadows:
|
|
|
|
if tese != None:
|
2018-08-28 15:10:28 +02:00
|
|
|
tese.add_out('vec4 lightPosition')
|
|
|
|
tese.add_uniform('mat4 LVP', '_biasLightViewProjectionMatrix')
|
|
|
|
tese.add_uniform('int lightShadow', '_lightCastShadow')
|
|
|
|
tese.write('if (lightShadow == 1) lightPosition = LVP * vec4(wposition, 1.0);')
|
2017-01-23 00:48:59 +01:00
|
|
|
else:
|
2018-06-13 12:20:20 +02:00
|
|
|
if is_displacement:
|
2018-08-28 15:10:28 +02:00
|
|
|
vert.add_out('vec4 lightPosition')
|
|
|
|
vert.add_uniform('mat4 LVP', '_biasLightViewProjectionMatrix')
|
|
|
|
vert.add_uniform('int lightShadow', '_lightCastShadow')
|
|
|
|
vert.write('if (lightShadow == 1) lightPosition = LVP * vec4(wposition, 1.0);')
|
2018-06-13 12:20:20 +02:00
|
|
|
else:
|
2018-08-28 15:10:28 +02:00
|
|
|
vert.add_out('vec4 lightPosition')
|
|
|
|
vert.add_uniform('int lightShadow', '_lightCastShadow')
|
|
|
|
vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrix')
|
|
|
|
vert.write('if (lightShadow == 1) lightPosition = LWVP * spos;')
|
2017-01-23 00:48:59 +01:00
|
|
|
|
2017-12-20 10:19:44 +01:00
|
|
|
frag.add_include('std/shadows.glsl')
|
2018-01-29 23:52:42 +01:00
|
|
|
frag.add_uniform('sampler2D shadowMap')
|
|
|
|
frag.add_uniform('samplerCube shadowMapCube')
|
2017-01-23 00:48:59 +01:00
|
|
|
frag.add_uniform('bool receiveShadow')
|
2018-08-28 15:10:28 +02:00
|
|
|
frag.add_uniform('float shadowsBias', '_lightShadowsBias')
|
|
|
|
frag.add_uniform('int lightShadow', '_lightCastShadow')
|
|
|
|
frag.add_uniform('vec2 lightProj', '_lightPlaneProj')
|
2017-01-23 00:48:59 +01:00
|
|
|
|
2017-03-20 21:02:23 +01:00
|
|
|
frag.write('if (receiveShadow) {')
|
2017-11-15 13:34:51 +01:00
|
|
|
frag.write(' if (lightShadow == 1) {')
|
|
|
|
if '_CSM' in wrd.world_defs:
|
2018-08-30 15:42:25 +02:00
|
|
|
frag.add_include('compiled.inc')
|
2017-11-15 13:34:51 +01:00
|
|
|
frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True)
|
|
|
|
frag.add_uniform('vec3 eye', '_cameraPosition')
|
2017-11-20 12:38:35 +01:00
|
|
|
frag.write('vec2 smSize;')
|
|
|
|
frag.write('vec3 lPos;')
|
|
|
|
frag.write('if (lightType == 0) {')
|
2017-11-15 13:34:51 +01:00
|
|
|
frag.write(' int casi;')
|
|
|
|
frag.write(' int casindex;')
|
|
|
|
frag.write(' mat4 LWVP = getCascadeMat(distance(eye, wposition), casi, casindex);')
|
2018-08-28 15:10:28 +02:00
|
|
|
frag.write(' vec4 lightPosition = LWVP * vec4(wposition, 1.0);')
|
|
|
|
frag.write(' lPos = lightPosition.xyz / lightPosition.w;')
|
2017-11-20 12:38:35 +01:00
|
|
|
frag.write(' smSize = shadowmapSize * vec2(shadowmapCascades, 1.0);')
|
|
|
|
frag.write('}')
|
|
|
|
frag.write('else {')
|
2018-08-28 15:10:28 +02:00
|
|
|
frag.write(' lPos = lightPosition.xyz / lightPosition.w;')
|
2017-11-20 12:38:35 +01:00
|
|
|
frag.write(' smSize = shadowmapSize;')
|
|
|
|
frag.write('}')
|
2017-01-23 00:48:59 +01:00
|
|
|
else:
|
2018-08-28 15:10:28 +02:00
|
|
|
frag.write(' vec3 lPos = lightPosition.xyz / lightPosition.w;')
|
2017-11-20 12:38:35 +01:00
|
|
|
frag.write(' const vec2 smSize = shadowmapSize;')
|
|
|
|
# frag.write('float bias = clamp(shadowsBias * 1.0 * tan(acos(clamp(dotNL, 0.0, 1.0))), 0.0, 0.01);')
|
2018-01-29 23:52:42 +01:00
|
|
|
frag.write(' visibility *= PCF(shadowMap, lPos.xy, lPos.z - shadowsBias, smSize);')
|
2017-03-20 21:02:23 +01:00
|
|
|
frag.write(' }')
|
2018-01-29 23:52:42 +01:00
|
|
|
frag.write(' else if (lightShadow == 2) visibility *= PCFCube(shadowMapCube, lp, -l, shadowsBias, lightProj, n);')
|
2017-01-23 00:48:59 +01:00
|
|
|
frag.write('}')
|
2016-12-19 01:25:22 +01:00
|
|
|
|
|
|
|
frag.write('if (lightType == 2) {')
|
2017-03-03 14:36:01 +01:00
|
|
|
frag.write(' float spotEffect = dot(lightDir, l);')
|
2017-03-11 01:50:47 +01:00
|
|
|
frag.write(' if (spotEffect < spotlightData.x) {')
|
|
|
|
frag.write(' visibility *= smoothstep(spotlightData.y, spotlightData.x, spotEffect);')
|
2017-03-03 14:36:01 +01:00
|
|
|
frag.write(' }')
|
2016-12-19 01:25:22 +01:00
|
|
|
frag.write('}')
|
|
|
|
|
2017-10-16 09:25:18 +02:00
|
|
|
blend = mat_state.material.arm_blending
|
|
|
|
if blend:
|
|
|
|
frag.add_out('vec4 fragColor')
|
2018-08-08 22:43:14 +02:00
|
|
|
if parse_opacity:
|
|
|
|
frag.write('fragColor = vec4(basecol, opacity);')
|
|
|
|
else:
|
|
|
|
# frag.write('fragColor = vec4(basecol * lightColor * visibility, 1.0);')
|
|
|
|
frag.write('fragColor = vec4(basecol, 1.0);')
|
2017-10-16 09:25:18 +02:00
|
|
|
# TODO: Fade out fragments near depth buffer here
|
|
|
|
return
|
|
|
|
|
2016-12-19 01:25:22 +01:00
|
|
|
frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);')
|
|
|
|
frag.write('vec3 f0 = surfaceF0(basecol, metallic);')
|
2017-03-03 14:36:01 +01:00
|
|
|
frag.write('vec3 direct;')
|
|
|
|
|
2017-11-27 14:29:21 +01:00
|
|
|
if '_LTC' in wrd.world_defs:
|
2017-12-20 10:19:44 +01:00
|
|
|
frag.add_include('std/ltc.glsl')
|
2017-03-03 14:36:01 +01:00
|
|
|
frag.add_uniform('sampler2D sltcMat', link='_ltcMat')
|
|
|
|
frag.add_uniform('sampler2D sltcMag', link='_ltcMag')
|
2018-08-28 15:10:28 +02:00
|
|
|
frag.add_uniform('vec3 lightArea0', link='_lightArea0')
|
|
|
|
frag.add_uniform('vec3 lightArea1', link='_lightArea1')
|
|
|
|
frag.add_uniform('vec3 lightArea2', link='_lightArea2')
|
|
|
|
frag.add_uniform('vec3 lightArea3', link='_lightArea3')
|
2017-03-03 14:36:01 +01:00
|
|
|
frag.write('if (lightType == 3) {')
|
|
|
|
frag.write(' float theta = acos(dotNV);')
|
|
|
|
frag.write(' vec2 tuv = vec2(roughness, theta / (0.5 * PI));')
|
|
|
|
frag.write(' tuv = tuv * LUT_SCALE + LUT_BIAS;')
|
|
|
|
frag.write(' vec4 t = texture(sltcMat, tuv);')
|
|
|
|
frag.write(' mat3 invM = mat3(vec3(1.0, 0.0, t.y), vec3(0.0, t.z, 0.0), vec3(t.w, 0.0, t.x));')
|
2018-08-28 15:10:28 +02:00
|
|
|
frag.write(' float ltcspec = ltcEvaluate(n, vVec, dotNV, wposition, invM, lightArea0, lightArea1, lightArea2, lightArea3);')
|
2017-03-03 14:36:01 +01:00
|
|
|
frag.write(' ltcspec *= texture(sltcMag, tuv).a;')
|
2018-08-28 15:10:28 +02:00
|
|
|
frag.write(' float ltcdiff = ltcEvaluate(n, vVec, dotNV, wposition, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);')
|
2018-05-19 19:29:14 +02:00
|
|
|
frag.write(' direct = albedo * ltcdiff + ltcspec * specular;')
|
2017-03-03 14:36:01 +01:00
|
|
|
frag.write('}')
|
|
|
|
frag.write('else {')
|
|
|
|
frag.tab += 1
|
|
|
|
|
|
|
|
frag.write('direct = lambertDiffuseBRDF(albedo, dotNL);')
|
2018-05-19 19:29:14 +02:00
|
|
|
frag.write('direct += specularBRDF(f0, roughness, dotNL, dotNH, dotNV, dotVH) * specular;')
|
2016-12-19 01:25:22 +01:00
|
|
|
|
2017-11-27 14:29:21 +01:00
|
|
|
if '_LTC' in wrd.world_defs:
|
2017-03-03 14:36:01 +01:00
|
|
|
frag.write('}')
|
|
|
|
frag.tab -= 1
|
|
|
|
|
2018-01-29 19:06:57 +01:00
|
|
|
if '_Brdf' in wrd.world_defs:
|
|
|
|
frag.write('vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;')
|
|
|
|
|
2017-01-23 20:41:45 +01:00
|
|
|
if '_Irr' in wrd.world_defs:
|
2017-09-25 10:30:41 +02:00
|
|
|
frag.write('vec3 indirect = shIrradiance(n);')
|
|
|
|
if '_EnvTex' in wrd.world_defs:
|
|
|
|
frag.write('indirect /= PI;')
|
|
|
|
frag.write('indirect *= albedo;')
|
2017-01-23 20:41:45 +01:00
|
|
|
|
|
|
|
if '_Rad' in wrd.world_defs:
|
2017-03-14 20:43:54 +01:00
|
|
|
frag.write('vec3 reflectionWorld = reflect(-vVec, n);')
|
2017-01-23 20:41:45 +01:00
|
|
|
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));')
|
2017-09-20 18:35:37 +02:00
|
|
|
frag.write('indirect += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5;')
|
2018-05-19 19:29:14 +02:00
|
|
|
elif '_EnvCol' in wrd.world_defs:
|
|
|
|
frag.add_uniform('vec3 backgroundCol', link='_backgroundCol')
|
|
|
|
frag.write('indirect += backgroundCol * f0;')
|
2017-01-23 20:41:45 +01:00
|
|
|
else:
|
|
|
|
frag.write('vec3 indirect = albedo;')
|
2018-03-27 12:29:12 +02:00
|
|
|
frag.write('indirect *= envmapStrength;')
|
2017-10-23 21:01:00 +02:00
|
|
|
|
|
|
|
if '_VoxelGI' in wrd.world_defs or '_VoxelAO' in wrd.world_defs:
|
2017-12-20 10:19:44 +01:00
|
|
|
frag.add_include('std/conetrace.glsl')
|
2018-01-29 23:52:42 +01:00
|
|
|
frag.add_uniform('sampler3D voxels')
|
2017-10-23 21:01:00 +02:00
|
|
|
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;')
|
|
|
|
if '_VoxelAO' in wrd.world_defs:
|
2017-12-19 18:05:38 +01:00
|
|
|
frag.write('indirect *= vec3(1.0 - traceAO(voxpos, n, voxels));')
|
|
|
|
# frag.write('indirect = vec3(1.0 - traceAO(voxpos, n, voxels));') # AO view
|
2017-10-23 21:01:00 +02:00
|
|
|
else:
|
2017-12-19 18:05:38 +01:00
|
|
|
frag.write('vec4 indirectDiffuse = traceDiffuse(voxpos, n, voxels);')
|
2018-05-21 17:55:26 +02:00
|
|
|
frag.write('indirect = indirect * voxelgiEnv + vec3(indirectDiffuse.rgb * voxelgiDiff * basecol);')
|
|
|
|
frag.write('if (specular > 0.0) {')
|
2018-01-29 23:52:42 +01:00
|
|
|
frag.write('vec3 indirectSpecular = traceSpecular(voxels, voxpos, n, vVec, roughness);')
|
2017-10-23 21:01:00 +02:00
|
|
|
frag.write('indirectSpecular *= f0 * envBRDF.x + envBRDF.y;')
|
2018-05-21 17:55:26 +02:00
|
|
|
frag.write('indirect += indirectSpecular * voxelgiSpec * specular;')
|
|
|
|
frag.write('}')
|