NotAdam / Lumina

A simple, performant and extensible framework for interacting with FFXIV game data
Do What The F*ck You Want To Public License
101 stars 52 forks source link

Add DDS support #68

Closed Soreepeong closed 1 year ago

Soreepeong commented 1 year ago

Tested with the following code. WTV recognizes output DDS files.

Code ```cs using System; using System.Runtime.CompilerServices; using Lumina.Data.Files; using Lumina.Data.Parsing.Tex.DirectDrawSurface; namespace Lumina.Example { class Program { static void Main( string[] args ) { var gameData = new GameData( args[ 0 ] ); #if true var tex = gameData.GetFileFromDisk< TexFile >( /* bgcommon/texture/~A6C45FC3 */ @"test.tex" )!; var basename = "test"; { #else foreach( var path in new[] { "bg/ffxiv/fst_f1/cnt/f1c1/level/envl/evl6364405.tex", "common/font/font1.tex", "common/graphics/texture/-caustics.tex", "common/graphics/texture/-fresnel.tex", "common/graphics/texture/-mogu_anime_en.tex", "ui/loadingimage/-nowloading_base22_hr1.tex", "ui/loadingimage/-nowloading_base23_hr1.tex", "ui/loadingimage/-nowloading_base25_hr1.tex", "ui/icon/000000/000013_hr1.tex", } ) { var tex = gameData.GetFile< TexFile >( path )!; var basename = Path.GetFileNameWithoutExtension( path ); #endif var dds = tex.ToDdsFile( true ); dds.WriteToFile( $"Z:/test/{basename}.dds" ); for( var i = 0; i < tex.TextureBuffer.Depth; i++ ) { for( var j = 0; j < tex.TextureBuffer.MipmapAllocations.Length; j++ ) { var buf = tex.TextureBuffer.Filter( j, i, TexFile.TextureFormat.B8G8R8A8 ); var dds2 = new DdsFile( new() { Size = Unsafe.SizeOf< DdsHeader >(), Flags = DdsHeaderFlags.Caps | DdsHeaderFlags.PixelFormat | DdsHeaderFlags.Width | DdsHeaderFlags.Height, Width = buf.Width, Height = buf.Height, Depth = 0, MipMapCount = 0, PixelFormat = new() { Size = Unsafe.SizeOf< DdsPixelFormat >(), Flags = DdsPixelFormatFlags.Rgb | DdsPixelFormatFlags.AlphaPixels, RgbBitCount = 32, RBitMask = 0xFF0000, GBitMask = 0xFF00, BBitMask = 0xFF, ABitMask = 0xFF000000, }, Caps = DdsCaps1.Texture, Caps2 = 0, }, buf.RawData, Array.Empty< byte >() ); dds2.Header.Pitch = dds2.Pitch( 0 ); dds2.WriteToFile( $"Z:/test/{basename}.conv[{i},{j}].dds" ); } } foreach( var slice in dds.EnumerateSlices() ) { var span = dds.SliceSpan( slice.Image, slice.Face, slice.Mipmap, slice.Slice ); var dds2 = new DdsFile( new() { Size = Unsafe.SizeOf< DdsHeader >(), Flags = DdsHeaderFlags.Caps | DdsHeaderFlags.PixelFormat | DdsHeaderFlags.Width | DdsHeaderFlags.Height, Width = slice.Width, Height = slice.Height, Depth = 0, MipMapCount = 0, PixelFormat = dds.Header.PixelFormat, Caps = DdsCaps1.Texture, Caps2 = 0, }, new() { DxgiFormat = dds.HeaderDxt10.DxgiFormat, ResourceDimension = DdsHeaderDxt10ResourceDimension.Texture2D, MiscFlag = 0, ArraySize = 1, MiscFlags2 = dds.HeaderDxt10.MiscFlags2, }, span.ToArray(), Array.Empty< byte >() ); dds2.Header.Pitch = dds2.Pitch( 0 ); dds2.WriteToFile( $"Z:/test/{basename}.raw[{slice.Image}.{slice.Face}.{slice.Mipmap}.{slice.Slice}].dds" ); } } } } } ```
Soreepeong commented 1 year ago

this is getting out of hand and probably better off not being in lumina