259 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			259 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | import bpy | ||
|  | 
 | ||
|  | import lnx.material.cycles as cycles | ||
|  | import lnx.material.mat_state as mat_state | ||
|  | import lnx.material.mat_utils as mat_utils | ||
|  | import lnx.material.make_skin as make_skin | ||
|  | import lnx.material.make_inst as make_inst | ||
|  | import lnx.material.make_tess as make_tess | ||
|  | import lnx.material.make_mesh as make_mesh | ||
|  | import lnx.material.make_attrib as make_attrib | ||
|  | import lnx.material.make_particle as make_particle | ||
|  | import lnx.material.make_finalize as make_finalize | ||
|  | import lnx.material.make_morph_target as make_morph_target | ||
|  | import lnx.assets as assets | ||
|  | import lnx.utils | ||
|  | 
 | ||
|  | if lnx.is_reload(__name__): | ||
|  |     cycles = lnx.reload_module(cycles) | ||
|  |     mat_state = lnx.reload_module(mat_state) | ||
|  |     mat_utils = lnx.reload_module(mat_utils) | ||
|  |     make_skin = lnx.reload_module(make_skin) | ||
|  |     make_inst = lnx.reload_module(make_inst) | ||
|  |     make_tess = lnx.reload_module(make_tess) | ||
|  |     make_particle = lnx.reload_module(make_particle) | ||
|  |     make_finalize = lnx.reload_module(make_finalize) | ||
|  |     assets = lnx.reload_module(assets) | ||
|  |     lnx.utils = lnx.reload_module(lnx.utils) | ||
|  | else: | ||
|  |     lnx.enable_reload(__name__) | ||
|  | 
 | ||
|  | 
 | ||
|  | def make(context_id, rpasses, shadowmap=False, shadowmap_transparent=False): | ||
|  | 
 | ||
|  |     is_disp = mat_utils.disp_linked(mat_state.output_node) | ||
|  | 
 | ||
|  |     vs = [{'name': 'pos', 'data': 'short4norm'}] | ||
|  |     if is_disp or shadowmap_transparent: | ||
|  |         vs.append({'name': 'nor', 'data': 'short2norm'}) | ||
|  | 
 | ||
|  |     if shadowmap_transparent: | ||
|  |         con_depth = mat_state.data.add_context({ | ||
|  |             'name': context_id, | ||
|  |             'vertex_elements': vs, | ||
|  |             'depth_write': False, | ||
|  |             'depth_read': True, | ||
|  |             'compare_mode': 'less', | ||
|  |             'cull_mode': 'clockwise', | ||
|  |             'blend_source': 'blend_zero', | ||
|  |             'blend_destination': 'source_color', | ||
|  |             'blend_operation': 'add', | ||
|  |             'color_writes_red': [True], | ||
|  |             'color_writes_green': [True], | ||
|  |             'color_writes_blue': [True], | ||
|  |             'color_writes_alpha': [True] | ||
|  |         }) | ||
|  |     else: | ||
|  |         con_depth = mat_state.data.add_context({ | ||
|  |             'name': context_id, | ||
|  |             'vertex_elements': vs, | ||
|  |             'depth_write': True, | ||
|  |             'depth_read': False, | ||
|  |             'compare_mode': 'less', | ||
|  |             'cull_mode': 'clockwise', | ||
|  |             'color_writes_red': [False], | ||
|  |             'color_writes_green': [False], | ||
|  |             'color_writes_blue': [False], | ||
|  |             'color_writes_alpha': [False] | ||
|  |         }) | ||
|  | 
 | ||
|  |     vert = con_depth.make_vert() | ||
|  |     frag = con_depth.make_frag() | ||
|  |     geom = None | ||
|  |     tesc = None | ||
|  |     tese = None | ||
|  | 
 | ||
|  |     vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);') | ||
|  |     vert.add_include('compiled.inc') | ||
|  |     frag.add_include('compiled.inc') | ||
|  | 
 | ||
|  |     parse_opacity = 'translucent' in rpasses or 'refraction' in rpasses or mat_state.material.lnx_discard | ||
|  | 
 | ||
|  |     parse_custom_particle = (cycles.node_by_name(mat_state.nodes, 'LnxCustomParticleNode') is not None) | ||
|  | 
 | ||
|  |     if shadowmap_transparent: | ||
|  |         billboard = mat_state.material.lnx_billboard | ||
|  |         if billboard == 'spherical': | ||
|  |             vert.add_uniform('mat3 N', '_normalMatrixSphere') | ||
|  |         elif billboard == 'cylindrical': | ||
|  |             vert.add_uniform('mat3 N', '_normalMatrixCylinder') | ||
|  |         else: | ||
|  |             vert.add_uniform('mat3 N', '_normalMatrix') | ||
|  |         make_mesh._write_material_attribs_default(frag, parse_opacity) #TODO remove duplicate parsing | ||
|  |         vert.add_out('vec3 wnormal') | ||
|  |         make_attrib.write_norpos(con_depth, vert) | ||
|  |         frag.write_attrib('vec3 n = normalize(wnormal);') | ||
|  |         cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, basecol_only=True, parse_opacity=True) | ||
|  |     elif parse_opacity: | ||
|  |         frag.write('float opacity;') | ||
|  |         frag.write('float ior;') | ||
|  | 
 | ||
