mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Add support for explicit diffuse + specular textures
This commit is contained in:
parent
e8fd452b8f
commit
2fa7272762
1 changed files with 51 additions and 4 deletions
|
|
@ -6,6 +6,7 @@ using SixLabors.ImageSharp.Advanced;
|
|||
using SixLabors.ImageSharp.Formats.Png;
|
||||
using SixLabors.ImageSharp.Memory;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
|
||||
namespace Penumbra.Import.Models.Export;
|
||||
|
||||
|
|
@ -32,25 +33,37 @@ public class MaterialExporter
|
|||
|
||||
private static MaterialBuilder BuildCharacter(Material material, string name)
|
||||
{
|
||||
// TODO: handle models with an underlying diffuse
|
||||
var table = material.Mtrl.Table;
|
||||
|
||||
// TODO: there's a few normal usages i should check, i think.
|
||||
// TODO: tryget
|
||||
var normal = material.Textures[TextureUsage.SamplerNormal];
|
||||
|
||||
var operation = new ProcessCharacterNormalOperation(normal, table);
|
||||
ParallelRowIterator.IterateRows(ImageSharpConfiguration.Default, normal.Bounds(), in operation);
|
||||
|
||||
var baseColor = operation.BaseColor;
|
||||
if (material.Textures.TryGetValue(TextureUsage.SamplerDiffuse, out var diffuse))
|
||||
{
|
||||
MultiplyOperation.Execute(diffuse, baseColor);
|
||||
baseColor = diffuse;
|
||||
}
|
||||
|
||||
// TODO: what about the two specularmaps?
|
||||
var specular = operation.Specular;
|
||||
if (material.Textures.TryGetValue(TextureUsage.SamplerSpecular, out var newSpecular))
|
||||
{
|
||||
MultiplyOperation.Execute(newSpecular, specular);
|
||||
}
|
||||
|
||||
// TODO: clean up this name generation a bunch. probably a method.
|
||||
var imageName = name.Replace("/", "").Replace(".mtrl", "");
|
||||
|
||||
return BuildSharedBase(material, name)
|
||||
// NOTE: this isn't particularly precise to game behavior, but good enough for now.
|
||||
.WithAlpha(AlphaMode.MASK, 0.5f)
|
||||
.WithBaseColor(BuildImage(operation.BaseColor, $"{imageName}_basecolor"))
|
||||
.WithBaseColor(BuildImage(baseColor, $"{imageName}_basecolor"))
|
||||
.WithNormal(BuildImage(operation.Normal, $"{imageName}_normal"))
|
||||
.WithSpecularColor(BuildImage(operation.Specular, $"{imageName}_specular"))
|
||||
.WithSpecularColor(BuildImage(specular, $"{imageName}_specular"))
|
||||
.WithEmissive(BuildImage(operation.Emissive, $"{imageName}_emissive"), Vector3.One, 1);
|
||||
}
|
||||
|
||||
|
|
@ -105,6 +118,40 @@ public class MaterialExporter
|
|||
}
|
||||
}
|
||||
|
||||
private readonly struct MultiplyOperation
|
||||
{
|
||||
public static void Execute<TPixel1, TPixel2>(Image<TPixel1> target, Image<TPixel2> multiplier)
|
||||
where TPixel1 : unmanaged, IPixel<TPixel1>
|
||||
where TPixel2 : unmanaged, IPixel<TPixel2>
|
||||
{
|
||||
// Ensure the images are the same size
|
||||
var (small, large) = target.Width < multiplier.Width && target.Height < multiplier.Height
|
||||
? ((Image)target, (Image)multiplier)
|
||||
: (multiplier, target);
|
||||
small.Mutate(context => context.Resize(large.Width, large.Height));
|
||||
|
||||
var operation = new MultiplyOperation<TPixel1, TPixel2>(target, multiplier);
|
||||
ParallelRowIterator.IterateRows(ImageSharpConfiguration.Default, target.Bounds(), in operation);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly struct MultiplyOperation<TPixel1, TPixel2>(Image<TPixel1> target, Image<TPixel2> multiplier) : IRowOperation
|
||||
where TPixel1 : unmanaged, IPixel<TPixel1>
|
||||
where TPixel2 : unmanaged, IPixel<TPixel2>
|
||||
{
|
||||
|
||||
public void Invoke(int y)
|
||||
{
|
||||
var targetSpan = target.Frames.RootFrame.PixelBuffer.DangerousGetRowSpan(y);
|
||||
var multiplierSpan = multiplier.Frames.RootFrame.PixelBuffer.DangerousGetRowSpan(y);
|
||||
|
||||
for (int x = 0; x < targetSpan.Length; x++)
|
||||
{
|
||||
targetSpan[x].FromVector4(targetSpan[x].ToVector4() * multiplierSpan[x].ToVector4());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static TableRow GetTableRowIndices(float input)
|
||||
{
|
||||
// These calculations are ported from character.shpk.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue