diff --git a/Penumbra/Import/Textures/CombinedTexture.cs b/Penumbra/Import/Textures/CombinedTexture.cs index 61c3dbd5..8e831806 100644 --- a/Penumbra/Import/Textures/CombinedTexture.cs +++ b/Penumbra/Import/Textures/CombinedTexture.cs @@ -91,11 +91,11 @@ public partial class CombinedTexture : IDisposable var tex = type switch { - TextureSaveType.AsIs => _current.Type is Texture.FileType.Bitmap or Texture.FileType.Png ? CreateUncompressed(s, mipMaps ) : s, + TextureSaveType.AsIs => _current.Type is Texture.FileType.Bitmap or Texture.FileType.Png ? CreateUncompressed( s, mipMaps ) : s, TextureSaveType.Bitmap => CreateUncompressed( s, mipMaps ), - TextureSaveType.BC5 => CreateCompressed( s, mipMaps, false ), - TextureSaveType.BC7 => CreateCompressed( s, mipMaps, true ), - _ => throw new ArgumentOutOfRangeException( nameof( type ), type, null ), + TextureSaveType.BC5 => CreateCompressed( s, mipMaps, false ), + TextureSaveType.BC7 => CreateCompressed( s, mipMaps, true ), + _ => throw new ArgumentOutOfRangeException( nameof( type ), type, null ), }; if( !writeTex ) @@ -117,25 +117,29 @@ public partial class CombinedTexture : IDisposable private static void SaveTex( string path, ScratchImage input ) { - var header = input.Meta.ToTexHeader(); + var header = input.ToTexHeader(); if( header.Format == TexFile.TextureFormat.Unknown ) { throw new Exception( $"Could not save tex file with format {input.Meta.Format}, not convertible to a valid .tex formats." ); } - using var stream = File.OpenWrite( path ); + using var stream = File.Open( path, File.Exists(path) ? FileMode.Truncate : FileMode.CreateNew); using var w = new BinaryWriter( stream ); header.Write( w ); w.Write( input.Pixels ); } private static ScratchImage AddMipMaps( ScratchImage input, bool mipMaps ) - => mipMaps ? input.GenerateMipMaps() : input; + => mipMaps + ? input.GenerateMipMaps( Math.Min( 13, 1 + BitOperations.Log2( ( uint )Math.Max( input.Meta.Width, input.Meta.Height ) ) ) ) + : input; private static ScratchImage CreateUncompressed( ScratchImage input, bool mipMaps ) { - if( input.Meta.Format == DXGIFormat.B8G8R8A8UNorm) - return AddMipMaps(input, mipMaps); + if( input.Meta.Format == DXGIFormat.B8G8R8A8UNorm ) + { + return AddMipMaps( input, mipMaps ); + } if( input.Meta.Format.IsCompressed() ) { @@ -151,8 +155,8 @@ public partial class CombinedTexture : IDisposable private static ScratchImage CreateCompressed( ScratchImage input, bool mipMaps, bool bc7 ) { - var format = bc7 ? DXGIFormat.BC7UNorm : DXGIFormat.BC5UNorm; - if( input.Meta.Format == format) + var format = bc7 ? DXGIFormat.BC7UNorm : DXGIFormat.BC3UNorm; + if( input.Meta.Format == format ) { return input; } diff --git a/Penumbra/Import/Textures/TexFileParser.cs b/Penumbra/Import/Textures/TexFileParser.cs index f38d066e..e9de84a0 100644 --- a/Penumbra/Import/Textures/TexFileParser.cs +++ b/Penumbra/Import/Textures/TexFileParser.cs @@ -61,8 +61,8 @@ public static class TexFileParser return i; } - width = Math.Max( width / 2, 4 ); - height = Math.Max( height / 2, 4 ); + width = Math.Max( width / 2, 1 ); + height = Math.Max( height / 2, 1 ); lastOffset = offset; lastSize = requiredSize; } @@ -103,8 +103,9 @@ public static class TexFileParser } } - public static TexFile.TexHeader ToTexHeader( this TexMeta meta ) + public static TexFile.TexHeader ToTexHeader( this ScratchImage scratch ) { + var meta = scratch.Meta; var ret = new TexFile.TexHeader() { Height = ( ushort )meta.Height, @@ -121,34 +122,33 @@ public static class TexFileParser _ => 0, }, }; - unsafe - { - ret.LodOffset[ 0 ] = 0; - ret.LodOffset[ 1 ] = 1; - ret.LodOffset[ 2 ] = 2; - ret.OffsetToSurface[ 0 ] = 80; - var size = meta.Format.BitsPerPixel() * meta.Width * meta.Height / 8; - for( var i = 1; i < meta.MipLevels; ++i ) - { - ret.OffsetToSurface[ i ] = ( uint )( 80 + size ); - size >>= 2; - if( size == 0 ) - { - ret.MipLevels = ( ushort )i; - break; - } - } - - for( var i = ret.MipLevels; i < 13; ++i ) - { - ret.OffsetToSurface[ i ] = 0; - } - } + ret.FillSurfaceOffsets( scratch ); return ret; } + private static unsafe void FillSurfaceOffsets( this ref TexFile.TexHeader header, ScratchImage scratch ) + { + var idx = 0; + fixed( byte* ptr = scratch.Pixels ) + { + foreach( var image in scratch.Images ) + { + var offset = ( byte* )image.Pixels - ptr; + header.OffsetToSurface[ idx++ ] = ( uint )( 80 + offset ); + } + } + + for( ; idx < 13; ++idx ) + header.OffsetToSurface[ idx ] = 0; + + header.LodOffset[ 0 ] = 0; + header.LodOffset[ 1 ] = 1; + header.LodOffset[ 2 ] = 2; + } + + public static TexMeta ToTexMeta( this TexFile.TexHeader header ) => new() { diff --git a/Penumbra/lib/OtterTex.dll b/Penumbra/lib/OtterTex.dll index 44793977..5e54e1f6 100644 Binary files a/Penumbra/lib/OtterTex.dll and b/Penumbra/lib/OtterTex.dll differ