Merge remote-tracking branch 'Exter-N/better-tex'

This commit is contained in:
Ottermandias 2025-03-14 00:16:33 +01:00
commit 83574dfeb1
6 changed files with 58 additions and 19 deletions

View file

@ -6,7 +6,10 @@ public partial class CombinedTexture : IDisposable
{
AsIs,
Bitmap,
BC1,
BC3,
BC4,
BC5,
BC7,
}

View file

@ -1,3 +1,4 @@
using Dalamud.Interface;
using Dalamud.Interface.Textures;
using Dalamud.Interface.Textures.TextureWraps;
using Dalamud.Plugin.Services;
@ -6,15 +7,17 @@ using OtterGui.Log;
using OtterGui.Services;
using OtterGui.Tasks;
using OtterTex;
using SharpDX.Direct3D11;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.PixelFormats;
using DxgiDevice = SharpDX.DXGI.Device;
using Image = SixLabors.ImageSharp.Image;
namespace Penumbra.Import.Textures;
public sealed class TextureManager(IDataManager gameData, Logger logger, ITextureProvider textureProvider)
public sealed class TextureManager(IDataManager gameData, Logger logger, ITextureProvider textureProvider, IUiBuilder uiBuilder)
: SingleTaskQueue, IDisposable, IService
{
private readonly Logger _logger = logger;
@ -201,8 +204,11 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
rgba, width, height),
CombinedTexture.TextureSaveType.AsIs when imageTypeBehaviour is TextureType.Dds => AddMipMaps(image.AsDds!, _mipMaps),
CombinedTexture.TextureSaveType.Bitmap => ConvertToRgbaDds(image, _mipMaps, cancel, rgba, width, height),
CombinedTexture.TextureSaveType.BC3 => ConvertToCompressedDds(image, _mipMaps, false, cancel, rgba, width, height),
CombinedTexture.TextureSaveType.BC7 => ConvertToCompressedDds(image, _mipMaps, true, cancel, rgba, width, height),
CombinedTexture.TextureSaveType.BC1 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC1UNorm, cancel, rgba, width, height),
CombinedTexture.TextureSaveType.BC3 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC3UNorm, cancel, rgba, width, height),
CombinedTexture.TextureSaveType.BC4 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC4UNorm, cancel, rgba, width, height),
CombinedTexture.TextureSaveType.BC5 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC5UNorm, cancel, rgba, width, height),
CombinedTexture.TextureSaveType.BC7 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC7UNorm, cancel, rgba, width, height),
_ => throw new Exception("Wrong save type."),
};
@ -320,7 +326,7 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
}
/// <summary> Convert an existing image to a block compressed .dds. Does not create a deep copy of an existing dds of the correct format and just returns the existing one. </summary>
public static BaseImage ConvertToCompressedDds(BaseImage input, bool mipMaps, bool bc7, CancellationToken cancel, byte[]? rgba = null,
public BaseImage ConvertToCompressedDds(BaseImage input, bool mipMaps, DXGIFormat format, CancellationToken cancel, byte[]? rgba = null,
int width = 0, int height = 0)
{
switch (input.Type.ReduceToBehaviour())
@ -331,12 +337,12 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
cancel.ThrowIfCancellationRequested();
var dds = ConvertToDds(rgba, width, height).AsDds!;
cancel.ThrowIfCancellationRequested();
return CreateCompressed(dds, mipMaps, bc7, cancel);
return CreateCompressed(dds, mipMaps, format, cancel);
}
case TextureType.Dds:
{
var scratch = input.AsDds!;
return CreateCompressed(scratch, mipMaps, bc7, cancel);
return CreateCompressed(scratch, mipMaps, format, cancel);
}
default: return new BaseImage();
}
@ -384,9 +390,8 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
}
/// <summary> Create a BC3 or BC7 block-compressed .dds from the input (optionally with mipmaps). Returns input (+ mipmaps) if it is already the correct format. </summary>
public static ScratchImage CreateCompressed(ScratchImage input, bool mipMaps, bool bc7, CancellationToken cancel)
public ScratchImage CreateCompressed(ScratchImage input, bool mipMaps, DXGIFormat format, CancellationToken cancel)
{
var format = bc7 ? DXGIFormat.BC7UNorm : DXGIFormat.BC3UNorm;
if (input.Meta.Format == format)
return input;
@ -398,6 +403,16 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
input = AddMipMaps(input, mipMaps);
cancel.ThrowIfCancellationRequested();
// See https://github.com/microsoft/DirectXTex/wiki/Compress#parameters for the format condition.
if (format is DXGIFormat.BC6HUF16 or DXGIFormat.BC6HSF16 or DXGIFormat.BC7UNorm or DXGIFormat.BC7UNormSRGB)
{
var device = uiBuilder.Device;
var dxgiDevice = device.QueryInterface<DxgiDevice>();
using var deviceClone = new Device(dxgiDevice.Adapter, device.CreationFlags, device.FeatureLevel);
return input.Compress(deviceClone.NativePointer, format, CompressFlags.Parallel);
}
return input.Compress(format, CompressFlags.BC7Quick | CompressFlags.Parallel);
}

View file

@ -80,6 +80,10 @@
<HintPath>$(DalamudLibPath)SharpDX.Direct3D11.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SharpDX.DXGI">
<HintPath>$(DalamudLibPath)SharpDX.DXGI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="OtterTex.dll">
<HintPath>lib\OtterTex.dll</HintPath>
</Reference>

