You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
* Option is disabled by default * When enabled, the resulting merged mesh will have: ** An additional unused material which is created from the merge of all meshes materials ** An additional set of UV coordinates that can be used to apply the merged material to any section of the mesh ** Added additional static switch params to BaseFlattenMaterials to allow specifying UV channel [FYI] jurre.debaare #rnx #ROBOMERGE-SOURCE: CL 7473968 via CL 7474018 #ROBOMERGE-BOT: (v372-7473910) [CL 7474030 by sebastien lussier in Main branch]
285 lines
14 KiB
C++
285 lines
14 KiB
C++
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Engine/MaterialMerging.h"
|
|
#include "StaticParameterSet.h"
|
|
#include "Materials/Material.h"
|
|
#include "Engine/Texture2D.h"
|
|
#include "MaterialUtilities.h"
|
|
#include "Materials/MaterialInstanceConstant.h"
|
|
#include "IMeshMergeUtilities.h"
|
|
#include "MeshMergeModule.h"
|
|
#include "Modules/ModuleManager.h"
|
|
|
|
namespace ProxyMaterialUtilities
|
|
{
|
|
#define TEXTURE_MACRO_BASE(a, b, c) \
|
|
bool b##a##Texture = FlattenMaterial.DoesPropertyContainData(EFlattenMaterialProperties::a) && !FlattenMaterial.IsPropertyConstant(EFlattenMaterialProperties::a); \
|
|
if ( b##a##Texture) \
|
|
{ \
|
|
UTexture2D* a##Texture = b##a##Texture ? FMaterialUtilities::CreateTexture(InOuter, AssetBasePath + TEXT("T_") + AssetBaseName + TEXT("_" #a), FlattenMaterial.GetPropertySize(EFlattenMaterialProperties::a), FlattenMaterial.GetPropertySamples(EFlattenMaterialProperties::a), b, TEXTUREGROUP_HierarchicalLOD, RF_Public | RF_Standalone, c) : nullptr; \
|
|
OutMaterial->SetTextureParameterValueEditorOnly(FMaterialParameterInfo(#a "Texture"), a##Texture); \
|
|
FStaticSwitchParameter SwitchParameter; \
|
|
SwitchParameter.ParameterInfo.Name = "Use" #a; \
|
|
SwitchParameter.Value = true; \
|
|
SwitchParameter.bOverride = true; \
|
|
NewStaticParameterSet.StaticSwitchParameters.Add(SwitchParameter); \
|
|
a##Texture->PostEditChange(); \
|
|
OutAssetsToSync.Add(a##Texture); \
|
|
}
|
|
|
|
#define TEXTURE_MACRO_VECTOR(a, b, c) TEXTURE_MACRO_BASE(a, b, c)\
|
|
else\
|
|
{ \
|
|
OutMaterial->SetVectorParameterValueEditorOnly(FMaterialParameterInfo(#a "Const"), FlattenMaterial.GetPropertySamples(EFlattenMaterialProperties::a)[0]); \
|
|
}
|
|
|
|
#define TEXTURE_MACRO_VECTOR_LINEAR(a, b, c) TEXTURE_MACRO_BASE(a, b, c)\
|
|
else\
|
|
{ \
|
|
OutMaterial->SetVectorParameterValueEditorOnly(FMaterialParameterInfo(#a "Const"), FlattenMaterial.GetPropertySamples(EFlattenMaterialProperties::a)[0].ReinterpretAsLinear()); \
|
|
}
|
|
|
|
#define TEXTURE_MACRO_SCALAR(a, b, c) TEXTURE_MACRO_BASE(a, b, c)\
|
|
else \
|
|
{ \
|
|
FLinearColor Colour = FlattenMaterial.IsPropertyConstant(EFlattenMaterialProperties::a) ? FLinearColor::FromSRGBColor( FlattenMaterial.GetPropertySamples(EFlattenMaterialProperties::a)[0]) : FLinearColor( InMaterialProxySettings.a##Constant, 0, 0, 0 ); \
|
|
OutMaterial->SetScalarParameterValueEditorOnly(FMaterialParameterInfo(#a "Const"), Colour.R); \
|
|
}
|
|
|
|
static const bool CalculatePackedTextureData(const FFlattenMaterial& InMaterial, bool& bOutPackMetallic, bool& bOutPackSpecular, bool& bOutPackRoughness, int32& OutNumSamples, FIntPoint& OutSize)
|
|
{
|
|
// Whether or not a material property is baked down
|
|
const bool bHasMetallic = InMaterial.DoesPropertyContainData(EFlattenMaterialProperties::Metallic) && !InMaterial.IsPropertyConstant(EFlattenMaterialProperties::Metallic);
|
|
const bool bHasRoughness = InMaterial.DoesPropertyContainData(EFlattenMaterialProperties::Roughness) && !InMaterial.IsPropertyConstant(EFlattenMaterialProperties::Roughness);
|
|
const bool bHasSpecular = InMaterial.DoesPropertyContainData(EFlattenMaterialProperties::Specular) && !InMaterial.IsPropertyConstant(EFlattenMaterialProperties::Specular);
|
|
|
|
// Check for same texture sizes
|
|
bool bSameTextureSize = false;
|
|
|
|
// Determine whether or not the properties sizes match
|
|
|
|
|
|
const FIntPoint MetallicSize = InMaterial.GetPropertySize(EFlattenMaterialProperties::Metallic);
|
|
const FIntPoint SpecularSize = InMaterial.GetPropertySize(EFlattenMaterialProperties::Specular);
|
|
const FIntPoint RoughnessSize = InMaterial.GetPropertySize(EFlattenMaterialProperties::Roughness);
|
|
|
|
bSameTextureSize = (MetallicSize == RoughnessSize) || (MetallicSize == SpecularSize);
|
|
if (bSameTextureSize)
|
|
{
|
|
OutSize = MetallicSize;
|
|
OutNumSamples = InMaterial.GetPropertySamples(EFlattenMaterialProperties::Metallic).Num();
|
|
}
|
|
else
|
|
{
|
|
bSameTextureSize = (RoughnessSize == SpecularSize);
|
|
if (bSameTextureSize)
|
|
{
|
|
OutSize = RoughnessSize;
|
|
OutNumSamples = InMaterial.GetPropertySamples(EFlattenMaterialProperties::Roughness).Num();
|
|
}
|
|
}
|
|
|
|
// Now that we know if the data matches determine whether or not we should pack the properties
|
|
int32 NumPacked = 0;
|
|
if (OutNumSamples != 0)
|
|
{
|
|
bOutPackMetallic = bHasMetallic ? (OutNumSamples == InMaterial.GetPropertySamples(EFlattenMaterialProperties::Metallic).Num()) : false;
|
|
NumPacked += (bOutPackMetallic) ? 1 : 0;
|
|
bOutPackRoughness = bHasRoughness ? (OutNumSamples == InMaterial.GetPropertySamples(EFlattenMaterialProperties::Roughness).Num()) : false;
|
|
NumPacked += (bOutPackRoughness) ? 1 : 0;
|
|
bOutPackSpecular = bHasSpecular ? (OutNumSamples == InMaterial.GetPropertySamples(EFlattenMaterialProperties::Specular).Num()) : false;
|
|
NumPacked += (bOutPackSpecular) ? 1 : 0;
|
|
}
|
|
else
|
|
{
|
|
bOutPackMetallic = bOutPackRoughness = bOutPackSpecular = false;
|
|
}
|
|
|
|
// Need atleast two properties to pack
|
|
return NumPacked >= 2;
|
|
}
|
|
|
|
static UMaterialInstanceConstant* CreateProxyMaterialInstance(UPackage* InOuter, const FMaterialProxySettings& InMaterialProxySettings, UMaterialInterface* InBaseMaterial, const FFlattenMaterial& FlattenMaterial, const FString& AssetBasePath, const FString& AssetBaseName, TArray<UObject*>& OutAssetsToSync)
|
|
{
|
|
UMaterialInterface* BaseMaterial = InBaseMaterial;
|
|
|
|
const IMeshMergeUtilities& Module = FModuleManager::Get().LoadModuleChecked<IMeshMergeModule>("MeshMergeUtilities").GetUtilities();
|
|
if (!Module.IsValidBaseMaterial(InBaseMaterial, false))
|
|
{
|
|
BaseMaterial = LoadObject<UMaterialInterface>(NULL, TEXT("/Engine/EngineMaterials/BaseFlattenMaterial.BaseFlattenMaterial"), NULL, LOAD_None, NULL);
|
|
}
|
|
|
|
UMaterialInstanceConstant* OutMaterial = FMaterialUtilities::CreateInstancedMaterial(BaseMaterial, InOuter, AssetBasePath + AssetBaseName, RF_Public | RF_Standalone);
|
|
OutAssetsToSync.Add(OutMaterial);
|
|
|
|
OutMaterial->BasePropertyOverrides.TwoSided = FlattenMaterial.bTwoSided && InMaterialProxySettings.bAllowTwoSidedMaterial;
|
|
OutMaterial->BasePropertyOverrides.bOverride_TwoSided = (FlattenMaterial.bTwoSided != false) && InMaterialProxySettings.bAllowTwoSidedMaterial;
|
|
OutMaterial->BasePropertyOverrides.DitheredLODTransition = FlattenMaterial.bDitheredLODTransition;
|
|
OutMaterial->BasePropertyOverrides.bOverride_DitheredLODTransition = FlattenMaterial.bDitheredLODTransition != false;
|
|
|
|
if (InMaterialProxySettings.BlendMode != BLEND_Opaque)
|
|
{
|
|
OutMaterial->BasePropertyOverrides.bOverride_BlendMode = true;
|
|
OutMaterial->BasePropertyOverrides.BlendMode = InMaterialProxySettings.BlendMode;
|
|
}
|
|
|
|
bool bPackMetallic, bPackSpecular, bPackRoughness;
|
|
int32 NumSamples = 0;
|
|
FIntPoint PackedSize;
|
|
const bool bPackTextures = CalculatePackedTextureData(FlattenMaterial, bPackMetallic, bPackSpecular, bPackRoughness, NumSamples, PackedSize);
|
|
|
|
const bool bSRGB = true;
|
|
const bool bRGB = false;
|
|
|
|
FStaticParameterSet NewStaticParameterSet;
|
|
|
|
if(FlattenMaterial.UVChannel != 0)
|
|
{
|
|
// If the used texture coordinate was not the default UV0 set the appropriate one on the instance material
|
|
FStaticSwitchParameter SwitchParameter;
|
|
SwitchParameter.ParameterInfo.Name = TEXT("UseCustomUV");
|
|
SwitchParameter.Value = true;
|
|
SwitchParameter.bOverride = true;
|
|
NewStaticParameterSet.StaticSwitchParameters.Add(SwitchParameter);
|
|
|
|
SwitchParameter.ParameterInfo.Name = *(TEXT("UseUV") + FString::FromInt(FlattenMaterial.UVChannel));
|
|
NewStaticParameterSet.StaticSwitchParameters.Add(SwitchParameter);
|
|
}
|
|
|
|
// Load textures and set switches accordingly
|
|
if (FlattenMaterial.GetPropertySize(EFlattenMaterialProperties::Diffuse).Num() > 0 && !(FlattenMaterial.IsPropertyConstant(EFlattenMaterialProperties::Diffuse) && FlattenMaterial.GetPropertySamples(EFlattenMaterialProperties::Diffuse)[0] == FColor::Black))
|
|
{
|
|
TEXTURE_MACRO_VECTOR(Diffuse, TC_Default, bSRGB);
|
|
}
|
|
|
|
if (FlattenMaterial.GetPropertySize(EFlattenMaterialProperties::Normal).Num() > 1)
|
|
{
|
|
TEXTURE_MACRO_BASE(Normal, TC_Normalmap, bRGB)
|
|
}
|
|
|
|
// Determine whether or not specific material properties are packed together into one texture (requires at least two to match (number of samples and texture size) in order to be packed
|
|
if (!bPackMetallic && (FlattenMaterial.GetPropertySize(EFlattenMaterialProperties::Metallic).Num() > 0 || !InMaterialProxySettings.bMetallicMap))
|
|
{
|
|
TEXTURE_MACRO_SCALAR(Metallic, TC_Default, bSRGB);
|
|
}
|
|
|
|
if (!bPackRoughness && (FlattenMaterial.GetPropertySize(EFlattenMaterialProperties::Roughness).Num() > 0 || !InMaterialProxySettings.bRoughnessMap))
|
|
{
|
|
TEXTURE_MACRO_SCALAR(Roughness, TC_Default, bSRGB);
|
|
}
|
|
|
|
if (!bPackSpecular && (FlattenMaterial.GetPropertySize(EFlattenMaterialProperties::Specular).Num() > 0 || !InMaterialProxySettings.bSpecularMap))
|
|
{
|
|
TEXTURE_MACRO_SCALAR(Specular, TC_Default, bSRGB);
|
|
}
|
|
|
|
const bool bNonSRGB = false;
|
|
|
|
if (FlattenMaterial.GetPropertySize(EFlattenMaterialProperties::Opacity).Num() > 0 || !InMaterialProxySettings.bOpacityMap)
|
|
{
|
|
TEXTURE_MACRO_SCALAR(Opacity, TC_Grayscale, bNonSRGB);
|
|
}
|
|
|
|
if (FlattenMaterial.GetPropertySize(EFlattenMaterialProperties::OpacityMask).Num() > 0 || !InMaterialProxySettings.bOpacityMaskMap)
|
|
{
|
|
TEXTURE_MACRO_SCALAR(OpacityMask, TC_Grayscale, bNonSRGB);
|
|
}
|
|
|
|
if (FlattenMaterial.GetPropertySize(EFlattenMaterialProperties::AmbientOcclusion).Num() > 0 || !InMaterialProxySettings.bAmbientOcclusionMap)
|
|
{
|
|
TEXTURE_MACRO_SCALAR(AmbientOcclusion, TC_Grayscale, bNonSRGB);
|
|
}
|
|
|
|
// Handle the packed texture if applicable
|
|
if (bPackTextures)
|
|
{
|
|
TArray<FColor> MergedTexture;
|
|
MergedTexture.AddZeroed(NumSamples);
|
|
|
|
// Merge properties into one texture using the separate colour channels
|
|
const EFlattenMaterialProperties Properties[3] = { EFlattenMaterialProperties::Metallic , EFlattenMaterialProperties::Roughness, EFlattenMaterialProperties::Specular };
|
|
|
|
//Property that is not part of the pack (because of a different size), will see is reserve pack space fill with Black Color.
|
|
const bool PropertyShouldBePack[3] = { bPackMetallic , bPackRoughness , bPackSpecular };
|
|
|
|
// Red mask (all properties are rendered into the red channel)
|
|
FColor NonAlphaRed = FColor::Red;
|
|
NonAlphaRed.A = 0;
|
|
const uint32 ColorMask = NonAlphaRed.DWColor();
|
|
const uint32 Shift[3] = { 0, 8, 16 };
|
|
for (int32 PropertyIndex = 0; PropertyIndex < 3; ++PropertyIndex)
|
|
{
|
|
const EFlattenMaterialProperties Property = Properties[PropertyIndex];
|
|
const bool HasProperty = PropertyShouldBePack[PropertyIndex] && FlattenMaterial.DoesPropertyContainData(Property) && !FlattenMaterial.IsPropertyConstant(Property);
|
|
|
|
if (HasProperty)
|
|
{
|
|
const TArray<FColor>& PropertySamples = FlattenMaterial.GetPropertySamples(Property);
|
|
// OR masked values (samples initialized to zero, so no random data)
|
|
for (int32 SampleIndex = 0; SampleIndex < NumSamples; ++SampleIndex)
|
|
{
|
|
// Black adds the alpha + red channel value shifted into the correct output channel
|
|
MergedTexture[SampleIndex].DWColor() |= (FColor::Black.DWColor() + ((PropertySamples[SampleIndex].DWColor() & ColorMask) >> Shift[PropertyIndex]));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create texture using the merged property data
|
|
UTexture2D* PackedTexture = FMaterialUtilities::CreateTexture(InOuter, AssetBasePath + TEXT("T_") + AssetBaseName + TEXT("_MRS"), PackedSize, MergedTexture, TC_Default, TEXTUREGROUP_HierarchicalLOD, RF_Public | RF_Standalone, bSRGB);
|
|
checkf(PackedTexture, TEXT("Failed to create texture"));
|
|
OutAssetsToSync.Add(PackedTexture);
|
|
|
|
// Setup switches for whether or not properties will be packed into one texture
|
|
FStaticSwitchParameter SwitchParameter;
|
|
SwitchParameter.ParameterInfo.Name = TEXT("PackMetallic");
|
|
SwitchParameter.Value = bPackMetallic;
|
|
SwitchParameter.bOverride = true;
|
|
NewStaticParameterSet.StaticSwitchParameters.Add(SwitchParameter);
|
|
|
|
SwitchParameter.ParameterInfo.Name = TEXT("PackSpecular");
|
|
SwitchParameter.Value = bPackSpecular;
|
|
SwitchParameter.bOverride = true;
|
|
NewStaticParameterSet.StaticSwitchParameters.Add(SwitchParameter);
|
|
|
|
SwitchParameter.ParameterInfo.Name = TEXT("PackRoughness");
|
|
SwitchParameter.Value = bPackRoughness;
|
|
SwitchParameter.bOverride = true;
|
|
NewStaticParameterSet.StaticSwitchParameters.Add(SwitchParameter);
|
|
|
|
// Set up switch and texture values
|
|
FMaterialParameterInfo ParameterInfo(TEXT("PackedTexture"));
|
|
OutMaterial->SetTextureParameterValueEditorOnly(ParameterInfo, PackedTexture);
|
|
}
|
|
|
|
// Emissive is a special case due to the scaling variable
|
|
if (FlattenMaterial.GetPropertySamples(EFlattenMaterialProperties::Emissive).Num() > 0 && !(FlattenMaterial.GetPropertySize(EFlattenMaterialProperties::Emissive).Num() == 1 && FlattenMaterial.GetPropertySamples(EFlattenMaterialProperties::Emissive)[0] == FColor::Black))
|
|
{
|
|
TEXTURE_MACRO_VECTOR_LINEAR(Emissive, TC_Default, bRGB);
|
|
|
|
if (FlattenMaterial.EmissiveScale != 1.0f)
|
|
{
|
|
FMaterialParameterInfo ParameterInfo(TEXT("EmissiveScale"));
|
|
OutMaterial->SetScalarParameterValueEditorOnly(ParameterInfo, FlattenMaterial.EmissiveScale);
|
|
}
|
|
}
|
|
|
|
// Force initializing the static permutations according to the switches we have set
|
|
OutMaterial->UpdateStaticPermutation(NewStaticParameterSet);
|
|
OutMaterial->InitStaticPermutation();
|
|
|
|
OutMaterial->PostEditChange();
|
|
|
|
return OutMaterial;
|
|
}
|
|
|
|
static UMaterialInstanceConstant* CreateProxyMaterialInstance(UPackage* InOuter, const FMaterialProxySettings& InMaterialProxySettings, FFlattenMaterial& FlattenMaterial, const FString& AssetBasePath, const FString& AssetBaseName, TArray<UObject*>& OutAssetsToSync)
|
|
{
|
|
UMaterialInterface* BaseMaterial = LoadObject<UMaterialInterface>(NULL, TEXT("/Engine/EngineMaterials/BaseFlattenMaterial.BaseFlattenMaterial"), NULL, LOAD_None, NULL);
|
|
return CreateProxyMaterialInstance(InOuter, InMaterialProxySettings, BaseMaterial, FlattenMaterial, AssetBasePath, AssetBasePath, OutAssetsToSync);
|
|
}
|
|
|
|
};
|