forked from LeenkxTeam/LNXSDK
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')
|