forked from LeenkxTeam/LNXSDK
Fix thinWall and passes
This commit is contained in:
@ -908,7 +908,9 @@ class RenderPath {
|
||||
#end
|
||||
|
||||
Data.getShader(shaderPath[0], shaderPath[1], function(res: ShaderData) {
|
||||
cc.context = res.getContext(shaderPath[2]);
|
||||
if (res != null) {
|
||||
cc.context = res.getContext(shaderPath[2]);
|
||||
}
|
||||
loading--;
|
||||
});
|
||||
}
|
||||
|
||||
@ -55,6 +55,7 @@ class ShaderData {
|
||||
if (raw == null) {
|
||||
trace('Shader data "$name" not found!');
|
||||
done(null);
|
||||
return;
|
||||
}
|
||||
new ShaderData(raw, done, overrideContext);
|
||||
});
|
||||
|
||||
@ -384,7 +384,8 @@ def export_data_impl(fp, sdk_path):
|
||||
os.utime(g, None)
|
||||
|
||||
# Write referenced shader passes
|
||||
if not os.path.isfile(build_dir + '/compiled/Shaders/shader_datas.lnx') or state.last_world_defs != wrd.world_defs:
|
||||
current_passes = tuple(sorted(assets.shader_passes))
|
||||
if not os.path.isfile(build_dir + '/compiled/Shaders/shader_datas.lnx') or state.last_world_defs != wrd.world_defs or getattr(state, 'last_shader_passes', None) != current_passes:
|
||||
res = {'shader_datas': []}
|
||||
|
||||
for ref in assets.shader_passes:
|
||||
@ -431,6 +432,7 @@ def export_data_impl(fp, sdk_path):
|
||||
if not os.path.exists(target):
|
||||
shutil.copy(file, target)
|
||||
state.last_world_defs = wrd.world_defs
|
||||
state.last_shader_passes = current_passes
|
||||
|
||||
# Reset path
|
||||
os.chdir(fp)
|
||||
|
||||
@ -236,6 +236,8 @@ def build():
|
||||
|
||||
if rpdat.rp_renderer == 'Deferred':
|
||||
assets.add_shader_pass('copy_pass')
|
||||
elif rpdat.rp_renderer == 'Forward' and not rpdat.rp_compositornodes:
|
||||
assets.add_shader_pass('copy_pass')
|
||||
|
||||
assets.add_shader_pass('blend_pass')
|
||||
assets.add_shader_pass('add_pass')
|
||||
@ -243,9 +245,6 @@ def build():
|
||||
if rpdat.rp_render_to_texture:
|
||||
assets.add_khafile_def('rp_render_to_texture')
|
||||
|
||||
if rpdat.rp_renderer == 'Forward' and not rpdat.rp_compositornodes:
|
||||
assets.add_shader_pass('copy_pass')
|
||||
|
||||
if rpdat.rp_compositornodes:
|
||||
assets.add_khafile_def('rp_compositornodes')
|
||||
compo_depth = False
|
||||
@ -341,6 +340,8 @@ def build():
|
||||
wrd.world_defs += '_FSR1_{0}'.format(rpdat.rp_fsr1)
|
||||
assets.add_shader_pass('fsr1_easu_pass')
|
||||
assets.add_shader_pass('fsr1_rcas_pass')
|
||||
if rpdat.rp_renderer == 'Forward':
|
||||
assets.add_shader_pass('copy_pass')
|
||||
|
||||
if rpdat.rp_ssao:
|
||||
assets.add_khafile_def('rp_ssao')
|
||||
|
||||
@ -67,19 +67,19 @@ def resize_texture_if_needed(image: bpy.types.Image, filepath: str, max_size: in
|
||||
"""
|
||||
if max_size <= 0:
|
||||
return filepath
|
||||
|
||||
|
||||
if image.size[0] <= max_size and image.size[1] <= max_size:
|
||||
return filepath
|
||||
|
||||
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
texture_quality = wrd.lnx_texture_quality
|
||||
|
||||
|
||||
cache_key = (filepath, max_size, texture_quality, os.path.getmtime(filepath) if os.path.exists(filepath) else 0)
|
||||
if cache_key in texture_resize_cache:
|
||||
cached_path = texture_resize_cache[cache_key]
|
||||
if os.path.exists(cached_path):
|
||||
return cached_path
|
||||
|
||||
|
||||
width, height = image.size[0], image.size[1]
|
||||
if width > height:
|
||||
new_width = max_size
|
||||
@ -87,55 +87,55 @@ def resize_texture_if_needed(image: bpy.types.Image, filepath: str, max_size: in
|
||||
else:
|
||||
new_height = max_size
|
||||
new_width = int((width / height) * max_size)
|
||||
|
||||
|
||||
build_dir = lnx.utils.get_fp_build()
|
||||
resized_dir = os.path.join(build_dir, 'compiled', 'Assets', 'unpacked')
|
||||
os.makedirs(resized_dir, exist_ok=True)
|
||||
|
||||
|
||||
basename = os.path.basename(filepath)
|
||||
name, ext = os.path.splitext(basename)
|
||||
quality_suffix = f"q{int(texture_quality * 100)}"
|
||||
resized_path = os.path.join(resized_dir, f"{name}_{max_size}px_{quality_suffix}{ext}")
|
||||
|
||||
|
||||
if os.path.exists(resized_path):
|
||||
src_mtime = os.path.getmtime(filepath)
|
||||
dst_mtime = os.path.getmtime(resized_path)
|
||||
if dst_mtime >= src_mtime:
|
||||
texture_resize_cache[cache_key] = resized_path
|
||||
return resized_path
|
||||
|
||||
|
||||
try:
|
||||
ffmpeg_path = lnx.utils.get_ffmpeg_path()
|
||||
|
||||
|
||||
if ffmpeg_path is None or ffmpeg_path == '':
|
||||
print(f"[Texture Optimizer] WARNING: FFmpeg not found. Please set FFmpeg path in addon preferences.")
|
||||
print(f"[Texture Optimizer] Skipping resize for: {basename}")
|
||||
return filepath
|
||||
|
||||
|
||||
file_ext = os.path.splitext(filepath)[1].lower().lstrip('.')
|
||||
|
||||
|
||||
cmd = [
|
||||
ffmpeg_path,
|
||||
'-y',
|
||||
'-y',
|
||||
'-i', filepath,
|
||||
'-vf', f'scale={new_width}:{new_height}:flags=lanczos',
|
||||
]
|
||||
|
||||
|
||||
if file_ext in ('png', 'tga', 'bmp'):
|
||||
compression_level = round((1.0 - texture_quality) * 9)
|
||||
cmd.extend(['-compression_level', str(compression_level)])
|
||||
else:
|
||||
qscale = round(2 + (1.0 - texture_quality) * 29)
|
||||
cmd.extend(['-q:v', str(qscale)])
|
||||
|
||||
|
||||
cmd.append(resized_path)
|
||||
|
||||
|
||||
startupinfo = None
|
||||
if os.name == 'nt':
|
||||
if os.name == 'nt':
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
startupinfo.wShowWindow = subprocess.SW_HIDE
|
||||
|
||||
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
@ -143,7 +143,7 @@ def resize_texture_if_needed(image: bpy.types.Image, filepath: str, max_size: in
|
||||
startupinfo=startupinfo,
|
||||
timeout=60
|
||||
)
|
||||
|
||||
|
||||
if result.returncode == 0 and os.path.exists(resized_path):
|
||||
print(f"[Texture Optimizer] Resized: {basename} {width}x{height} -> {new_width}x{new_height}")
|
||||
texture_resize_cache[cache_key] = resized_path
|
||||
@ -152,7 +152,7 @@ def resize_texture_if_needed(image: bpy.types.Image, filepath: str, max_size: in
|
||||
error_msg = result.stderr.decode('utf-8', errors='ignore') if result.stderr else 'Unknown error'
|
||||
print(f"[Texture Optimizer] WARNING: FFmpeg failed to resize {basename}: {error_msg}")
|
||||
return filepath
|
||||
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
print(f"[Texture Optimizer] WARNING: FFmpeg timeout while resizing {basename}")
|
||||
return filepath
|
||||
@ -641,7 +641,7 @@ def parse_normal_map_color_input(inp, strength_input=None, space='TANGENT'):
|
||||
|
||||
state.normal_parsed = True
|
||||
frag.write_normal += 1
|
||||
|
||||
|
||||
color_val = parse_vector_input(inp)
|
||||
strength = parse_value_input(strength_input) if strength_input is not None else '1.0'
|
||||
|
||||
@ -660,7 +660,7 @@ def parse_normal_map_color_input(inp, strength_input=None, space='TANGENT'):
|
||||
frag.write(f'texn.xy *= {strength};')
|
||||
frag.write('n = normalize(TBN * texn);')
|
||||
state.con.add_elem('tang', 'short4norm')
|
||||
|
||||
|
||||
elif space in ['OBJECT', 'BLENDER_OBJECT']:
|
||||
frag.add_uniform('mat3 N', '_normalMatrix')
|
||||
frag.write(f'vec3 objn = ({color_val}) * 2.0 - 1.0;')
|
||||
@ -693,6 +693,8 @@ def parse_value_input(inp: bpy.types.NodeSocket) -> floatstr:
|
||||
return rgb_to_bw(res_var)
|
||||
elif socket_type in ('VALUE', 'INT'):
|
||||
return res_var
|
||||
elif socket_type == 'BOOLEAN':
|
||||
return f'({res_var} ? 1.0 : 0.0)'
|
||||
else:
|
||||
log.warn(f'Node tree "{tree_name()}": socket "{link.from_socket.name}" of node "{link.from_node.name}" cannot be connected to a scalar value socket')
|
||||
return '0.0'
|
||||
@ -990,6 +992,12 @@ def dfdy_fine(val: str) -> str:
|
||||
|
||||
|
||||
def to_vec1(v):
|
||||
if isinstance(v, bool):
|
||||
return '1.0' if v else '0.0'
|
||||
if v == 'False':
|
||||
return '0.0'
|
||||
if v == 'True':
|
||||
return '1.0'
|
||||
return str(v)
|
||||
|
||||
|
||||
@ -1177,7 +1185,7 @@ def make_texture(
|
||||
if filepath != original_filepath:
|
||||
resized_filename = lnx.utils.extract_filename(filepath)
|
||||
tex['file'] = lnx.utils.safestr(resized_filename)
|
||||
|
||||
|
||||
# Link image path to assets
|
||||
# TODO: Khamake converts .PNG to .jpg? Convert ext to lowercase on windows
|
||||
if lnx.utils.get_os() == 'win':
|
||||
|
||||
@ -149,6 +149,10 @@ def parse(material: Material, mat_data, mat_users: Dict[Material, List[Object]],
|
||||
if val_str is None:
|
||||
return None
|
||||
val_str = str(val_str).strip()
|
||||
if val_str in ('True', 'true'):
|
||||
return 1.0
|
||||
if val_str in ('False', 'false'):
|
||||
return 0.0
|
||||
try:
|
||||
return float(val_str)
|
||||
except (ValueError, TypeError):
|
||||
@ -296,7 +300,7 @@ def parse(material: Material, mat_data, mat_users: Dict[Material, List[Object]],
|
||||
|
||||
elif rp == 'translucent' or rp == 'refraction':
|
||||
c['bind_constants'].append({'name': 'receiveShadow', 'boolValue': material.lnx_receive_shadow})
|
||||
|
||||
|
||||
elif rp == 'shadowmap':
|
||||
if wrd.lnx_batch_materials:
|
||||
if len(c['bind_textures']) > 0:
|
||||
|
||||
@ -99,12 +99,12 @@ class ShaderContext:
|
||||
def sort_vs(self):
|
||||
vs = []
|
||||
ar = ['pos', 'nor', 'tex', 'tex1', 'morph', 'col', 'tang', 'bone', 'weight', 'ipos', 'irot', 'iscl']
|
||||
|
||||
|
||||
if 'vertex_elements' in self.data:
|
||||
for elem in self.data['vertex_elements']:
|
||||
if elem['name'] not in ar:
|
||||
ar.append(elem['name'])
|
||||
|
||||
|
||||
for ename in ar:
|
||||
elem = self.get_elem(ename)
|
||||
if elem != None:
|
||||
@ -137,6 +137,15 @@ class ShaderContext:
|
||||
if default_value is not None:
|
||||
if ctype == 'float':
|
||||
c['floatValue'] = default_value
|
||||
if isinstance(default_value, bool):
|
||||
c['floatValue'] = 1.0 if default_value else 0.0
|
||||
elif isinstance(default_value, (int, float)):
|
||||
c['floatValue'] = float(default_value)
|
||||
else:
|
||||
try:
|
||||
c['floatValue'] = float(default_value)
|
||||
except (ValueError, TypeError):
|
||||
c['floatValue'] = default_value
|
||||
if ctype == 'vec3':
|
||||
c['vec3Value'] = default_value
|
||||
if is_lnx_mat_param is not None:
|
||||
@ -418,11 +427,11 @@ class Shader:
|
||||
def validate(self):
|
||||
import re
|
||||
issues = []
|
||||
|
||||
|
||||
# Check for duplicate variable declarations in main_attribs
|
||||
var_pattern = re.compile(r'\b(vec[234]|float|int|mat[234])\s+(\w+)\s*[;=]')
|
||||
declared_vars = {}
|
||||
|
||||
|
||||
for line in self.main_attribs.split('\n'):
|
||||
match = var_pattern.search(line)
|
||||
if match:
|
||||
@ -431,7 +440,7 @@ class Shader:
|
||||
issues.append(f"Duplicate variable declaration: '{var_name}' (type: {var_type})")
|
||||
else:
|
||||
declared_vars[var_name] = var_type
|
||||
|
||||
|
||||
return issues
|
||||
|
||||
def get(self):
|
||||
|
||||
Reference in New Issue
Block a user