Skip to content

Commit

Permalink
final commit (hopefully)
Browse files Browse the repository at this point in the history
Invert the logic, account for multi texture, hopefully improve code, toggle to skip auto pick, better descriptions (i think)
  • Loading branch information
Lilaa3 committed Apr 6, 2024
1 parent 5bee1cd commit 31a7a54
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 65 deletions.
16 changes: 11 additions & 5 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,9 @@ def draw(self, context):
prop_split(col, context.scene, "gameEditorMode", "Game")
col.prop(context.scene, "exportHiddenGeometry")
col.prop(context.scene, "fullTraceback")
col.prop(context.scene.fast64.settings, "prefer_ci_over_rgba")
col.separator()
col.prop(context.scene.fast64.settings, "auto_pick_texture_format")
col.prop(context.scene.fast64.settings, "prefer_rgba_over_ci")
prop_split(col, context.scene.fast64.settings, "anim_range_choice", "Anim Range")


Expand Down Expand Up @@ -268,11 +270,15 @@ class Fast64Settings_Properties(bpy.types.PropertyGroup):
],
default="intersect_action_and_scene",
)
prefer_ci_over_rgba: bpy.props.BoolProperty(
name="Prefer CI Over RGBA",
description="When enabled, fast64 will default colored textures that fit ci requirements to ci instead of rgba even if the texture fits as an rgba16 for the sake of performance",
auto_pick_texture_format: bpy.props.BoolProperty(
name="Auto Pick Texture Format",
description="When enabled, fast64 will try to pick the best texture format whenever a texture is selected.",
default=True,
)
prefer_rgba_over_ci: bpy.props.BoolProperty(
name="Prefer RGBA Over CI",
description="When enabled, fast64 will default colored textures's format to RGBA even if they fit CI requirements, with the exception of textures that would not fit into TMEM otherwise",
)


class Fast64_Properties(bpy.types.PropertyGroup):
"""
Expand Down
136 changes: 76 additions & 60 deletions fast64_internal/f3d/f3d_material.py
Original file line number Diff line number Diff line change
Expand Up @@ -1898,23 +1898,90 @@ def update_tex_values_index(self: Material, *, texProperty: "TextureProperty", t
tex_I_node.node_tree = desired_node


def get_color_info_from_tex(tex: bpy.types.Image):
is_greyscale, has_alpha_4_bit, has_alpha_1_bit = True, False, False
rgba_colors: set[int] = set()

pixels, channel_count = tex.pixels, tex.channels

for x in range(tex.size[0]):
for y in range(tex.size[1]): # N64 is -Y, Blender is +Y, in this context this doesn´t matter
pixel_color = [1, 1, 1, 1]
for field in range(channel_count):
pixel_color[field] = pixels[(y * tex.size[0] + x) * channel_count + field]
rgba_colors.add(getRGBA16Tuple(pixel_color))

if not (pixel_color[0] == pixel_color[1] and pixel_color[1] == pixel_color[2]):
is_greyscale = False

if pixel_color[3] < 0.9375:
has_alpha_4_bit = True
if pixel_color[3] < 0.5:
has_alpha_1_bit = True

return is_greyscale, has_alpha_1_bit, has_alpha_4_bit, rgba_colors


def get_optimal_format(tex: bpy.types.Image | None, prefer_rgba_over_ci: bool):
if not tex:
return "RGBA16"

n_size = tex.size[0] * tex.size[1]
if n_size > 8192: # Image is too big
return "RGBA16"

is_greyscale, has_alpha_1_bit, has_alpha_4_bit, rgba_colors = get_color_info_from_tex(tex)

if is_greyscale:
if n_size > 4096:
if has_alpha_1_bit:
return "IA4"
return "I4"

if has_alpha_4_bit:
return "IA8"

return "I8"
else:
if len(rgba_colors) <= 16 and (not prefer_rgba_over_ci or n_size > 2048):
return "CI4"
if not prefer_rgba_over_ci and len(rgba_colors) <= 256:
return "CI8"

return "RGBA16"


def update_tex_values_and_formats(self, context):
with F3DMaterial_UpdateLock(get_material_from_context(context)) as material:
if not material:
return

f3d_mat = context.material.f3d_mat
settings_props = context.scene.fast64.settings
if not settings_props.auto_pick_texture_format:
update_tex_values_manual(material, context)
return

f3d_mat: F3DMaterialProperty = material.f3d_mat
useDict = all_combiner_uses(f3d_mat)
isMultiTexture = (
useDict["Texture 0"]
and f3d_mat.tex0.tex is not None
and useDict["Texture 1"]
and f3d_mat.tex1.tex is not None
tex0_props = f3d_mat.tex0
tex1_props = f3d_mat.tex1

tex0, tex1 = tex0_props.tex if useDict["Texture 0"] else None, (
tex1_props.tex if useDict["Texture 1"] else None
)
if self.tex is not None:
self.tex_format = getOptimalFormat(self.tex, self.tex_format, isMultiTexture)

update_tex_values_manual(context.material, context)
if tex0:
tex0_props.tex_format = get_optimal_format(tex0, settings_props.prefer_rgba_over_ci)
if tex1:
tex1_props.tex_format = get_optimal_format(tex1, settings_props.prefer_rgba_over_ci)

if tex0 and tex1:
if tex0_props.tex_format.startswith("CI") and not tex1_props.tex_format.startswith("CI"):
tex0_props.tex_format = "RGBA16"
elif tex1_props.tex_format.startswith("CI") and not tex0_props.tex_format.startswith("CI"):
tex1_props.tex_format = "RGBA16"

update_tex_values_manual(material, context)


def update_tex_values(self, context):
Expand Down Expand Up @@ -3367,57 +3434,6 @@ def execute(self, context):
return {"FINISHED"}


def getOptimalFormat(tex, curFormat, isMultitexture):
texFormat = "RGBA16"
if isMultitexture:
return curFormat
if tex.size[0] * tex.size[1] > 8192: # Image too big
return curFormat

isGreyscale = True
hasAlpha4bit = False
hasAlpha1bit = False
pixelValues = set()

# N64 is -Y, Blender is +Y
pixels = tex.pixels[:]
for j in reversed(range(tex.size[1])):
for i in range(tex.size[0]):
color = [1, 1, 1, 1]
for field in range(tex.channels):
color[field] = pixels[(j * tex.size[0] + i) * tex.channels + field]
if not (color[0] == color[1] and color[1] == color[2]):
isGreyscale = False
if color[3] < 0.9375:
hasAlpha4bit = True
if color[3] < 0.5:
hasAlpha1bit = True
pixelValues.add(getRGBA16Tuple(color))

n_size = tex.size[0] * tex.size[1]
if isGreyscale:
if n_size > 4096:
if not hasAlpha1bit:
texFormat = "I4"
else:
texFormat = "IA4"
else:
if not hasAlpha4bit:
texFormat = "I8"
else:
texFormat = "IA8"
else:
prefer_ci_over_rgba = bpy.context.scene.fast64.settings.prefer_ci_over_rgba
if (prefer_ci_over_rgba and len(pixelValues) <= 16) or (len(pixelValues) <= 16 and n_size > 2048):
texFormat = "CI4"
elif prefer_ci_over_rgba and len(pixelValues) <= 256 and n_size <= 2048:
texFormat = "CI8"
else:
texFormat = "RGBA16"

return texFormat


def getCurrentPresetDir():
return "f3d/" + bpy.context.scene.gameEditorMode.lower()

Expand Down

0 comments on commit 31a7a54

Please sign in to comment.