View file

@ -138,7 +138,7 @@ public partial class MtrlTab
foreach (var constant in Mtrl.ShaderPackage.Constants)
{
var values = Mtrl.GetConstantValue<byte>(constant);
if (values != null)
if (values != [])
SetMaterialParameter(constant.Id, 0, values);
}

View file

@ -25,11 +25,17 @@ public partial class ModEditWindow
{
("As Is", "Save the current texture with its own format without additional conversion or compression, if possible."),
("RGBA (Uncompressed)",
"Save the current texture as an uncompressed BGRA bitmap. This requires the most space but technically offers the best quality."),
("BC3 (Simple Compression)",
"Save the current texture compressed via BC3/DXT5 compression. This offers a 4:1 compression ratio and is quick with acceptable quality."),
("BC7 (Complex Compression)",
"Save the current texture compressed via BC7 compression. This offers a 4:1 compression ratio and has almost indistinguishable quality, but may take a while."),
"Save the current texture as an uncompressed BGRA bitmap.\nThis requires the most space but technically offers the best quality."),
("BC1 (Simple Compression for Opaque RGB)",
"Save the current texture compressed via BC1/DXT1 compression.\nThis offers a 8:1 compression ratio and is quick with acceptable quality, but only supports RGB, without Alpha.\n\nCan be used for diffuse maps and equipment textures to save extra space."),
("BC3 (Simple Compression for RGBA)",
"Save the current texture compressed via BC3/DXT5 compression.\nThis offers a 4:1 compression ratio and is quick with acceptable quality, and fully supports RGBA.\n\nGeneric format that can be used for most textures."),
("BC4 (Simple Compression for Opaque Grayscale)",
"Save the current texture compressed via BC4 compression.\nThis offers a 8:1 compression ratio and has almost indistinguishable quality, but only supports Grayscale, without Alpha.\n\nCan be used for face paints and legacy marks."),
("BC5 (Simple Compression for Opaque RG)",
"Save the current texture compressed via BC5 compression.\nThis offers a 4:1 compression ratio and has almost indistinguishable quality, but only supports RG, without B or Alpha.\n\nRecommended for index maps, unrecommended for normal maps."),
("BC7 (Complex Compression for RGBA)",
"Save the current texture compressed via BC7 compression.\nThis offers a 4:1 compression ratio and has almost indistinguishable quality, but may take a while.\n\nGeneric format that can be used for most textures."),
};
private void DrawInputChild(string label, Texture tex, Vector2 size, Vector2 imageSize)
@ -134,7 +140,7 @@ public partial class ModEditWindow
tt, !isActive || !canSaveInPlace || _center.IsLeftCopy && _currentSaveAs == (int)CombinedTexture.TextureSaveType.AsIs))
{
_center.SaveAs(_left.Type, _textures, _left.Path, (CombinedTexture.TextureSaveType)_currentSaveAs, _addMipMaps);
InvokeChange(Mod, _left.Path);
AddChangeTask(_left.Path);
AddReloadTask(_left.Path, false);
}
@ -159,7 +165,7 @@ public partial class ModEditWindow
!canConvertInPlace || _left.Format is DXGIFormat.BC7Typeless or DXGIFormat.BC7UNorm or DXGIFormat.BC7UNormSRGB))
{
_center.SaveAsTex(_textures, _left.Path, CombinedTexture.TextureSaveType.BC7, _left.MipMaps > 1);
InvokeChange(Mod, _left.Path);
AddChangeTask(_left.Path);
AddReloadTask(_left.Path, false);
}
@ -169,7 +175,7 @@ public partial class ModEditWindow
!canConvertInPlace || _left.Format is DXGIFormat.BC3Typeless or DXGIFormat.BC3UNorm or DXGIFormat.BC3UNormSRGB))
{
_center.SaveAsTex(_textures, _left.Path, CombinedTexture.TextureSaveType.BC3, _left.MipMaps > 1);
InvokeChange(Mod, _left.Path);
AddChangeTask(_left.Path);
AddReloadTask(_left.Path, false);
}
@ -180,7 +186,7 @@ public partial class ModEditWindow
|| _left.Format is DXGIFormat.B8G8R8A8UNorm or DXGIFormat.B8G8R8A8Typeless or DXGIFormat.B8G8R8A8UNormSRGB))
{
_center.SaveAsTex(_textures, _left.Path, CombinedTexture.TextureSaveType.Bitmap, _left.MipMaps > 1);
InvokeChange(Mod, _left.Path);
AddChangeTask(_left.Path);
AddReloadTask(_left.Path, false);
}
}
@ -235,7 +241,7 @@ public partial class ModEditWindow
if (a)
{
_center.SaveAs(null, _textures, b, (CombinedTexture.TextureSaveType)_currentSaveAs, _addMipMaps);
InvokeChange(Mod, b);
AddChangeTask(b);
if (b == _left.Path)
AddReloadTask(_left.Path, false);
else if (b == _right.Path)
@ -245,6 +251,17 @@ public partial class ModEditWindow
_forceTextureStartPath = false;
}
private void AddChangeTask(string path)
{
_center.SaveTask.ContinueWith(t =>
{
if (!t.IsCompletedSuccessfully)
return;
_framework.RunOnFrameworkThread(() => InvokeChange(Mod, path));
}, TaskScheduler.Default);
}
private void AddReloadTask(string path, bool right)
{
_center.SaveTask.ContinueWith(t =>

Binary file not shown.