|  |     if(con_depth).is_elem('morph'): | ||
|  |         make_morph_target.morph_pos(vert) | ||
|  | 
 | ||
|  |     if con_depth.is_elem('bone'): | ||
|  |         make_skin.skin_pos(vert) | ||
|  | 
 | ||
|  |     if (not is_disp and parse_custom_particle): | ||
|  |         cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity) | ||
|  | 
 | ||
|  |     if con_depth.is_elem('ipos'): | ||
|  |         make_inst.inst_pos(con_depth, vert) | ||
|  | 
 | ||
|  |     rpdat = lnx.utils.get_rp() | ||
|  |     if mat_state.material.lnx_particle_flag and rpdat.lnx_particles == 'On': | ||
|  |         make_particle.write(vert, shadowmap=shadowmap) | ||
|  | 
 | ||
|  |     if is_disp: | ||
|  |         if rpdat.lnx_rp_displacement == 'Vertex': | ||
|  |             frag.ins = vert.outs | ||
|  |             vert.add_uniform('mat3 N', '_normalMatrix') | ||
|  |             vert.write('vec3 wnormal = normalize(N * vec3(nor.xy, pos.w));') | ||
|  |             if(con_depth.is_elem('ipos')): | ||
|  |                 vert.write('wposition = vec4(W * spos).xyz;') | ||
|  |                 if(con_depth.is_elem('irot')): | ||
|  |                     vert.write('wnormal = normalize(N * mirot * vec3(nor.xy, pos.w));') | ||
|  |             if not shadowmap_transparent: | ||
|  |                 cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity) | ||
|  |             if con_depth.is_elem('tex'): | ||
|  |                 vert.add_out('vec2 texCoord') ## vs only, remove out | ||
|  |                 vert.add_uniform('float texUnpack', link='_texUnpack') | ||
|  |                 vert.write_attrib('texCoord = tex * texUnpack;') | ||
|  |             if con_depth.is_elem('tex1'): | ||
|  |                 vert.add_out('vec2 texCoord1') ## vs only, remove out | ||
|  |                 vert.add_uniform('float texUnpack', link='_texUnpack') | ||
|  |                 vert.write_attrib('texCoord1 = tex1 * texUnpack;') | ||
|  |             if con_depth.is_elem('col'): | ||
|  |                 vert.add_out('vec3 vcolor') | ||
|  |                 vert.write_attrib('vcolor = col.rgb;') | ||
|  |             vert.write('wposition += wnormal * disp;') | ||
|  |             if shadowmap: | ||
|  |                 vert.add_uniform('mat4 LVP', '_lightViewProjectionMatrix') | ||
|  |                 vert.write('gl_Position = LVP * vec4(wposition, 1.0);') | ||
|  |             else: | ||
|  |                 vert.add_uniform('mat4 VP', '_viewProjectionMatrix') | ||
|  |                 vert.write('gl_Position = VP * vec4(wposition, 1.0);') | ||
|  | 
 | ||
|  |         else: # Tessellation | ||
|  |             tesc = con_depth.make_tesc() | ||
|  |             tese = con_depth.make_tese() | ||
|  |             tesc.ins = vert.outs | ||
|  |             tese.ins = tesc.outs | ||
|  |             frag.ins = tese.outs | ||
|  | 
 | ||
|  |             vert.add_out('vec3 wnormal') | ||
|  |             vert.add_uniform('mat3 N', '_normalMatrix') | ||
|  |             vert.write('wnormal = normalize(N * vec3(nor.xy, pos.w));') | ||
|  | 
 | ||
|  |             make_tess.tesc_levels(tesc, rpdat.lnx_tess_shadows_inner, rpdat.lnx_tess_shadows_outer) | ||
|  |             make_tess.interpolate(tese, 'wposition', 3) | ||
|  |             make_tess.interpolate(tese, 'wnormal', 3, normalize=True) | ||
|  | 
 | ||
|  |             if not shadowmap_transparent: | ||
|  |                 cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=parse_opacity) | ||
|  | 
 | ||
|  |             if con_depth.is_elem('tex'): | ||
|  |                 vert.add_out('vec2 texCoord') | ||
|  |                 vert.add_uniform('float texUnpack', link='_texUnpack') | ||
|  |                 vert.write('texCoord = tex * texUnpack;') | ||
|  |                 tese.write_pre = True | ||
|  |                 make_tess.interpolate(tese, 'texCoord', 2, declare_out=frag.contains('texCoord')) | ||
|  |                 tese.write_pre = False | ||
|  | 
 | ||
