Update leenkx/blender/lnx/material/make_finalize.py

This commit is contained in:
2025-05-21 22:39:52 +00:00
parent dab9a38424
commit 210d5ea532

View File

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