UMaterialInstance viewer

This commit is contained in:
MountainFlash 2021-11-19 22:39:12 +05:30
parent 7d12023618
commit dc797ade45
No known key found for this signature in database
GPG Key ID: 6BDA200334E04E1A
2 changed files with 106 additions and 71 deletions

View File

@ -689,6 +689,15 @@ namespace FModel.ViewModels
SaveExport(export);
return true;
}
case UMaterialInstance when UserSettings.Default.IsAutoOpenMeshes:
{
Application.Current.Dispatcher.Invoke(() =>
{
var modelViewer = Helper.GetWindow<ModelViewer>("Model Viewer", () => new ModelViewer().Show());
modelViewer.Load(export);
});
return true;
}
default:
{
using var package = new CreatorPackage(export, UserSettings.Default.CosmeticStyle);

View File

@ -130,6 +130,9 @@ namespace FModel.ViewModels
case USkeletalMesh sk:
LoadSkeletalMesh(sk);
break;
case UMaterialInstance mi:
LoadMaterialInstance(mi);
break;
default: // idiot
throw new ArgumentOutOfRangeException();
}
@ -202,6 +205,22 @@ namespace FModel.ViewModels
Cam.AnimateTo(camAxis.Position, camAxis.LookDirection, new Vector3D(0, 1, 0), 500);
}
private void LoadMaterialInstance(UMaterialInstance materialInstance)
{
var builder = new MeshBuilder();
builder.AddSphere(Vector3.Zero, 10);
var camAxis = SetupCameraAndAxis(new FBox(new FVector(-15), new FVector(15)));
var (m, isRendering) = LoadMaterial(materialInstance);
_geometries.Add(new MeshGeometryModel3D
{
Transform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(1,0,0), -90)),
Name = materialInstance.Name.Replace('-', '_'), Geometry = builder.ToMeshGeometry3D(),
Material = m, IsRendering = isRendering, Tag = false // flag
}, camAxis);
}
private void LoadStaticMesh(UStaticMesh mesh)
{
if (!mesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Count <= 0)
@ -258,77 +277,7 @@ namespace FModel.ViewModels
if (section.Material == null || !section.Material.TryLoad<UMaterialInterface>(out var unrealMaterial))
continue;
var m = new PBRMaterial { RenderShadowMap = true, EnableAutoTangent = true, RenderEnvironmentMap = true };
var parameters = new CMaterialParams();
unrealMaterial.GetParams(parameters);
var isRendering = !parameters.IsNull;
if (isRendering)
{
if (parameters.Diffuse is UTexture2D diffuse)
m.AlbedoMap = new TextureModel(diffuse.Decode()?.Encode().AsStream());
if (parameters.Normal is UTexture2D normal)
m.NormalMap = new TextureModel(normal.Decode()?.Encode().AsStream());
if (_game == FGame.FortniteGame)
{
// Fortnite's Specular Texture Channels
// R Specular
// G Metallic
// B Roughness
if (parameters.Specular is UTexture2D specular)
{
var mip = specular.GetFirstMip();
TextureDecoder.DecodeTexture(mip, specular.Format, specular.isNormalMap,
out var data, out var colorType);
unsafe
{
var offset = 0;
fixed (byte* d = data)
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
{
d[offset] = 0;
(d[offset+1], d[offset+2]) = (d[offset+2], d[offset+1]); // swap G and B
offset += 4;
}
}
var width = mip.SizeX;
var height = mip.SizeY;
using var bitmap = new SKBitmap(new SKImageInfo(width, height, colorType, SKAlphaType.Unpremul));
unsafe
{
fixed (byte* p = data)
{
bitmap.SetPixels(new IntPtr(p));
}
}
// R -> AO G -> Roughness B -> Metallic
m.RoughnessMetallicMap = new TextureModel(bitmap.Encode(SKEncodedImageFormat.Png, 100).AsStream());
m.RenderAmbientOcclusionMap = false; // red channel is not ao
m.MetallicFactor = 1;
m.RoughnessFactor = 1;
}
}
// if (parameters.Specular is UTexture2D specular)
// m.AmbientOcculsionMap = new TextureModel(specular.Decode()?.Encode().AsStream());
// if (parameters.Specular is UTexture2D specularPower)
// {
// m.RoughnessFactor = parameters.MobileSpecularPower;
// m.RoughnessMetallicMap = new TextureModel(specularPower.Decode()?.Encode().AsStream());
// }
// if (parameters.Emissive is UTexture2D emissive)
// {
// m.EmissiveColor = Color4.White; // FortniteGame/Content/Characters/Player/Female/Medium/Bodies/F_MED_Obsidian/Meshes/F_MED_Obsidian.uasset
// m.EmissiveMap = new TextureModel(emissive.Decode()?.Encode().AsStream());
// }
}
else
{
m = new PBRMaterial { AlbedoColor = new Color4(1, 0, 0, 1) }; //PhongMaterials.Red;
}
var (m, isRendering) = LoadMaterial(unrealMaterial);
_geometries.Add(new MeshGeometryModel3D
{
@ -338,6 +287,83 @@ namespace FModel.ViewModels
}
}
private (PBRMaterial material, bool isRendering) LoadMaterial(UMaterialInterface unrealMaterial)
{
var m = new PBRMaterial { RenderShadowMap = true, EnableAutoTangent = true, RenderEnvironmentMap = true };
var parameters = new CMaterialParams();
unrealMaterial.GetParams(parameters);
var isRendering = !parameters.IsNull;
if (isRendering)
{
if (parameters.Diffuse is UTexture2D diffuse)
m.AlbedoMap = new TextureModel(diffuse.Decode()?.Encode().AsStream());
if (parameters.Normal is UTexture2D normal)
m.NormalMap = new TextureModel(normal.Decode()?.Encode().AsStream());
if (_game == FGame.FortniteGame)
{
// Fortnite's Specular Texture Channels
// R Specular
// G Metallic
// B Roughness
if (parameters.Specular is UTexture2D specular)
{
var mip = specular.GetFirstMip();
TextureDecoder.DecodeTexture(mip, specular.Format, specular.isNormalMap,
out var data, out var colorType);
unsafe
{
var offset = 0;
fixed (byte* d = data)
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
{
d[offset] = 0;
(d[offset+1], d[offset+2]) = (d[offset+2], d[offset+1]); // swap G and B
offset += 4;
}
}
var width = mip.SizeX;
var height = mip.SizeY;
using var bitmap = new SKBitmap(new SKImageInfo(width, height, colorType, SKAlphaType.Unpremul));
unsafe
{
fixed (byte* p = data)
{
bitmap.SetPixels(new IntPtr(p));
}
}
// R -> AO G -> Roughness B -> Metallic
m.RoughnessMetallicMap = new TextureModel(bitmap.Encode(SKEncodedImageFormat.Png, 100).AsStream());
m.RenderAmbientOcclusionMap = false; // red channel is not ao
m.MetallicFactor = 1;
m.RoughnessFactor = 1;
}
}
// if (parameters.Specular is UTexture2D specular)
// m.AmbientOcculsionMap = new TextureModel(specular.Decode()?.Encode().AsStream());
// if (parameters.Specular is UTexture2D specularPower)
// {
// m.RoughnessFactor = parameters.MobileSpecularPower;
// m.RoughnessMetallicMap = new TextureModel(specularPower.Decode()?.Encode().AsStream());
// }
// if (parameters.Emissive is UTexture2D emissive)
// {
// m.EmissiveColor = Color4.White; // FortniteGame/Content/Characters/Player/Female/Medium/Bodies/F_MED_Obsidian/Meshes/F_MED_Obsidian.uasset
// m.EmissiveMap = new TextureModel(emissive.Decode()?.Encode().AsStream());
// }
}
else
{
m = new PBRMaterial { AlbedoColor = new Color4(1, 0, 0, 1) }; //PhongMaterials.Red;
}
return (m, isRendering);
}
private CamAxisHolder SetupCameraAndAxis(FBox box)
{
var ret = new CamAxisHolder();