|  |             if con_depth.is_elem('tex1'): | ||
|  |                 vert.add_out('vec2 texCoord1') | ||
|  |                 vert.write('texCoord1 = tex1;') | ||
|  |                 tese.write_pre = True | ||
|  |                 make_tess.interpolate(tese, 'texCoord1', 2, declare_out=frag.contains('texCoord1')) | ||
|  |                 tese.write_pre = False | ||
|  | 
 | ||
|  |             if con_depth.is_elem('col'): | ||
|  |                 vert.add_out('vec3 vcolor') | ||
|  |                 vert.write('vcolor = col.rgb;') | ||
|  |                 tese.write_pre = True | ||
|  |                 make_tess.interpolate(tese, 'vcolor', 3, declare_out=frag.contains('vcolor')) | ||
|  |                 tese.write_pre = False | ||
|  | 
 | ||
|  |             if shadowmap: | ||
|  |                 tese.add_uniform('mat4 LVP', '_lightViewProjectionMatrix') | ||
|  |                 tese.write('wposition += wnormal * disp;') | ||
|  |                 tese.write('gl_Position = LVP * vec4(wposition, 1.0);') | ||
|  |             else: | ||
|  |                 tese.add_uniform('mat4 VP', '_viewProjectionMatrix') | ||
|  |                 tese.write('wposition += wnormal * disp;') | ||
|  |                 tese.write('gl_Position = VP * vec4(wposition, 1.0);') | ||
|  |     # No displacement | ||
|  |     else: | ||
|  |         frag.ins = vert.outs | ||
|  |         billboard = mat_state.material.lnx_billboard | ||
|  |         if shadowmap: | ||
|  |             if billboard == 'spherical': | ||
|  |                 vert.add_uniform('mat4 LWVP', '_lightWorldViewProjectionMatrixSphere') | ||
|  |             elif billboard == 'cylindrical': | ||
|  |                 vert.add_uniform('mat4 LWVP', '_lightWorldViewProjectionMatrixCylinder') | ||
|  |             else: # off | ||
|  |                 vert.add_uniform('mat4 LWVP', '_lightWorldViewProjectionMatrix') | ||
|  |             vert.write('gl_Position = LWVP * spos;') | ||
|  |         else: | ||
|  |             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;') | ||
|  | 
 | ||
|  |         if parse_opacity: | ||
|  |             if not parse_custom_particle and not shadowmap_transparent: | ||
|  |                 cycles.parse(mat_state.nodes, con_depth, vert, frag, geom, tesc, tese, parse_surface=False, parse_opacity=True) | ||
|  | 
 | ||
|  |             if con_depth.is_elem('tex'): | ||
|  |                 vert.add_out('vec2 texCoord') | ||
|  |                 vert.add_uniform('float texUnpack', link='_texUnpack') | ||
|  |                 if mat_state.material.lnx_tilesheet_flag: | ||
|  |                     vert.add_uniform('vec2 tilesheetOffset', '_tilesheetOffset') | ||
|  |                     vert.write('texCoord = tex * texUnpack + tilesheetOffset;') | ||
|  |                 else: | ||
|  |                     vert.write('texCoord = tex * texUnpack;') | ||
|  | 
 | ||
|  |             if con_depth.is_elem('tex1'): | ||
|  |                 vert.add_out('vec2 texCoord1') | ||
|  |                 vert.write('texCoord1 = tex1;') | ||
|  | 
 | ||
|  |             if con_depth.is_elem('col'): | ||
|  |                 vert.add_out('vec3 vcolor') | ||
|  |                 vert.write('vcolor = col.rgb;') | ||
|  | 
 | ||
|  |     if shadowmap_transparent: | ||
|  |         frag.add_out('vec4 fragColor') | ||
|  |         vert.add_out('vec4 wvpposition') | ||
|  |         vert.write('wvpposition = gl_Position;') | ||
|  |         frag.write('float depth = (wvpposition.z / wvpposition.w) * 0.5 + 0.5;') | ||
|  |         frag.write('vec3 color = basecol;') | ||
|  |         frag.write('color *= 1.0 - opacity;') | ||
|  |         frag.write('fragColor = vec4(color, depth);') | ||
|  | 
 | ||
|  |     if parse_opacity and not shadowmap_transparent: | ||
|  |         if mat_state.material.lnx_discard: | ||
|  |             opac = mat_state.material.lnx_discard_opacity_shadows | ||
|  |         else: | ||
|  |             opac = '1.0' | ||
|  |         frag.write('if (opacity < {0}) discard;'.format(opac)) | ||
|  | 
 | ||
|  |     make_finalize.make(con_depth) | ||
|  | 
 | ||
|  |     assets.vs_equal(con_depth, assets.shader_cons['depth_vert']) | ||
|  |     assets.fs_equal(con_depth, assets.shader_cons['depth_frag']) | ||
|  | 
 | ||
|  |     return con_depth |