156 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			156 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | import bpy | ||
|  | 
 | ||
|  | import lnx | ||
|  | import lnx.material.mat_state as mat_state | ||
|  | import lnx.material.make_tess as make_tess | ||
|  | from lnx.material.shader import ShaderContext | ||
|  | 
 | ||
|  | if lnx.is_reload(__name__): | ||
|  |     mat_state = lnx.reload_module(mat_state) | ||
|  |     make_tess = lnx.reload_module(make_tess) | ||
|  |     lnx.material.shader = lnx.reload_module(lnx.material.shader) | ||
|  |     from lnx.material.shader import ShaderContext | ||
|  | else: | ||
|  |     lnx.enable_reload(__name__) | ||
|  | 
 | ||
|  | 
 | ||
|  | def make(con_mesh: ShaderContext): | ||
|  |     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 | ||
|  |     # TODO: enable from cycles.py | ||
|  |     if frag.contains('dotNV') and not frag.contains('float dotNV'): | ||
|  |         frag.write_init('float dotNV = max(dot(n, vVec), 0.0);') | ||
|  | 
 | ||
|  |         # n is not always defined yet (in some shadowmap shaders e.g.) | ||
|  |         if not frag.contains('vec3 n'): | ||
|  |             vert.add_out('vec3 wnormal') | ||
|  |             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') | ||
|  |             vert.write_attrib('wnormal = normalize(N * vec3(nor.xy, pos.w));') | ||
|  |             frag.write_attrib('vec3 n = normalize(wnormal);') | ||
|  | 
 | ||
|  |             # If not yet added, add nor vertex data | ||
|  |             vertex_elems = con_mesh.data['vertex_elements'] | ||
|  |             has_normals = False | ||
|  |             for elem in vertex_elems: | ||
|  |                 if elem['name'] == 'nor': | ||
|  |                     has_normals = True | ||
|  |                     break | ||
|  |             if not has_normals: | ||
|  |                 vertex_elems.append({'name': 'nor', 'data': 'short2norm'}) | ||
|  | 
 | ||
|  |     write_wpos = False | ||
|  |     if frag.contains('vVec') and not frag.contains('vec3 vVec'): | ||
|  |         if tese is not None: | ||
|  |             tese.add_out('vec3 eyeDir') | ||
|  |             tese.add_uniform('vec3 eye', '_cameraPosition') | ||
|  |             tese.write('eyeDir = eye - wposition;') | ||
|  | 
 | ||
|  |         else: | ||
|  |             if not vert.contains('wposition'): | ||
|  |                 write_wpos = True | ||
|  |             vert.add_out('vec3 eyeDir') | ||
|  |             vert.add_uniform('vec3 eye', '_cameraPosition') | ||
|  |             vert.write('eyeDir = eye - wposition;') | ||
|  |         frag.write_attrib('vec3 vVec = normalize(eyeDir);') | ||
|  | 
 | ||
|  |     export_wpos = False | ||
|  |     if frag.contains('wposition') and not frag.contains('vec3 wposition'): | ||
|  |         export_wpos = True | ||
|  |     if tese is not None: | ||
|  |         export_wpos = True | ||
|  |     if vert.contains('wposition'): | ||
|  |         write_wpos = True | ||
|  | 
 | ||
|  |     if export_wpos: | ||
|  |         vert.add_uniform('mat4 W', '_worldMatrix') | ||
|  |         vert.add_out('vec3 wposition') | ||
|  |         vert.write('wposition = vec4(W * spos).xyz;') | ||
|  |     elif write_wpos: | ||
|  |         vert.add_uniform('mat4 W', '_worldMatrix') | ||
|  |         vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;') | ||
|  | 
 | ||
|  |     frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition') | ||
|  |     if frag_mpos: | ||
|  |         vert.add_out('vec3 mposition') | ||
|  |         vert.add_uniform('float posUnpack', link='_posUnpack') | ||
|  |         vert.write_attrib('mposition = spos.xyz * posUnpack;') | ||
|  | 
 | ||
|  |     if tese is not None: | ||
|  |         if frag_mpos: | ||
|  |             make_tess.interpolate(tese, 'mposition', 3, declare_out=True) | ||
|  |         elif tese.contains('mposition') and not tese.contains('vec3 mposition'): | ||
|  |             vert.add_out('vec3 mposition') | ||
|  |             vert.write_pre = True | ||
|  |             vert.add_uniform('float posUnpack', link='_posUnpack') | ||
|  |             vert.write('mposition = spos.xyz * posUnpack;') | ||
|  |             vert.write_pre = False | ||
|  |             make_tess.interpolate(tese, 'mposition', 3, declare_out=False) | ||
|  | 
 | ||
|  |     frag_bpos = (frag.contains('bposition') and not frag.contains('vec3 bposition')) or vert.contains('bposition') | ||
|  |     if frag_bpos: | ||
|  |         vert.add_out('vec3 bposition') | ||
|  |         vert.add_uniform('vec3 dim', link='_dim') | ||
|  |         vert.add_uniform('vec3 hdim', link='_halfDim') | ||
|  |         vert.add_uniform('float posUnpack', link='_posUnpack') | ||
|  |         vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') | ||
|  |         vert.write_attrib('if (dim.z == 0) bposition.z = 0;') | ||
|  |         vert.write_attrib('if (dim.y == 0) bposition.y = 0;') | ||
|  |         vert.write_attrib('if (dim.x == 0) bposition.x = 0;') | ||
|  | 
 | ||
|  |     if tese is not 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.add_uniform('vec3 dim', link='_dim') | ||
|  |             vert.add_uniform('vec3 hdim', link='_halfDim') | ||
|  |             vert.add_uniform('float posUnpack', link='_posUnpack') | ||
|  |             vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') | ||
|  |             make_tess.interpolate(tese, 'bposition', 3, declare_out=False) | ||
|  | 
 | ||
|  |     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 | ||
|  |         con_mesh.add_elem('tex', 'short2norm') | ||
|  |         con_mesh.add_elem('tang', 'short4norm') | ||
|  |         vert.add_out('vec3 wtangent') | ||
|  |         vert.write_pre = True | ||
|  |         vert.write('wtangent = normalize(N * tang.xyz);') | ||
|  |         vert.write_pre = False | ||
|  | 
 | ||
|  |     if tese is not 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.xyz);') | ||
|  |             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);') | ||
|  | 
 | ||
|  |     if frag.contains('nAttr'): | ||
|  |         vert.add_out('vec3 nAttr') | ||
|  |         vert.write_attrib('nAttr = vec3(nor.xy, pos.w);') | ||
|  | 
 | ||
|  |     wrd = bpy.data.worlds['Lnx'] | ||
|  |     if '_Legacy' in wrd.world_defs: | ||
|  |         frag.replace('sampler2DShadow', 'sampler2D') | ||
|  |         frag.replace('samplerCubeShadow', 'samplerCube') |