2019-12-26 15:32:37 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2016-11-23 15:48:37 -05:00
# include "MaterialUtilities.h"
# include "EngineDefines.h"
# include "ShowFlags.h"
# include "Materials/MaterialInterface.h"
# include "Materials/Material.h"
# include "Engine/Texture2D.h"
# include "Misc/App.h"
# include "Materials/MaterialInstance.h"
# include "Materials/MaterialInstanceConstant.h"
# include "Engine/TextureRenderTarget2D.h"
# include "Modules/ModuleManager.h"
# include "Misc/PackageName.h"
2017-11-16 11:36:35 -05:00
# include "LegacyScreenPercentageDriver.h"
2015-04-29 22:39:01 -04:00
2022-12-16 16:24:02 -05:00
# include "Materials/MaterialAttributeDefinitionMap.h"
2016-11-23 15:48:37 -05:00
# include "Materials/MaterialExpressionConstant.h"
# include "Materials/MaterialExpressionConstant4Vector.h"
# include "Materials/MaterialExpressionMultiply.h"
2022-12-16 16:24:02 -05:00
# include "Materials/MaterialRenderProxy.h"
2016-11-23 15:48:37 -05:00
# include "Engine/TextureCube.h"
2019-09-14 09:45:25 -04:00
# include "Engine/Texture2DArray.h"
2016-11-23 15:48:37 -05:00
# include "SceneView.h"
2021-12-08 11:38:32 -05:00
# include "SceneViewExtension.h"
2015-04-29 22:39:01 -04:00
# include "RendererInterface.h"
2016-11-23 15:48:37 -05:00
# include "EngineModule.h"
# include "ImageUtils.h"
# include "CanvasTypes.h"
# include "Materials/MaterialExpressionTextureSample.h"
# include "MaterialCompiler.h"
2022-12-15 16:01:51 -05:00
# include "MaterialDomain.h"
2016-11-23 15:48:37 -05:00
# include "DeviceProfiles/DeviceProfileManager.h"
# include "Materials/MaterialParameterCollection.h"
2015-04-29 22:39:01 -04:00
# include "LandscapeProxy.h"
# include "LandscapeComponent.h"
2016-11-23 15:48:37 -05:00
# include "Engine/MeshMerging.h"
# include "Engine/StaticMesh.h"
2015-10-28 19:18:20 -04:00
# include "MeshUtilities.h"
# include "MeshRendering.h"
# include "MeshMergeData.h"
2022-10-26 12:57:32 -04:00
# include "PrimitiveSceneProxy.h"
2018-01-20 11:19:29 -05:00
# include "Templates/UniquePtr.h"
2022-10-26 12:57:32 -04:00
# include "TextureResource.h"
2015-04-29 22:39:01 -04:00
2017-06-21 10:25:35 -04:00
# include "IMaterialBakingModule.h"
# include "MaterialBakingStructures.h"
# include "MaterialOptions.h"
2019-10-01 20:41:42 -04:00
# include "StaticMeshAttributes.h"
2020-06-16 22:16:25 -04:00
# include "TextureCompiler.h"
2019-01-03 19:28:34 -05:00
2022-09-20 01:40:59 -04:00
# include "TriangleTypes.h"
# include "DynamicMesh/DynamicMesh3.h"
# include "DynamicMesh/DynamicMeshAttributeSet.h"
2016-07-20 18:23:54 -04:00
# if WITH_EDITOR
2016-11-23 15:48:37 -05:00
# include "DeviceProfiles/DeviceProfile.h"
2016-07-20 18:23:54 -04:00
# include "Tests/AutomationEditorCommon.h"
# endif // WITH_EDITOR
2017-06-21 10:25:35 -04:00
2015-10-28 19:18:20 -04:00
IMPLEMENT_MODULE ( FMaterialUtilities , MaterialUtilities ) ;
2015-05-04 03:40:20 -04:00
2015-04-30 02:24:37 -04:00
DEFINE_LOG_CATEGORY_STATIC ( LogMaterialUtilities , Log , All ) ;
2015-04-29 22:39:01 -04:00
2022-02-14 12:01:24 -05:00
static TAutoConsoleVariable < int32 > CVarMaterialUtilitiesWarmupFrames (
TEXT ( " MaterialUtilities.WarmupFrames " ) ,
10 ,
TEXT ( " Number of frames to render before each capture in order to warmup various rendering systems (VT/Nanite/etc). " ) ) ;
2015-10-28 19:18:20 -04:00
bool FMaterialUtilities : : CurrentlyRendering = false ;
TArray < UTextureRenderTarget2D * > FMaterialUtilities : : RenderTargetPool ;
void FMaterialUtilities : : StartupModule ( )
{
2017-08-31 12:08:38 -04:00
FCoreUObjectDelegates : : GetPreGarbageCollectDelegate ( ) . AddRaw ( this , & FMaterialUtilities : : OnPreGarbageCollect ) ;
2015-10-28 19:18:20 -04:00
}
void FMaterialUtilities : : ShutdownModule ( )
{
2017-08-31 12:08:38 -04:00
FCoreUObjectDelegates : : GetPreGarbageCollectDelegate ( ) . RemoveAll ( this ) ;
2015-10-28 19:18:20 -04:00
ClearRenderTargetPool ( ) ;
}
void FMaterialUtilities : : OnPreGarbageCollect ( )
{
ClearRenderTargetPool ( ) ;
}
2017-06-21 10:25:35 -04:00
UMaterialInterface * FMaterialUtilities : : CreateProxyMaterialAndTextures ( UPackage * OuterPackage , const FString & AssetName , const FBakeOutput & BakeOutput , const FMeshData & MeshData , const FMaterialData & MaterialData , UMaterialOptions * Options )
{
2022-02-14 18:36:13 -05:00
check ( MaterialData . Material ) ;
2021-05-27 10:31:36 -04:00
TArray < EMaterialProperty > SRGBEnabledProperties { MP_BaseColor , MP_EmissiveColor , MP_SubsurfaceColor } ;
2017-06-21 10:25:35 -04:00
// Certain material properties use differen compression settings
TMap < EMaterialProperty , TextureCompressionSettings > SpecialCompressionSettingProperties ;
SpecialCompressionSettingProperties . Add ( MP_Normal , TC_Normalmap ) ;
SpecialCompressionSettingProperties . Add ( MP_Opacity , TC_Grayscale ) ;
SpecialCompressionSettingProperties . Add ( MP_OpacityMask , TC_Grayscale ) ;
SpecialCompressionSettingProperties . Add ( MP_AmbientOcclusion , TC_Grayscale ) ;
2021-05-27 10:31:36 -04:00
UMaterial * BaseMaterial = GEngine - > DefaultFlattenMaterial ;
2017-06-21 10:25:35 -04:00
check ( BaseMaterial ) ;
/** Create Proxy material and populate flags */
UMaterialInstanceConstant * Material = FMaterialUtilities : : CreateInstancedMaterial ( BaseMaterial , OuterPackage , AssetName , RF_Public | RF_Standalone ) ;
2022-02-24 23:17:38 -05:00
check ( Material ) ;
2017-06-21 10:25:35 -04:00
Material - > BasePropertyOverrides . TwoSided = MaterialData . Material - > IsTwoSided ( ) ;
Material - > BasePropertyOverrides . bOverride_TwoSided = MaterialData . Material - > IsTwoSided ( ) ;
2022-11-30 02:10:42 -05:00
Material - > BasePropertyOverrides . bOverride_bIsThinSurface = MaterialData . Material - > IsThinSurface ( ) ;
2017-06-21 10:25:35 -04:00
Material - > BasePropertyOverrides . DitheredLODTransition = MaterialData . Material - > IsDitheredLODTransition ( ) ;
Material - > BasePropertyOverrides . bOverride_DitheredLODTransition = MaterialData . Material - > IsDitheredLODTransition ( ) ;
2022-12-14 12:32:01 -05:00
if ( ! IsOpaqueBlendMode ( * MaterialData . Material ) )
2017-06-21 10:25:35 -04:00
{
Material - > BasePropertyOverrides . bOverride_BlendMode = true ;
Material - > BasePropertyOverrides . BlendMode = MaterialData . Material - > GetBlendMode ( ) ;
}
FStaticParameterSet NewStaticParameterSet ;
// iterate over each property and its size
for ( auto Iterator : BakeOutput . PropertySizes )
{
EMaterialProperty Property = Iterator . Key ;
FIntPoint DataSize = Iterator . Value ;
// Retrieve pixel data for the current property
const TArray < FColor > & ColorData = BakeOutput . PropertyData . FindChecked ( Property ) ;
// Look up the property name string
2019-01-23 17:01:56 -05:00
const UEnum * PropertyEnum = StaticEnum < EMaterialProperty > ( ) ;
2017-06-21 10:25:35 -04:00
FName PropertyName = PropertyEnum - > GetNameByValue ( Property ) ;
FString TrimmedPropertyName = PropertyName . ToString ( ) ;
TrimmedPropertyName . RemoveFromStart ( TEXT ( " MP_ " ) ) ;
// If the pixel data isn't constant create a texture for it
if ( ColorData . Num ( ) > 1 )
{
2022-02-14 12:01:24 -05:00
FMaterialParameterInfo ParameterInfo ( * ( TrimmedPropertyName + TEXT ( " Texture " ) ) ) ;
FCreateTexture2DParameters CreateParams ;
CreateParams . TextureGroup = TEXTUREGROUP_HierarchicalLOD ;
CreateParams . CompressionSettings = SpecialCompressionSettingProperties . Contains ( Property ) ? SpecialCompressionSettingProperties . FindChecked ( Property ) : TC_Default ;
CreateParams . bSRGB = SRGBEnabledProperties . Contains ( Property ) ;
// Make sure the texture is a VT if required by the material sampler
2022-03-10 21:09:41 -05:00
UTexture * DefaultTexture = nullptr ;
Material - > GetTextureParameterValue ( ParameterInfo , DefaultTexture ) ;
if ( DefaultTexture )
2022-02-14 12:01:24 -05:00
{
2022-03-10 21:09:41 -05:00
CreateParams . bVirtualTexture = DefaultTexture - > VirtualTextureStreaming ;
2022-02-14 12:01:24 -05:00
}
UTexture * Texture = FMaterialUtilities : : CreateTexture ( OuterPackage , TEXT ( " T_ " ) + AssetName + TEXT ( " _ " ) + TrimmedPropertyName , DataSize , ColorData , CreateParams , RF_Public | RF_Standalone ) ;
2017-06-21 10:25:35 -04:00
// Set texture parameter value on instance material
2017-10-04 13:36:51 -04:00
Material - > SetTextureParameterValueEditorOnly ( ParameterInfo , Texture ) ;
2017-06-21 10:25:35 -04:00
FStaticSwitchParameter SwitchParameter ;
2017-10-04 13:36:51 -04:00
SwitchParameter . ParameterInfo . Name = * ( TEXT ( " Use " ) + TrimmedPropertyName ) ;
2017-06-21 10:25:35 -04:00
SwitchParameter . Value = true ;
SwitchParameter . bOverride = true ;
2022-10-28 13:54:13 -04:00
NewStaticParameterSet . StaticSwitchParameters . Add ( SwitchParameter ) ;
2017-06-21 10:25:35 -04:00
}
else
{
2017-10-04 13:36:51 -04:00
// Otherwise set either float4 or float constant values on instance material
FMaterialParameterInfo ParameterInfo ( * ( TrimmedPropertyName + TEXT ( " Const " ) ) ) ;
2017-06-21 10:25:35 -04:00
if ( Property = = MP_BaseColor | | Property = = MP_EmissiveColor )
{
2020-09-01 14:07:48 -04:00
Material - > SetVectorParameterValueEditorOnly ( ParameterInfo , FLinearColor : : FromSRGBColor ( ColorData [ 0 ] ) ) ;
2017-06-21 10:25:35 -04:00
}
else
{
2020-09-01 14:07:48 -04:00
Material - > SetScalarParameterValueEditorOnly ( ParameterInfo , FLinearColor : : FromSRGBColor ( ColorData [ 0 ] ) . R ) ;
2017-06-21 10:25:35 -04:00
}
}
}
// Apply emissive scaling
if ( BakeOutput . PropertyData . Contains ( MP_EmissiveColor ) )
{
if ( BakeOutput . EmissiveScale ! = 1.0f )
{
2017-10-04 13:36:51 -04:00
FMaterialParameterInfo ParameterInfo ( TEXT ( " EmissiveScale " ) ) ;
Material - > SetScalarParameterValueEditorOnly ( ParameterInfo , BakeOutput . EmissiveScale ) ;
2017-06-21 10:25:35 -04:00
}
}
// If the used texture coordinate was not the default UV0 set the appropriate one on the instance material
if ( MeshData . TextureCoordinateIndex ! = 0 )
{
FStaticSwitchParameter SwitchParameter ;
2017-10-04 13:36:51 -04:00
SwitchParameter . ParameterInfo . Name = TEXT ( " UseCustomUV " ) ;
2017-06-21 10:25:35 -04:00
SwitchParameter . Value = true ;
SwitchParameter . bOverride = true ;
2022-10-28 13:54:13 -04:00
NewStaticParameterSet . StaticSwitchParameters . Add ( SwitchParameter ) ;
2017-06-21 10:25:35 -04:00
2017-10-04 13:36:51 -04:00
SwitchParameter . ParameterInfo . Name = * ( TEXT ( " UseUV " ) + FString : : FromInt ( MeshData . TextureCoordinateIndex ) ) ;
2022-10-28 13:54:13 -04:00
NewStaticParameterSet . StaticSwitchParameters . Add ( SwitchParameter ) ;
2017-06-21 10:25:35 -04:00
}
Material - > UpdateStaticPermutation ( NewStaticParameterSet ) ;
Material - > InitStaticPermutation ( ) ;
Material - > PostEditChange ( ) ;
return Material ;
}
UMaterialInterface * FMaterialUtilities : : CreateProxyMaterialAndTextures ( const FString & PackageName , const FString & AssetName , const FBakeOutput & BakeOutput , const FMeshData & MeshData , const FMaterialData & MaterialData , UMaterialOptions * Options )
{
2020-09-24 00:43:27 -04:00
UPackage * MaterialPackage = CreatePackage ( * PackageName ) ;
2017-06-21 10:25:35 -04:00
check ( MaterialPackage ) ;
MaterialPackage - > FullyLoad ( ) ;
MaterialPackage - > Modify ( ) ;
return CreateProxyMaterialAndTextures ( MaterialPackage , AssetName , BakeOutput , MeshData , MaterialData , Options ) ;
}
2015-10-28 19:18:20 -04:00
2015-04-29 22:39:01 -04:00
/*------------------------------------------------------------------------------
Helper classes for render material to texture
------------------------------------------------------------------------------*/
2015-05-11 07:08:08 -04:00
struct FExportMaterialCompiler : public FProxyMaterialCompiler
{
FExportMaterialCompiler ( FMaterialCompiler * InCompiler ) :
FProxyMaterialCompiler ( InCompiler )
{ }
// gets value stored by SetMaterialProperty()
virtual EShaderFrequency GetCurrentShaderFrequency ( ) const override
{
// not used by Lightmass
return SF_Pixel ;
}
2019-05-06 06:04:18 -04:00
virtual FMaterialShadingModelField GetMaterialShadingModels ( ) const override
2016-08-18 20:28:33 -04:00
{
// not used by Lightmass
return MSM_MAX ;
}
2021-11-18 14:37:34 -05:00
virtual FMaterialShadingModelField GetCompiledShadingModels ( ) const override
{
// not used by Lightmass
return MSM_MAX ;
}
2015-09-24 09:04:18 -04:00
virtual int32 WorldPosition ( EWorldPositionIncludedOffsets WorldPositionIncludedOffsets ) override
{
2015-12-08 09:25:02 -05:00
# if WITH_EDITOR
return Compiler - > MaterialBakingWorldPosition ( ) ;
# else
2015-09-24 09:04:18 -04:00
return Compiler - > WorldPosition ( WorldPositionIncludedOffsets ) ;
2015-12-08 09:25:02 -05:00
# endif
2015-09-24 09:04:18 -04:00
}
2023-06-06 20:59:55 -04:00
virtual int32 ObjectWorldPosition ( EPositionOrigin OriginType ) override
2015-09-24 09:04:18 -04:00
{
2023-06-06 20:59:55 -04:00
return Compiler - > ObjectWorldPosition ( OriginType ) ;
2015-09-24 09:04:18 -04:00
}
virtual int32 DistanceCullFade ( ) override
{
return Compiler - > Constant ( 1.0f ) ;
}
2023-06-06 20:59:55 -04:00
virtual int32 ActorWorldPosition ( EPositionOrigin OriginType ) override
2015-09-24 09:04:18 -04:00
{
2023-06-06 20:59:55 -04:00
return Compiler - > ActorWorldPosition ( OriginType ) ;
2015-09-24 09:04:18 -04:00
}
2015-05-11 07:08:08 -04:00
virtual int32 ParticleRelativeTime ( ) override
{
return Compiler - > Constant ( 0.0f ) ;
}
virtual int32 ParticleMotionBlurFade ( ) override
{
return Compiler - > Constant ( 1.0f ) ;
}
2015-11-12 18:11:48 -05:00
virtual int32 PixelNormalWS ( ) override
{
// Current returning vertex normal since pixel normal will contain incorrect data (normal calculated from uv data used as vertex positions to render out the material)
return Compiler - > VertexNormal ( ) ;
}
2015-05-11 07:08:08 -04:00
2015-10-28 08:58:16 -04:00
virtual int32 ParticleRandom ( ) override
{
return Compiler - > Constant ( 0.0f ) ;
}
2015-05-11 07:08:08 -04:00
virtual int32 ParticleDirection ( ) override
{
return Compiler - > Constant3 ( 0.0f , 0.0f , 0.0f ) ;
}
virtual int32 ParticleSpeed ( ) override
{
return Compiler - > Constant ( 0.0f ) ;
}
virtual int32 ParticleSize ( ) override
{
return Compiler - > Constant2 ( 0.0f , 0.0f ) ;
}
2023-04-21 17:35:23 -04:00
virtual int32 ParticleSpriteRotation ( ) override
{
return Compiler - > Constant2 ( 0.0f , 0.0f ) ;
}
2015-05-11 07:08:08 -04:00
virtual int32 ObjectRadius ( ) override
{
return Compiler - > Constant ( 500 ) ;
}
virtual int32 ObjectBounds ( ) override
{
2015-11-12 18:11:48 -05:00
return Compiler - > ObjectBounds ( ) ;
2015-05-11 07:08:08 -04:00
}
2019-05-22 20:04:48 -04:00
virtual int32 PreSkinnedLocalBounds ( int32 OutputIndex ) override
2019-03-19 19:49:42 -04:00
{
2019-05-22 20:04:48 -04:00
return Compiler - > PreSkinnedLocalBounds ( OutputIndex ) ;
2019-03-19 19:49:42 -04:00
}
2015-05-11 07:08:08 -04:00
virtual int32 CameraVector ( ) override
{
2015-09-24 09:04:18 -04:00
return Compiler - > Constant3 ( 0.0f , 0.0f , 1.0f ) ;
2015-05-11 07:08:08 -04:00
}
2015-09-24 09:04:18 -04:00
2015-05-11 07:08:08 -04:00
virtual int32 ReflectionAboutCustomWorldNormal ( int32 CustomWorldNormal , int32 bNormalizeCustomWorldNormal ) override
{
2015-11-12 18:11:48 -05:00
return Compiler - > ReflectionAboutCustomWorldNormal ( CustomWorldNormal , bNormalizeCustomWorldNormal ) ;
2015-05-11 07:08:08 -04:00
}
virtual int32 VertexColor ( ) override
{
2015-09-24 09:04:18 -04:00
return Compiler - > VertexColor ( ) ;
}
2016-10-07 10:20:36 -04:00
virtual int32 PreSkinnedPosition ( ) override
{
return Compiler - > PreSkinnedPosition ( ) ;
}
2016-10-20 20:09:22 -04:00
virtual int32 PreSkinnedNormal ( ) override
{
return Compiler - > PreSkinnedNormal ( ) ;
}
2017-02-16 17:52:21 -05:00
virtual int32 VertexInterpolator ( uint32 InterpolatorIndex ) override
{
return Compiler - > VertexInterpolator ( InterpolatorIndex ) ;
}
2015-09-24 09:04:18 -04:00
virtual int32 LightVector ( ) override
{
2015-11-12 18:11:48 -05:00
return Compiler - > LightVector ( ) ;
2015-09-24 09:04:18 -04:00
}
virtual int32 ReflectionVector ( ) override
{
2015-11-12 18:11:48 -05:00
return Compiler - > ReflectionVector ( ) ;
2015-09-24 09:04:18 -04:00
}
2023-11-06 20:11:55 -05:00
virtual int32 AtmosphericFogColor ( int32 WorldPosition , EPositionOrigin PositionOrigin ) override
2015-09-24 09:04:18 -04:00
{
return INDEX_NONE ;
}
virtual int32 PrecomputedAOMask ( ) override
{
return Compiler - > PrecomputedAOMask ( ) ;
}
2015-12-08 09:25:02 -05:00
# if WITH_EDITOR
virtual int32 MaterialBakingWorldPosition ( ) override
{
return Compiler - > MaterialBakingWorldPosition ( ) ;
}
# endif
2015-09-24 09:04:18 -04:00
virtual int32 AccessCollectionParameter ( UMaterialParameterCollection * ParameterCollection , int32 ParameterIndex , int32 ComponentIndex ) override
{
if ( ! ParameterCollection | | ParameterIndex = = - 1 )
{
return INDEX_NONE ;
}
// Collect names of all parameters
TArray < FName > ParameterNames ;
ParameterCollection - > GetParameterNames ( ParameterNames , /*bVectorParameters=*/ false ) ;
int32 NumScalarParameters = ParameterNames . Num ( ) ;
ParameterCollection - > GetParameterNames ( ParameterNames , /*bVectorParameters=*/ true ) ;
// Find a parameter corresponding to ParameterIndex/ComponentIndex pair
int32 Index ;
for ( Index = 0 ; Index < ParameterNames . Num ( ) ; Index + + )
{
FGuid ParameterId = ParameterCollection - > GetParameterId ( ParameterNames [ Index ] ) ;
int32 CheckParameterIndex , CheckComponentIndex ;
ParameterCollection - > GetParameterIndex ( ParameterId , CheckParameterIndex , CheckComponentIndex ) ;
if ( CheckParameterIndex = = ParameterIndex & & CheckComponentIndex = = ComponentIndex )
{
// Found
break ;
}
}
if ( Index > = ParameterNames . Num ( ) )
{
// Not found, should not happen
return INDEX_NONE ;
}
// Create code for parameter
if ( Index < NumScalarParameters )
{
const FCollectionScalarParameter * ScalarParameter = ParameterCollection - > GetScalarParameterByName ( ParameterNames [ Index ] ) ;
check ( ScalarParameter ) ;
return Constant ( ScalarParameter - > DefaultValue ) ;
}
else
{
const FCollectionVectorParameter * VectorParameter = ParameterCollection - > GetVectorParameterByName ( ParameterNames [ Index ] ) ;
check ( VectorParameter ) ;
const FLinearColor & Color = VectorParameter - > DefaultValue ;
return Constant4 ( Color . R , Color . G , Color . B , Color . A ) ;
}
2015-05-11 07:08:08 -04:00
}
2015-08-05 23:29:49 -04:00
2019-09-14 09:45:25 -04:00
virtual EMaterialCompilerType GetCompilerType ( ) const override { return EMaterialCompilerType : : MaterialProxy ; }
2015-05-11 07:08:08 -04:00
} ;
2015-04-29 22:39:01 -04:00
class FExportMaterialProxy : public FMaterial , public FMaterialRenderProxy
{
public :
FExportMaterialProxy ( )
: FMaterial ( )
2021-10-12 21:21:22 -04:00
, FMaterialRenderProxy ( TEXT ( " FExportMaterialProxy " ) )
2015-04-29 22:39:01 -04:00
{
2020-09-01 14:07:48 -04:00
SetQualityLevelProperties ( GMaxRHIFeatureLevel ) ;
2015-04-29 22:39:01 -04:00
}
FExportMaterialProxy ( UMaterialInterface * InMaterialInterface , EMaterialProperty InPropertyToCompile )
: FMaterial ( )
2021-10-12 21:21:22 -04:00
, FMaterialRenderProxy ( GetPathNameSafe ( InMaterialInterface - > GetMaterial ( ) ) )
2015-04-29 22:39:01 -04:00
, MaterialInterface ( InMaterialInterface )
, PropertyToCompile ( InPropertyToCompile )
{
2020-09-01 14:07:48 -04:00
SetQualityLevelProperties ( GMaxRHIFeatureLevel ) ;
2015-04-29 22:39:01 -04:00
Material = InMaterialInterface - > GetMaterial ( ) ;
2020-02-06 13:13:41 -05:00
ReferencedTextures = InMaterialInterface - > GetReferencedTextures ( ) ;
2015-04-29 22:39:01 -04:00
FPlatformMisc : : CreateGuid ( Id ) ;
FMaterialResource * Resource = InMaterialInterface - > GetMaterialResource ( GMaxRHIFeatureLevel ) ;
FMaterialShaderMapId ResourceId ;
2020-04-23 14:34:23 -04:00
Resource - > GetShaderMapId ( GMaxRHIShaderPlatform , nullptr , ResourceId ) ;
2015-05-04 16:32:50 -04:00
{
TArray < FShaderType * > ShaderTypes ;
TArray < FVertexFactoryType * > VFTypes ;
2015-10-31 10:55:13 -04:00
TArray < const FShaderPipelineType * > ShaderPipelineTypes ;
2021-03-03 16:56:02 -04:00
GetDependentShaderAndVFTypes ( GMaxRHIShaderPlatform , ResourceId . LayoutParams , ShaderTypes , ShaderPipelineTypes , VFTypes ) ;
2015-05-04 16:32:50 -04:00
// Overwrite the shader map Id's dependencies with ones that came from the FMaterial actually being compiled (this)
2019-05-06 06:04:18 -04:00
// This is necessary as we change FMaterial attributes like GetShadingModels(), which factor into the ShouldCache functions that determine dependent shader types
2018-09-11 14:44:10 -04:00
ResourceId . SetShaderDependencies ( ShaderTypes , ShaderPipelineTypes , VFTypes , GMaxRHIShaderPlatform ) ;
2015-05-04 16:32:50 -04:00
}
2015-04-29 22:39:01 -04:00
// Override with a special usage so we won't re-use the shader map used by the material for rendering
switch ( InPropertyToCompile )
{
case MP_BaseColor : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportBaseColor ; break ;
case MP_Specular : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportSpecular ; break ;
case MP_Normal : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportNormal ; break ;
2020-02-12 13:27:19 -05:00
case MP_Tangent : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportTangent ; break ;
2015-04-29 22:39:01 -04:00
case MP_Metallic : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportMetallic ; break ;
case MP_Roughness : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportRoughness ; break ;
2020-02-12 13:27:19 -05:00
case MP_Anisotropy : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportAnisotropy ; break ;
2015-09-24 09:04:18 -04:00
case MP_AmbientOcclusion : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportAO ; break ;
2015-10-30 17:41:13 -04:00
case MP_EmissiveColor : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportEmissive ; break ;
2015-11-12 18:11:48 -05:00
case MP_Opacity : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportOpacity ; break ;
2017-09-30 03:42:01 -04:00
case MP_OpacityMask : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportOpacity ; break ;
2015-11-12 18:11:48 -05:00
case MP_SubsurfaceColor : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportSubSurfaceColor ; break ;
2015-10-30 17:41:13 -04:00
default :
ensureMsgf ( false , TEXT ( " ExportMaterial has no usage for property %i. Will likely reuse the normal rendering shader and crash later with a parameter mismatch " ) , ( int32 ) InPropertyToCompile ) ;
break ;
2015-04-29 22:39:01 -04:00
} ;
2020-02-06 13:13:41 -05:00
CacheShaders ( ResourceId , GMaxRHIShaderPlatform ) ;
2015-04-29 22:39:01 -04:00
}
2017-06-21 10:25:35 -04:00
virtual bool IsUsedWithStaticLighting ( ) const { return true ; }
2015-04-29 22:39:01 -04:00
/** This override is required otherwise the shaders aren't ready for use when the surface is rendered resulting in a blank image */
virtual bool RequiresSynchronousCompilation ( ) const override { return true ; } ;
/**
* Should the shader for this material with the given platform, shader type and vertex
* factory type combination be compiled
*
* @param Platform The platform currently being compiled for
* @param ShaderType Which shader is being compiled
* @param VertexFactory Which vertex factory is being compiled (can be NULL)
*
* @return true if the shader should be compiled
*/
virtual bool ShouldCache ( EShaderPlatform Platform , const FShaderType * ShaderType , const FVertexFactoryType * VertexFactoryType ) const override
{
// Always cache - decreases performance but avoids missing shaders during exports.
return true ;
}
2021-06-07 11:35:07 -04:00
virtual TArrayView < const TObjectPtr < UObject > > GetReferencedTextures ( ) const override
2015-04-29 22:39:01 -04:00
{
return ReferencedTextures ;
}
////////////////
// FMaterialRenderProxy interface.
2020-10-22 19:19:16 -04:00
virtual const FMaterial * GetMaterialNoFallback ( ERHIFeatureLevel : : Type InFeatureLevel ) const override
2015-04-29 22:39:01 -04:00
{
2020-10-22 19:19:16 -04:00
if ( GetRenderingThreadShaderMap ( ) )
2015-04-29 22:39:01 -04:00
{
2020-10-22 19:19:16 -04:00
return this ;
2015-04-29 22:39:01 -04:00
}
2020-10-22 19:19:16 -04:00
return nullptr ;
}
virtual const FMaterialRenderProxy * GetFallback ( ERHIFeatureLevel : : Type InFeatureLevel ) const override
{
return UMaterial : : GetDefaultMaterial ( MD_Surface ) - > GetRenderProxy ( ) ;
2015-04-29 22:39:01 -04:00
}
2021-08-31 17:38:39 -04:00
virtual bool GetParameterValue ( EMaterialParameterType Type , const FHashedMaterialParameterInfo & ParameterInfo , FMaterialParameterValue & OutValue , const FMaterialRenderContext & Context ) const override
2015-04-29 22:39:01 -04:00
{
2021-08-31 17:38:39 -04:00
return MaterialInterface - > GetRenderProxy ( ) - > GetParameterValue ( Type , ParameterInfo , OutValue , Context ) ;
2019-09-06 18:57:30 -04:00
}
2015-04-29 22:39:01 -04:00
// Material properties.
/** Entry point for compiling a specific material property. This must call SetMaterialProperty. */
virtual int32 CompilePropertyAndSetMaterialProperty ( EMaterialProperty Property , FMaterialCompiler * Compiler , EShaderFrequency OverrideShaderFrequency , bool bUsePreviousFrameTime ) const override
{
// needs to be called in this function!!
Compiler - > SetMaterialProperty ( Property , OverrideShaderFrequency , bUsePreviousFrameTime ) ;
int32 Ret = CompilePropertyAndSetMaterialPropertyWithoutCast ( Property , Compiler ) ;
2019-11-07 13:44:43 -05:00
return Compiler - > ForceCast ( Ret , FMaterialAttributeDefinitionMap : : GetValueType ( Property ) , MFCF_ExactMatch | MFCF_ReplicateValue ) ;
2015-04-29 22:39:01 -04:00
}
/** helper for CompilePropertyAndSetMaterialProperty() */
int32 CompilePropertyAndSetMaterialPropertyWithoutCast ( EMaterialProperty Property , FMaterialCompiler * Compiler ) const
{
2017-06-21 10:25:35 -04:00
if ( Property = = MP_EmissiveColor | | Property = = MP_SubsurfaceColor )
2015-04-29 22:39:01 -04:00
{
2022-12-13 10:44:43 -05:00
const bool bIsOpaqueOrMasked = IsOpaqueOrMaskedBlendMode ( * MaterialInterface ) ;
2015-04-29 22:39:01 -04:00
UMaterial * ProxyMaterial = MaterialInterface - > GetMaterial ( ) ;
2015-05-11 07:08:08 -04:00
check ( ProxyMaterial ) ;
FExportMaterialCompiler ProxyCompiler ( Compiler ) ;
2016-10-20 20:09:22 -04:00
const uint32 ForceCast_Exact_Replicate = MFCF_ForceCast | MFCF_ExactMatch | MFCF_ReplicateValue ;
2015-05-11 07:08:08 -04:00
2015-04-29 22:39:01 -04:00
switch ( PropertyToCompile )
{
case MP_EmissiveColor :
// Emissive is ALWAYS returned...
2016-10-20 20:09:22 -04:00
return MaterialInterface - > CompileProperty ( & ProxyCompiler , MP_EmissiveColor , ForceCast_Exact_Replicate ) ;
2015-04-29 22:39:01 -04:00
case MP_BaseColor :
2017-06-21 10:25:35 -04:00
// Only return for Opaque and Masked...
2022-12-13 10:44:43 -05:00
if ( bIsOpaqueOrMasked )
2017-06-21 10:25:35 -04:00
{
2017-03-24 09:53:37 -04:00
return MaterialInterface - > CompileProperty ( & ProxyCompiler , MP_BaseColor , ForceCast_Exact_Replicate ) ;
2017-06-21 10:25:35 -04:00
}
2015-04-29 22:39:01 -04:00
break ;
case MP_Specular :
case MP_Roughness :
2020-02-12 13:27:19 -05:00
case MP_Anisotropy :
2015-04-29 22:39:01 -04:00
case MP_Metallic :
2015-09-24 09:04:18 -04:00
case MP_AmbientOcclusion :
2017-06-21 10:25:35 -04:00
case MP_SubsurfaceColor :
2015-04-29 22:39:01 -04:00
// Only return for Opaque and Masked...
2022-12-13 10:44:43 -05:00
if ( bIsOpaqueOrMasked )
2015-04-29 22:39:01 -04:00
{
2016-10-20 20:09:22 -04:00
return MaterialInterface - > CompileProperty ( & ProxyCompiler , PropertyToCompile , ForceCast_Exact_Replicate ) ;
2015-04-29 22:39:01 -04:00
}
break ;
case MP_Normal :
2020-02-12 13:27:19 -05:00
case MP_Tangent :
2015-04-29 22:39:01 -04:00
// Only return for Opaque and Masked...
2022-12-13 10:44:43 -05:00
if ( bIsOpaqueOrMasked )
2015-04-29 22:39:01 -04:00
{
2016-10-20 20:09:22 -04:00
return Compiler - > Add (
2020-02-12 13:27:19 -05:00
Compiler - > Mul ( MaterialInterface - > CompileProperty ( & ProxyCompiler , PropertyToCompile , ForceCast_Exact_Replicate ) , Compiler - > Constant ( 0.5f ) ) , // [-1,1] * 0.5
2016-10-20 20:09:22 -04:00
Compiler - > Constant ( 0.5f ) ) ; // [-0.5,0.5] + 0.5
2015-04-29 22:39:01 -04:00
}
break ;
2019-05-07 06:36:48 -04:00
case MP_ShadingModel :
return MaterialInterface - > CompileProperty ( & ProxyCompiler , MP_ShadingModel ) ;
2022-12-01 14:52:03 -05:00
case MP_SurfaceThickness :
return MaterialInterface - > CompileProperty ( & ProxyCompiler , MP_SurfaceThickness ) ;
2020-10-08 03:11:37 -04:00
case MP_FrontMaterial :
return MaterialInterface - > CompileProperty ( & ProxyCompiler , MP_FrontMaterial ) ;
2015-04-29 22:39:01 -04:00
default :
return Compiler - > Constant ( 1.0f ) ;
}
return Compiler - > Constant ( 0.0f ) ;
}
2023-04-11 16:48:54 -04:00
else if ( Property = = MP_WorldPositionOffset | | Property = = MP_Displacement )
2015-04-29 22:39:01 -04:00
{
//This property MUST return 0 as a default or during the process of rendering textures out for lightmass to use, pixels will be off by 1.
return Compiler - > Constant ( 0.0f ) ;
}
else if ( Property > = MP_CustomizedUVs0 & & Property < = MP_CustomizedUVs7 )
{
// Pass through customized UVs
return MaterialInterface - > CompileProperty ( Compiler , Property ) ;
}
2019-05-07 06:36:48 -04:00
else if ( Property = = MP_ShadingModel )
{
return MaterialInterface - > CompileProperty ( Compiler , MP_ShadingModel ) ;
}
2022-12-01 14:52:03 -05:00
else if ( Property = = MP_SurfaceThickness )
{
return MaterialInterface - > CompileProperty ( Compiler , MP_SurfaceThickness ) ;
}
2020-10-08 03:11:37 -04:00
else if ( Property = = MP_FrontMaterial )
{
return MaterialInterface - > CompileProperty ( Compiler , MP_FrontMaterial ) ;
}
2015-04-29 22:39:01 -04:00
else
{
return Compiler - > Constant ( 1.0f ) ;
}
}
virtual FString GetMaterialUsageDescription ( ) const override
{
2017-03-24 09:53:37 -04:00
return FString : : Printf ( TEXT ( " ExportMaterialRenderer %s " ) , MaterialInterface ? * MaterialInterface - > GetName ( ) : TEXT ( " NULL " ) ) ;
2015-04-29 22:39:01 -04:00
}
2017-03-21 17:46:52 -04:00
virtual EMaterialDomain GetMaterialDomain ( ) const override
2015-04-29 22:39:01 -04:00
{
if ( Material )
{
return Material - > MaterialDomain ;
}
return MD_Surface ;
}
virtual bool IsTwoSided ( ) const override
{
if ( MaterialInterface )
{
return MaterialInterface - > IsTwoSided ( ) ;
}
return false ;
}
2022-11-30 02:10:42 -05:00
virtual bool IsThinSurface ( ) const override
{
if ( MaterialInterface )
{
return MaterialInterface - > IsThinSurface ( ) ;
}
return false ;
}
2015-04-29 22:39:01 -04:00
virtual bool IsDitheredLODTransition ( ) const override
{
if ( MaterialInterface )
{
return MaterialInterface - > IsDitheredLODTransition ( ) ;
}
return false ;
}
virtual bool IsLightFunction ( ) const override
{
if ( Material )
{
return ( Material - > MaterialDomain = = MD_LightFunction ) ;
}
return false ;
}
2016-06-27 13:42:20 -04:00
virtual bool IsDeferredDecal ( ) const override
2015-04-29 22:39:01 -04:00
{
2016-06-27 13:42:20 -04:00
return Material & & Material - > MaterialDomain = = MD_DeferredDecal ;
2015-04-29 22:39:01 -04:00
}
virtual bool IsSpecialEngineMaterial ( ) const override
{
if ( Material )
{
return ( Material - > bUsedAsSpecialEngineMaterial = = 1 ) ;
}
2017-06-21 10:25:35 -04:00
return true ;
2015-04-29 22:39:01 -04:00
}
virtual bool IsWireframe ( ) const override
{
if ( Material )
{
return ( Material - > Wireframe = = 1 ) ;
}
return false ;
}
2019-05-06 06:04:18 -04:00
virtual bool IsMasked ( ) const override { return false ; }
virtual enum EBlendMode GetBlendMode ( ) const override { return BLEND_Opaque ; }
2022-12-02 03:49:35 -05:00
virtual enum ERefractionMode GetRefractionMode ( ) const override { return Material ? ( ERefractionMode ) Material - > RefractionMethod : RM_None ; }
virtual bool GetRootNodeOverridesDefaultRefraction ( ) const override { return Material ? Material - > bRootNodeOverridesDefaultDistortion : false ; }
2019-05-06 06:04:18 -04:00
virtual FMaterialShadingModelField GetShadingModels ( ) const override { return MSM_Unlit ; }
2019-06-08 23:02:14 -04:00
virtual bool IsShadingModelFromMaterialExpression ( ) const override { return false ; }
2019-05-06 06:04:18 -04:00
virtual float GetOpacityMaskClipValue ( ) const override { return 0.5f ; }
virtual bool GetCastDynamicShadowAsMasked ( ) const override { return false ; }
2015-04-29 22:39:01 -04:00
virtual FString GetFriendlyName ( ) const override { return FString : : Printf ( TEXT ( " FExportMaterialRenderer %s " ) , MaterialInterface ? * MaterialInterface - > GetName ( ) : TEXT ( " NULL " ) ) ; }
/**
* Should shaders compiled for this material be saved to disk?
*/
virtual bool IsPersistent ( ) const override { return false ; }
virtual FGuid GetMaterialId ( ) const override { return Id ; }
2016-12-12 17:47:42 -05:00
virtual UMaterialInterface * GetMaterialInterface ( ) const override
2015-04-29 22:39:01 -04:00
{
return MaterialInterface ;
}
friend FArchive & operator < < ( FArchive & Ar , FExportMaterialProxy & V )
{
return Ar < < V . MaterialInterface ;
}
2022-12-14 14:47:58 -05:00
static bool WillFillData ( bool bIsOpaque , EMaterialProperty InMaterialProperty )
2015-04-29 22:39:01 -04:00
{
if ( InMaterialProperty = = MP_EmissiveColor )
{
return true ;
}
2022-12-14 14:47:58 -05:00
if ( bIsOpaque )
2015-04-29 22:39:01 -04:00
{
2022-12-14 14:47:58 -05:00
switch ( InMaterialProperty )
2015-04-29 22:39:01 -04:00
{
2022-12-14 14:47:58 -05:00
case MP_BaseColor : return true ;
case MP_Specular : return true ;
case MP_Normal : return true ;
case MP_Tangent : return true ;
case MP_Metallic : return true ;
case MP_Roughness : return true ;
case MP_Anisotropy : return true ;
case MP_AmbientOcclusion : return true ;
2015-04-29 22:39:01 -04:00
}
}
return false ;
}
2017-06-21 10:25:35 -04:00
virtual bool IsVolumetricPrimitive ( ) const override
{
2017-09-30 03:42:01 -04:00
return Material & & Material - > MaterialDomain = = MD_Volume ;
2017-06-21 10:25:35 -04:00
}
2019-07-16 09:48:17 -04:00
virtual void GatherExpressionsForCustomInterpolators ( TArray < UMaterialExpression * > & OutExpressions ) const override
{
if ( Material )
{
Material - > GetAllExpressionsForCustomInterpolators ( OutExpressions ) ;
}
}
2023-01-13 05:36:38 -05:00
virtual bool CheckInValidStateForCompilation ( class FMaterialCompiler * Compiler ) const override
{
return Material & & Material - > CheckInValidStateForCompilation ( Compiler ) ;
}
2015-04-29 22:39:01 -04:00
private :
/** The material interface for this proxy */
UMaterialInterface * MaterialInterface ;
UMaterial * Material ;
2021-06-07 11:35:07 -04:00
TArray < TObjectPtr < UObject > > ReferencedTextures ;
2015-04-29 22:39:01 -04:00
/** The property to compile for rendering the sample */
EMaterialProperty PropertyToCompile ;
FGuid Id ;
} ;
2022-02-14 12:01:24 -05:00
/**
* Render the scene to the provided canvas. Will potentially perform the render multiple times, depending on the value of
* the CVarMaterialUtilitiesWarmupFrames CVar. This is needed to ensure various rendering systems are primed properly before capturing
* the scene.
*/
static void PerformSceneRender ( FCanvas & Canvas , FSceneViewFamily & ViewFamily , bool bWithWarmup )
{
if ( bWithWarmup )
{
for ( int32 i = 0 ; i < CVarMaterialUtilitiesWarmupFrames . GetValueOnGameThread ( ) ; i + + )
{
GetRendererModule ( ) . BeginRenderingViewFamily ( & Canvas , & ViewFamily ) ;
}
}
GetRendererModule ( ) . BeginRenderingViewFamily ( & Canvas , & ViewFamily ) ;
}
2015-04-29 22:39:01 -04:00
static void RenderSceneToTexture (
2022-02-14 12:01:24 -05:00
FSceneInterface * Scene ,
const FName & VisualizationMode ,
const FVector & ViewOrigin ,
const FMatrix & ViewRotationMatrix ,
const FMatrix & ProjectionMatrix ,
const TSet < FPrimitiveComponentId > & ShowOnlyPrimitives ,
const TSet < FPrimitiveComponentId > & HiddenPrimitives ,
FIntPoint TargetSize ,
float TargetGamma ,
bool bPerformWarmpup ,
TArray < FColor > & OutSamples )
2015-04-29 22:39:01 -04:00
{
auto RenderTargetTexture = NewObject < UTextureRenderTarget2D > ( ) ;
check ( RenderTargetTexture ) ;
RenderTargetTexture - > AddToRoot ( ) ;
RenderTargetTexture - > ClearColor = FLinearColor : : Transparent ;
RenderTargetTexture - > TargetGamma = TargetGamma ;
RenderTargetTexture - > InitCustomFormat ( TargetSize . X , TargetSize . Y , PF_FloatRGBA , false ) ;
FTextureRenderTargetResource * RenderTargetResource = RenderTargetTexture - > GameThread_GetRenderTargetResource ( ) ;
FSceneViewFamilyContext ViewFamily (
FSceneViewFamily : : ConstructionValues ( RenderTargetResource , Scene , FEngineShowFlags ( ESFIM_Game ) )
2021-12-02 23:53:56 -05:00
. SetTime ( FGameTime : : GetTimeSinceAppStart ( ) )
2015-04-29 22:39:01 -04:00
) ;
// To enable visualization mode
ViewFamily . EngineShowFlags . SetPostProcessing ( true ) ;
ViewFamily . EngineShowFlags . SetVisualizeBuffer ( true ) ;
ViewFamily . EngineShowFlags . SetTonemapper ( false ) ;
2017-11-16 11:36:35 -05:00
ViewFamily . EngineShowFlags . SetScreenPercentage ( false ) ;
2015-04-29 22:39:01 -04:00
FSceneViewInitOptions ViewInitOptions ;
ViewInitOptions . SetViewRectangle ( FIntRect ( 0 , 0 , TargetSize . X , TargetSize . Y ) ) ;
ViewInitOptions . ViewFamily = & ViewFamily ;
ViewInitOptions . ViewOrigin = ViewOrigin ;
ViewInitOptions . ViewRotationMatrix = ViewRotationMatrix ;
ViewInitOptions . ProjectionMatrix = ProjectionMatrix ;
2022-02-24 23:17:38 -05:00
// If no "show only" primitives are provided, we must pass an unset TOptional - otherwise an empty set will mean no primitive should be visible.
ViewInitOptions . ShowOnlyPrimitives = ! ShowOnlyPrimitives . IsEmpty ( ) ? TOptional < TSet < FPrimitiveComponentId > > ( ShowOnlyPrimitives ) : TOptional < TSet < FPrimitiveComponentId > > ( ) ;
ViewInitOptions . HiddenPrimitives = HiddenPrimitives ;
2015-04-29 22:39:01 -04:00
FSceneView * NewView = new FSceneView ( ViewInitOptions ) ;
NewView - > CurrentBufferVisualizationMode = VisualizationMode ;
ViewFamily . Views . Add ( NewView ) ;
2017-11-16 11:36:35 -05:00
ViewFamily . SetScreenPercentageInterface ( new FLegacyScreenPercentageDriver (
2021-07-14 08:25:29 -04:00
ViewFamily , /* GlobalResolutionFraction = */ 1.0f ) ) ;
2017-11-16 11:36:35 -05:00
2021-12-02 23:53:56 -05:00
FCanvas Canvas ( RenderTargetResource , NULL , FGameTime : : GetTimeSinceAppStart ( ) , Scene - > GetFeatureLevel ( ) ) ;
2015-04-29 22:39:01 -04:00
Canvas . Clear ( FLinearColor : : Transparent ) ;
2021-12-08 11:38:32 -05:00
ViewFamily . ViewExtensions = GEngine - > ViewExtensions - > GatherActiveExtensions ( FSceneViewExtensionContext ( Scene ) ) ;
for ( const FSceneViewExtensionRef & Extension : ViewFamily . ViewExtensions )
{
Extension - > SetupViewFamily ( ViewFamily ) ;
Extension - > SetupView ( ViewFamily , * NewView ) ;
}
2022-02-14 12:01:24 -05:00
PerformSceneRender ( Canvas , ViewFamily , bPerformWarmpup ) ;
2015-04-29 22:39:01 -04:00
// Copy the contents of the remote texture to system memory
OutSamples . SetNumUninitialized ( TargetSize . X * TargetSize . Y ) ;
FReadSurfaceDataFlags ReadSurfaceDataFlags ;
ReadSurfaceDataFlags . SetLinearToGamma ( false ) ;
RenderTargetResource - > ReadPixelsPtr ( OutSamples . GetData ( ) , ReadSurfaceDataFlags , FIntRect ( 0 , 0 , TargetSize . X , TargetSize . Y ) ) ;
RenderTargetTexture - > RemoveFromRoot ( ) ;
RenderTargetTexture = nullptr ;
}
2022-02-14 12:01:24 -05:00
static void RenderSceneToTextures (
FSceneInterface * Scene ,
const FVector & ViewOrigin ,
const FMatrix & ViewRotationMatrix ,
const FMatrix & ProjectionMatrix ,
const TSet < FPrimitiveComponentId > & ShowOnlyPrimitives ,
const TSet < FPrimitiveComponentId > & HiddenPrimitives ,
FFlattenMaterial & OutFlattenMaterial )
{
TMap < EFlattenMaterialProperties , TPair < FName , float > > SupportedProperties ; // Property -> VisualisationMode|Gamma
SupportedProperties . Add ( EFlattenMaterialProperties : : Diffuse ) = TPair < FName , float > ( FName ( " BaseColor " ) , true ) ; // BaseColor to gamma space
SupportedProperties . Add ( EFlattenMaterialProperties : : Normal ) = TPair < FName , float > ( FName ( " WorldNormal " ) , false ) ; // Dump normal texture in linear space
SupportedProperties . Add ( EFlattenMaterialProperties : : Metallic ) = TPair < FName , float > ( FName ( " Metallic " ) , false ) ; // Dump metallic texture in linear space
SupportedProperties . Add ( EFlattenMaterialProperties : : Roughness ) = TPair < FName , float > ( FName ( " Roughness " ) , true ) ; // Roughness material powers color by 2.2, transform it back to linear
SupportedProperties . Add ( EFlattenMaterialProperties : : Specular ) = TPair < FName , float > ( FName ( " Specular " ) , false ) ; // Dump specular texture in linear space
bool bPerformWarmpup = true ;
for ( int32 PropertyIndex = 0 ; PropertyIndex < ( int32 ) EFlattenMaterialProperties : : NumFlattenMaterialProperties ; + + PropertyIndex )
{
const EFlattenMaterialProperties Property = ( EFlattenMaterialProperties ) PropertyIndex ;
if ( OutFlattenMaterial . ShouldGenerateDataForProperty ( Property ) )
{
TPair < FName , float > * PropertyInfo = SupportedProperties . Find ( Property ) ;
if ( PropertyInfo )
{
TArray < FColor > & Samples = OutFlattenMaterial . GetPropertySamples ( Property ) ;
const FIntPoint & Size = OutFlattenMaterial . GetPropertySize ( Property ) ;
const FName VisModeName = PropertyInfo - > Key ;
const float Gamma = PropertyInfo - > Value ? 2.2f : 1.0f ;
RenderSceneToTexture ( Scene , VisModeName , ViewOrigin , ViewRotationMatrix , ProjectionMatrix , ShowOnlyPrimitives , HiddenPrimitives , Size , Gamma , bPerformWarmpup , Samples ) ;
bPerformWarmpup = false ; // Perform warmup only on first render
}
else
{
UE_LOG ( LogMaterialUtilities , Error , TEXT ( " RenderSceneToTextures - Ignoring unsupported property " ) ) ;
}
}
}
}
2021-04-05 14:19:15 -04:00
FIntPoint FMaterialUtilities : : FindMaxTextureSize ( UMaterialInterface * InMaterialInterface , FIntPoint MinimumSize )
{
// static lod settings so that we only initialize them once
UTextureLODSettings * GameTextureLODSettings = UDeviceProfileManager : : Get ( ) . GetActiveProfile ( ) - > GetTextureLODSettings ( ) ;
2015-10-28 19:18:20 -04:00
2021-04-05 14:19:15 -04:00
TArray < UTexture * > MaterialTextures ;
InMaterialInterface - > GetUsedTextures ( MaterialTextures , EMaterialQualityLevel : : Num , false , GMaxRHIFeatureLevel , false ) ;
FTextureCompilingManager : : Get ( ) . FinishCompilation ( MaterialTextures ) ;
// find the largest texture in the list (applying it's LOD bias)
FIntPoint MaxSize = MinimumSize ;
for ( int32 TexIndex = 0 ; TexIndex < MaterialTextures . Num ( ) ; TexIndex + + )
{
UTexture * Texture = MaterialTextures [ TexIndex ] ;
if ( Texture = = NULL )
{
continue ;
}
// get the max size of the texture
FIntPoint LocalSize ( 0 , 0 ) ;
if ( Texture - > IsA ( UTexture2D : : StaticClass ( ) ) )
{
UTexture2D * Tex2D = ( UTexture2D * ) Texture ;
LocalSize = FIntPoint ( Tex2D - > GetSizeX ( ) , Tex2D - > GetSizeY ( ) ) ;
}
else if ( Texture - > IsA ( UTextureCube : : StaticClass ( ) ) )
{
UTextureCube * TexCube = ( UTextureCube * ) Texture ;
LocalSize = FIntPoint ( TexCube - > GetSizeX ( ) , TexCube - > GetSizeY ( ) ) ;
}
else if ( Texture - > IsA ( UTexture2DArray : : StaticClass ( ) ) )
{
UTexture2DArray * TexArray = ( UTexture2DArray * ) Texture ;
LocalSize = FIntPoint ( TexArray - > GetSizeX ( ) , TexArray - > GetSizeY ( ) ) ;
}
int32 LocalBias = GameTextureLODSettings - > CalculateLODBias ( Texture ) ;
// bias the texture size based on LOD group
FIntPoint BiasedLocalSize ( LocalSize . X > > LocalBias , LocalSize . Y > > LocalBias ) ;
MaxSize . X = FMath : : Max ( BiasedLocalSize . X , MaxSize . X ) ;
MaxSize . Y = FMath : : Max ( BiasedLocalSize . Y , MaxSize . Y ) ;
}
return MaxSize ;
}
2015-10-28 19:18:20 -04:00
2022-12-14 14:47:58 -05:00
bool FMaterialUtilities : : SupportsExport ( bool bIsOpaque , EMaterialProperty InMaterialProperty )
2015-04-29 22:39:01 -04:00
{
2022-12-14 14:47:58 -05:00
return FExportMaterialProxy : : WillFillData ( bIsOpaque , InMaterialProperty ) ;
2015-04-29 22:39:01 -04:00
}
2023-01-24 02:15:00 -05:00
bool FMaterialUtilities : : SupportsExport ( EBlendMode InBlendMode , EMaterialProperty InMaterialProperty )
{
return FExportMaterialProxy : : WillFillData ( IsOpaqueBlendMode ( InBlendMode ) , InMaterialProperty ) ;
}
2022-02-14 12:01:24 -05:00
static bool ExportLandscapeMaterial ( const ALandscapeProxy * InLandscape , const TSet < FPrimitiveComponentId > & ShowOnlyPrimitives , const TSet < FPrimitiveComponentId > & HiddenPrimitives , FFlattenMaterial & OutFlattenMaterial )
2015-04-29 22:39:01 -04:00
{
check ( InLandscape ) ;
FIntRect LandscapeRect = InLandscape - > GetBoundingRect ( ) ;
FVector MidPoint = FVector ( LandscapeRect . Min , 0.f ) + FVector ( LandscapeRect . Size ( ) , 0.f ) * 0.5f ;
FVector LandscapeCenter = InLandscape - > GetTransform ( ) . TransformPosition ( MidPoint ) ;
FVector LandscapeExtent = FVector ( LandscapeRect . Size ( ) , 0.f ) * InLandscape - > GetActorScale ( ) * 0.5f ;
FVector ViewOrigin = LandscapeCenter ;
FMatrix ViewRotationMatrix = FInverseRotationMatrix ( InLandscape - > GetActorRotation ( ) ) ;
ViewRotationMatrix * = FMatrix ( FPlane ( 1 , 0 , 0 , 0 ) ,
FPlane ( 0 , - 1 , 0 , 0 ) ,
FPlane ( 0 , 0 , - 1 , 0 ) ,
FPlane ( 0 , 0 , 0 , 1 ) ) ;
2022-06-09 07:03:13 -04:00
const FMatrix : : FReal ZOffset = UE_OLD_WORLD_MAX ;
2015-04-29 22:39:01 -04:00
FMatrix ProjectionMatrix = FReversedZOrthoMatrix (
LandscapeExtent . X ,
LandscapeExtent . Y ,
0.5f / ZOffset ,
ZOffset ) ;
FSceneInterface * Scene = InLandscape - > GetWorld ( ) - > Scene ;
2022-02-14 12:01:24 -05:00
RenderSceneToTextures ( Scene , ViewOrigin , ViewRotationMatrix , ProjectionMatrix , ShowOnlyPrimitives , HiddenPrimitives , OutFlattenMaterial ) ;
2015-04-29 22:39:01 -04:00
OutFlattenMaterial . MaterialId = InLandscape - > GetLandscapeGuid ( ) ;
return true ;
}
2022-02-14 12:01:24 -05:00
bool FMaterialUtilities : : ExportLandscapeMaterial ( const ALandscapeProxy * InLandscape , FFlattenMaterial & OutFlattenMaterial )
{
2023-05-04 11:35:05 -04:00
bool bExportSuccess = false ;
2022-02-14 12:01:24 -05:00
2023-05-04 11:35:05 -04:00
if ( InLandscape )
2022-02-14 12:01:24 -05:00
{
2023-05-04 11:35:05 -04:00
TSet < FPrimitiveComponentId > ShowOnlyPrimitives ;
// Include all landscape components scene proxies
for ( ULandscapeComponent * LandscapeComponent : InLandscape - > LandscapeComponents )
2022-02-14 12:01:24 -05:00
{
2023-05-04 11:35:05 -04:00
if ( LandscapeComponent & & LandscapeComponent - > SceneProxy )
{
ShowOnlyPrimitives . Add ( LandscapeComponent - > SceneProxy - > GetPrimitiveComponentId ( ) ) ;
}
2022-02-14 12:01:24 -05:00
}
2023-05-04 11:35:05 -04:00
// Include Nanite landscape scene proxy - these are the ones that are actually visible when rendering LS with Nanite support
2023-07-25 13:09:00 -04:00
if ( InLandscape - > HasNaniteComponents ( ) )
2023-05-04 11:35:05 -04:00
{
2023-07-25 13:09:00 -04:00
ShowOnlyPrimitives . Append ( InLandscape - > GetNanitePrimitiveComponentIds ( ) ) ;
2023-05-04 11:35:05 -04:00
}
bExportSuccess = : : ExportLandscapeMaterial ( InLandscape , ShowOnlyPrimitives , { } , OutFlattenMaterial ) ;
}
if ( ! bExportSuccess )
{
UE_LOG ( LogMaterialUtilities , Warning , TEXT ( " ExportLandscapeMaterial: Failed to export material for the provided ALandcapeProxy (%s) " ) , InLandscape ? * InLandscape - > GetName ( ) : TEXT ( " <null> " ) ) ;
2022-02-14 12:01:24 -05:00
}
2023-05-04 11:35:05 -04:00
return bExportSuccess ;
2022-02-14 12:01:24 -05:00
}
bool FMaterialUtilities : : ExportLandscapeMaterial ( const ALandscapeProxy * InLandscape , const TSet < FPrimitiveComponentId > & HiddenPrimitives , FFlattenMaterial & OutFlattenMaterial )
{
return : : ExportLandscapeMaterial ( InLandscape , { } , HiddenPrimitives , OutFlattenMaterial ) ;
}
2016-02-04 10:55:30 -05:00
UMaterial * FMaterialUtilities : : CreateMaterial ( const FFlattenMaterial & InFlattenMaterial , UPackage * InOuter , const FString & BaseName , EObjectFlags Flags , const struct FMaterialProxySettings & MaterialProxySettings , TArray < UObject * > & OutGeneratedAssets , const TextureGroup & InTextureGroup /*= TEXTUREGROUP_World*/ )
2015-04-29 22:39:01 -04:00
{
// Base name for a new assets
// In case outer is null BaseName has to be long package name
if ( InOuter = = nullptr & & FPackageName : : IsShortPackageName ( BaseName ) )
{
2015-04-30 02:24:37 -04:00
UE_LOG ( LogMaterialUtilities , Warning , TEXT ( " Invalid long package name: '%s'. " ) , * BaseName ) ;
2015-04-29 22:39:01 -04:00
return nullptr ;
}
const FString AssetBaseName = FPackageName : : GetShortName ( BaseName ) ;
2019-01-23 17:01:56 -05:00
const FString AssetBasePath = InOuter ? TEXT ( " " ) : FPackageName : : GetLongPackagePath ( BaseName ) ;
2015-04-29 22:39:01 -04:00
// Create material
const FString MaterialAssetName = TEXT ( " M_ " ) + AssetBaseName ;
UPackage * MaterialOuter = InOuter ;
if ( MaterialOuter = = NULL )
{
2020-09-24 00:43:27 -04:00
MaterialOuter = CreatePackage ( * ( AssetBasePath / MaterialAssetName ) ) ;
2015-04-29 22:39:01 -04:00
MaterialOuter - > FullyLoad ( ) ;
MaterialOuter - > Modify ( ) ;
}
UMaterial * Material = NewObject < UMaterial > ( MaterialOuter , FName ( * MaterialAssetName ) , Flags ) ;
Material - > TwoSided = false ;
2015-12-10 21:55:37 -05:00
Material - > DitheredLODTransition = InFlattenMaterial . bDitheredLODTransition ;
2015-04-29 22:39:01 -04:00
Material - > SetShadingModel ( MSM_DefaultLit ) ;
OutGeneratedAssets . Add ( Material ) ;
2022-05-04 12:21:52 -04:00
UMaterialEditorOnlyData * MaterialEditorOnly = Material - > GetEditorOnlyData ( ) ;
2015-04-29 22:39:01 -04:00
int32 MaterialNodeY = - 150 ;
int32 MaterialNodeStepY = 180 ;
// BaseColor
2016-09-22 15:33:34 -04:00
const TArray < FColor > & DiffuseSamples = InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Diffuse ) ;
if ( DiffuseSamples . Num ( ) > 1 )
2015-04-29 22:39:01 -04:00
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _D " ) ;
2019-01-23 17:01:56 -05:00
const FString AssetLongName = AssetBasePath / AssetName ;
2015-04-29 22:39:01 -04:00
const bool bSRGB = true ;
2016-09-22 15:33:34 -04:00
UTexture2D * Texture = CreateTexture ( InOuter , AssetLongName , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Diffuse ) , DiffuseSamples , TC_Default , InTextureGroup , Flags , bSRGB ) ;
2015-04-29 22:39:01 -04:00
OutGeneratedAssets . Add ( Texture ) ;
auto BasecolorExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
BasecolorExpression - > Texture = Texture ;
BasecolorExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_Color ;
BasecolorExpression - > MaterialExpressionEditorX = - 400 ;
BasecolorExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( BasecolorExpression ) ;
MaterialEditorOnly - > BaseColor . Expression = BasecolorExpression ;
2015-04-29 22:39:01 -04:00
2019-01-23 17:01:56 -05:00
MaterialNodeY + = MaterialNodeStepY ;
2015-04-29 22:39:01 -04:00
}
2016-09-22 15:33:34 -04:00
else if ( DiffuseSamples . Num ( ) = = 1 )
2015-10-28 19:18:20 -04:00
{
// Set Roughness to constant
2016-09-22 15:33:34 -04:00
FLinearColor BaseColor = FLinearColor ( DiffuseSamples [ 0 ] ) ;
2015-10-28 19:18:20 -04:00
auto BaseColorExpression = NewObject < UMaterialExpressionConstant4Vector > ( Material ) ;
2015-11-12 18:11:48 -05:00
BaseColorExpression - > Constant = BaseColor ;
2015-10-28 19:18:20 -04:00
BaseColorExpression - > MaterialExpressionEditorX = - 400 ;
BaseColorExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( BaseColorExpression ) ;
MaterialEditorOnly - > BaseColor . Expression = BaseColorExpression ;
2015-10-28 19:18:20 -04:00
MaterialNodeY + = MaterialNodeStepY ;
}
2015-09-24 09:04:18 -04:00
// Whether or not a material property is baked down
2016-09-22 15:33:34 -04:00
const bool bHasMetallic = InFlattenMaterial . DoesPropertyContainData ( EFlattenMaterialProperties : : Metallic ) & & ! InFlattenMaterial . IsPropertyConstant ( EFlattenMaterialProperties : : Metallic ) ;
const bool bHasSpecular = InFlattenMaterial . DoesPropertyContainData ( EFlattenMaterialProperties : : Specular ) & & ! InFlattenMaterial . IsPropertyConstant ( EFlattenMaterialProperties : : Specular ) ;
2022-02-17 13:52:22 -05:00
const bool bHasRoughness = InFlattenMaterial . DoesPropertyContainData ( EFlattenMaterialProperties : : Roughness ) & & ! InFlattenMaterial . IsPropertyConstant ( EFlattenMaterialProperties : : Roughness ) ;
2015-04-29 22:39:01 -04:00
2015-09-24 09:04:18 -04:00
// Number of material properties baked down to textures
const int BakedMaterialPropertyCount = bHasMetallic + bHasRoughness + bHasSpecular ;
// Check for same texture sizes
bool bSameTextureSize = true ;
2015-11-12 18:11:48 -05:00
int32 SampleCount = 0 ;
FIntPoint MergedSize ( 0 , 0 ) ;
2016-09-22 15:33:34 -04:00
for ( int32 PropertyIndex = 0 ; PropertyIndex < 3 ; + + PropertyIndex )
{
EFlattenMaterialProperties Property = ( EFlattenMaterialProperties ) ( PropertyIndex + ( int32 ) EFlattenMaterialProperties : : Metallic ) ;
const bool HasProperty = InFlattenMaterial . DoesPropertyContainData ( Property ) & & ! InFlattenMaterial . IsPropertyConstant ( Property ) ;
FIntPoint PropertySize = InFlattenMaterial . GetPropertySize ( Property ) ;
SampleCount = ( bHasMetallic & & SampleCount = = 0 ) ? InFlattenMaterial . GetPropertySamples ( Property ) . Num ( ) : SampleCount ;
MergedSize = ( bHasMetallic & & MergedSize . X = = 0 ) ? PropertySize : MergedSize ;
}
bSameTextureSize & = bHasMetallic ? ( SampleCount = = InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Metallic ) . Num ( ) ) : true ;
bSameTextureSize & = bHasSpecular ? ( SampleCount = = InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Specular ) . Num ( ) ) : true ;
2022-02-17 13:52:22 -05:00
bSameTextureSize & = bHasRoughness ? ( SampleCount = = InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Roughness ) . Num ( ) ) : true ;
2015-11-12 18:11:48 -05:00
2015-10-28 19:18:20 -04:00
// Merge values into one texture if more than one material property exists
2015-09-24 09:04:18 -04:00
if ( BakedMaterialPropertyCount > 1 & & bSameTextureSize )
{
2022-02-17 13:52:22 -05:00
// Metallic = R, Specular = G, Roughness = B
2015-09-24 09:04:18 -04:00
TArray < FColor > MergedSamples ;
MergedSamples . AddZeroed ( SampleCount ) ;
2016-10-06 12:11:11 -04:00
2016-09-22 15:33:34 -04:00
// R G B masks
const uint32 ColorMask [ 3 ] = { 0x00FF0000 , 0x0000FF00 , 0x000000FF } ;
2022-02-17 13:52:22 -05:00
2016-09-22 15:33:34 -04:00
for ( int32 PropertyIndex = 0 ; PropertyIndex < 3 ; + + PropertyIndex )
2015-09-24 09:04:18 -04:00
{
2016-09-22 15:33:34 -04:00
EFlattenMaterialProperties Property = ( EFlattenMaterialProperties ) ( PropertyIndex + ( int32 ) EFlattenMaterialProperties : : Metallic ) ;
const bool HasProperty = InFlattenMaterial . DoesPropertyContainData ( Property ) & & ! InFlattenMaterial . IsPropertyConstant ( Property ) ;
2016-10-06 12:11:11 -04:00
2016-09-22 15:33:34 -04:00
if ( HasProperty )
2019-01-23 17:01:56 -05:00
{
const TArray < FColor > & PropertySamples = InFlattenMaterial . GetPropertySamples ( Property ) ;
// OR masked values (samples initialized to zero, so no random data)
for ( int32 SampleIndex = 0 ; SampleIndex < SampleCount ; + + SampleIndex )
{
MergedSamples [ SampleIndex ] . DWColor ( ) | = ( PropertySamples [ SampleIndex ] . DWColor ( ) & ColorMask [ PropertyIndex ] ) ;
}
}
2015-09-24 09:04:18 -04:00
}
2022-02-17 13:52:22 -05:00
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _MSR " ) ;
2015-11-12 18:11:48 -05:00
const bool bSRGB = true ;
2019-01-23 17:01:56 -05:00
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath / AssetName , MergedSize , MergedSamples , TC_Default , InTextureGroup , Flags , bSRGB ) ;
2015-09-24 09:04:18 -04:00
OutGeneratedAssets . Add ( Texture ) ;
auto MergedExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
MergedExpression - > Texture = Texture ;
2015-11-12 18:11:48 -05:00
MergedExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_Color ;
2015-09-24 09:04:18 -04:00
MergedExpression - > MaterialExpressionEditorX = - 400 ;
MergedExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( MergedExpression ) ;
2015-09-24 09:04:18 -04:00
// Metallic
if ( bHasMetallic )
{
2022-05-04 12:21:52 -04:00
MaterialEditorOnly - > Metallic . Expression = MergedExpression ;
MaterialEditorOnly - > Metallic . Mask = MaterialEditorOnly - > Metallic . Expression - > GetOutputs ( ) [ 0 ] . Mask ;
MaterialEditorOnly - > Metallic . MaskR = 1 ;
MaterialEditorOnly - > Metallic . MaskG = 0 ;
MaterialEditorOnly - > Metallic . MaskB = 0 ;
MaterialEditorOnly - > Metallic . MaskA = 0 ;
2015-09-24 09:04:18 -04:00
}
// Specular
if ( bHasSpecular )
{
2022-05-04 12:21:52 -04:00
MaterialEditorOnly - > Specular . Expression = MergedExpression ;
MaterialEditorOnly - > Specular . Mask = MaterialEditorOnly - > Specular . Expression - > GetOutputs ( ) [ 0 ] . Mask ;
MaterialEditorOnly - > Specular . MaskR = 0 ;
MaterialEditorOnly - > Specular . MaskG = 1 ;
MaterialEditorOnly - > Specular . MaskB = 0 ;
MaterialEditorOnly - > Specular . MaskA = 0 ;
2015-09-24 09:04:18 -04:00
}
2022-02-17 13:52:22 -05:00
// Roughness
if ( bHasRoughness )
{
2022-05-04 12:21:52 -04:00
MaterialEditorOnly - > Roughness . Expression = MergedExpression ;
MaterialEditorOnly - > Roughness . Mask = MaterialEditorOnly - > Roughness . Expression - > GetOutputs ( ) [ 0 ] . Mask ;
MaterialEditorOnly - > Roughness . MaskR = 0 ;
MaterialEditorOnly - > Roughness . MaskG = 0 ;
MaterialEditorOnly - > Roughness . MaskB = 1 ;
MaterialEditorOnly - > Roughness . MaskA = 0 ;
2022-02-17 13:52:22 -05:00
}
2015-09-24 09:04:18 -04:00
MaterialNodeY + = MaterialNodeStepY ;
2015-04-29 22:39:01 -04:00
}
2015-09-24 09:04:18 -04:00
else
{
// Metallic
2016-09-22 15:33:34 -04:00
if ( bHasMetallic & & MaterialProxySettings . bMetallicMap )
2015-09-24 09:04:18 -04:00
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _M " ) ;
2015-11-12 18:11:48 -05:00
const bool bSRGB = true ;
2019-01-23 17:01:56 -05:00
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath / AssetName , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Metallic ) , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Metallic ) , TC_Default , InTextureGroup , Flags , bSRGB ) ;
2015-09-24 09:04:18 -04:00
OutGeneratedAssets . Add ( Texture ) ;
auto MetallicExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
MetallicExpression - > Texture = Texture ;
2016-01-14 08:11:47 -05:00
MetallicExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_Color ;
2015-09-24 09:04:18 -04:00
MetallicExpression - > MaterialExpressionEditorX = - 400 ;
MetallicExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( MetallicExpression ) ;
MaterialEditorOnly - > Metallic . Expression = MetallicExpression ;
2015-09-24 09:04:18 -04:00
MaterialNodeY + = MaterialNodeStepY ;
}
// Specular
2016-09-22 15:33:34 -04:00
if ( bHasSpecular & & MaterialProxySettings . bSpecularMap )
2015-09-24 09:04:18 -04:00
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _S " ) ;
2015-11-12 18:11:48 -05:00
const bool bSRGB = true ;
2019-01-23 17:01:56 -05:00
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath / AssetName , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Specular ) , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Specular ) , TC_Default , InTextureGroup , Flags , bSRGB ) ;
2015-09-24 09:04:18 -04:00
OutGeneratedAssets . Add ( Texture ) ;
auto SpecularExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
SpecularExpression - > Texture = Texture ;
2016-01-14 08:11:47 -05:00
SpecularExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_Color ;
2015-09-24 09:04:18 -04:00
SpecularExpression - > MaterialExpressionEditorX = - 400 ;
SpecularExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( SpecularExpression ) ;
MaterialEditorOnly - > Specular . Expression = SpecularExpression ;
2015-09-24 09:04:18 -04:00
MaterialNodeY + = MaterialNodeStepY ;
}
// Roughness
2016-09-22 15:33:34 -04:00
if ( bHasRoughness & & MaterialProxySettings . bRoughnessMap )
2015-09-24 09:04:18 -04:00
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _R " ) ;
2015-11-12 18:11:48 -05:00
const bool bSRGB = true ;
2019-01-23 17:01:56 -05:00
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath / AssetName , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Roughness ) , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Roughness ) , TC_Default , InTextureGroup , Flags , bSRGB ) ;
2015-09-24 09:04:18 -04:00
OutGeneratedAssets . Add ( Texture ) ;
auto RoughnessExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
RoughnessExpression - > Texture = Texture ;
2016-01-14 08:11:47 -05:00
RoughnessExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_Color ;
2015-09-24 09:04:18 -04:00
RoughnessExpression - > MaterialExpressionEditorX = - 400 ;
RoughnessExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( RoughnessExpression ) ;
MaterialEditorOnly - > Roughness . Expression = RoughnessExpression ;
2015-09-24 09:04:18 -04:00
MaterialNodeY + = MaterialNodeStepY ;
}
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . IsPropertyConstant ( EFlattenMaterialProperties : : Metallic ) | | ! MaterialProxySettings . bMetallicMap )
2015-04-29 22:39:01 -04:00
{
auto MetallicExpression = NewObject < UMaterialExpressionConstant > ( Material ) ;
2016-09-22 15:33:34 -04:00
MetallicExpression - > R = MaterialProxySettings . bMetallicMap ? FLinearColor ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Metallic ) [ 0 ] ) . R : MaterialProxySettings . MetallicConstant ;
2015-04-29 22:39:01 -04:00
MetallicExpression - > MaterialExpressionEditorX = - 400 ;
MetallicExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( MetallicExpression ) ;
MaterialEditorOnly - > Metallic . Expression = MetallicExpression ;
2015-04-29 22:39:01 -04:00
2015-09-24 09:04:18 -04:00
MaterialNodeY + = MaterialNodeStepY ;
2015-04-29 22:39:01 -04:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . IsPropertyConstant ( EFlattenMaterialProperties : : Specular ) | | ! MaterialProxySettings . bSpecularMap )
2015-06-30 01:11:32 -04:00
{
// Set Specular to constant
auto SpecularExpression = NewObject < UMaterialExpressionConstant > ( Material ) ;
2016-09-22 15:33:34 -04:00
SpecularExpression - > R = MaterialProxySettings . bSpecularMap ? FLinearColor ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Specular ) [ 0 ] ) . R : MaterialProxySettings . SpecularConstant ;
2015-06-30 01:11:32 -04:00
SpecularExpression - > MaterialExpressionEditorX = - 400 ;
SpecularExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( SpecularExpression ) ;
MaterialEditorOnly - > Specular . Expression = SpecularExpression ;
2015-04-29 22:39:01 -04:00
2015-09-24 09:04:18 -04:00
MaterialNodeY + = MaterialNodeStepY ;
2015-06-30 01:11:32 -04:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . IsPropertyConstant ( EFlattenMaterialProperties : : Roughness ) | | ! MaterialProxySettings . bRoughnessMap )
2015-04-29 22:39:01 -04:00
{
// Set Roughness to constant
auto RoughnessExpression = NewObject < UMaterialExpressionConstant > ( Material ) ;
2016-09-22 15:33:34 -04:00
RoughnessExpression - > R = MaterialProxySettings . bRoughnessMap ? FLinearColor ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Roughness ) [ 0 ] ) . R : MaterialProxySettings . RoughnessConstant ;
2015-04-29 22:39:01 -04:00
RoughnessExpression - > MaterialExpressionEditorX = - 400 ;
RoughnessExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( RoughnessExpression ) ;
MaterialEditorOnly - > Roughness . Expression = RoughnessExpression ;
2015-04-29 22:39:01 -04:00
2015-09-24 09:04:18 -04:00
MaterialNodeY + = MaterialNodeStepY ;
2015-04-29 22:39:01 -04:00
}
// Normal
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . DoesPropertyContainData ( EFlattenMaterialProperties : : Normal ) & & ! InFlattenMaterial . IsPropertyConstant ( EFlattenMaterialProperties : : Normal ) )
2015-04-29 22:39:01 -04:00
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _N " ) ;
const bool bSRGB = false ;
2019-01-23 17:01:56 -05:00
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath / AssetName , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Normal ) , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Normal ) , TC_Normalmap , ( InTextureGroup ! = TEXTUREGROUP_World ) ? InTextureGroup : TEXTUREGROUP_WorldNormalMap , Flags , bSRGB ) ;
2015-04-29 22:39:01 -04:00
OutGeneratedAssets . Add ( Texture ) ;
auto NormalExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
NormalExpression - > Texture = Texture ;
NormalExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_Normal ;
NormalExpression - > MaterialExpressionEditorX = - 400 ;
NormalExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( NormalExpression ) ;
MaterialEditorOnly - > Normal . Expression = NormalExpression ;
2015-04-29 22:39:01 -04:00
MaterialNodeY + = MaterialNodeStepY ;
}
2015-09-24 09:04:18 -04:00
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . IsPropertyConstant ( EFlattenMaterialProperties : : Emissive ) )
2015-09-24 09:04:18 -04:00
{
2015-10-28 19:18:20 -04:00
// Set Emissive to constant
2016-09-22 15:33:34 -04:00
FColor EmissiveColor = InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Emissive ) [ 0 ] ;
2015-10-28 19:18:20 -04:00
// Don't have to deal with black emissive color
if ( EmissiveColor ! = FColor ( 0 , 0 , 0 , 255 ) )
{
auto EmissiveColorExpression = NewObject < UMaterialExpressionConstant4Vector > ( Material ) ;
2015-11-12 18:11:48 -05:00
EmissiveColorExpression - > Constant = EmissiveColor . ReinterpretAsLinear ( ) * InFlattenMaterial . EmissiveScale ;
2015-10-28 19:18:20 -04:00
EmissiveColorExpression - > MaterialExpressionEditorX = - 400 ;
EmissiveColorExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( EmissiveColorExpression ) ;
MaterialEditorOnly - > EmissiveColor . Expression = EmissiveColorExpression ;
2015-09-24 09:04:18 -04:00
2015-10-28 19:18:20 -04:00
MaterialNodeY + = MaterialNodeStepY ;
}
}
2016-09-22 15:33:34 -04:00
else if ( InFlattenMaterial . DoesPropertyContainData ( EFlattenMaterialProperties : : Emissive ) & & ! InFlattenMaterial . IsPropertyConstant ( EFlattenMaterialProperties : : Emissive ) )
2015-10-28 19:18:20 -04:00
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _E " ) ;
2015-11-12 18:11:48 -05:00
const bool bSRGB = true ;
2019-01-23 17:01:56 -05:00
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath / AssetName , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Emissive ) , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Emissive ) , TC_Default , InTextureGroup , Flags , bSRGB ) ;
2015-10-28 19:18:20 -04:00
OutGeneratedAssets . Add ( Texture ) ;
//Assign emissive color to the material
UMaterialExpressionTextureSample * EmissiveColorExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
EmissiveColorExpression - > Texture = Texture ;
2015-11-12 18:11:48 -05:00
EmissiveColorExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_Color ;
2015-10-28 19:18:20 -04:00
EmissiveColorExpression - > MaterialExpressionEditorX = - 400 ;
EmissiveColorExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( EmissiveColorExpression ) ;
2015-10-28 19:18:20 -04:00
UMaterialExpressionMultiply * EmissiveColorScale = NewObject < UMaterialExpressionMultiply > ( Material ) ;
EmissiveColorScale - > A . Expression = EmissiveColorExpression ;
EmissiveColorScale - > ConstB = InFlattenMaterial . EmissiveScale ;
EmissiveColorScale - > MaterialExpressionEditorX = - 200 ;
EmissiveColorScale - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( EmissiveColorScale ) ;
2015-10-28 19:18:20 -04:00
2022-05-04 12:21:52 -04:00
MaterialEditorOnly - > EmissiveColor . Expression = EmissiveColorScale ;
2015-10-28 19:18:20 -04:00
MaterialNodeY + = MaterialNodeStepY ;
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . IsPropertyConstant ( EFlattenMaterialProperties : : Opacity ) )
2015-10-28 19:18:20 -04:00
{
// Set Opacity to constant
2016-09-22 15:33:34 -04:00
FLinearColor Opacity = FLinearColor ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Opacity ) [ 0 ] ) ;
2015-10-28 19:18:20 -04:00
auto OpacityExpression = NewObject < UMaterialExpressionConstant > ( Material ) ;
2015-11-12 18:11:48 -05:00
OpacityExpression - > R = Opacity . R ;
2015-10-28 19:18:20 -04:00
OpacityExpression - > MaterialExpressionEditorX = - 400 ;
OpacityExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( OpacityExpression ) ;
MaterialEditorOnly - > Opacity . Expression = OpacityExpression ;
2015-10-28 19:18:20 -04:00
MaterialNodeY + = MaterialNodeStepY ;
}
2016-09-22 15:33:34 -04:00
else if ( InFlattenMaterial . DoesPropertyContainData ( EFlattenMaterialProperties : : Opacity ) )
2015-10-28 19:18:20 -04:00
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _O " ) ;
2015-11-12 18:11:48 -05:00
const bool bSRGB = true ;
2019-01-23 17:01:56 -05:00
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath / AssetName , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Opacity ) , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Opacity ) , TC_Default , InTextureGroup , Flags , bSRGB ) ;
2015-10-28 19:18:20 -04:00
OutGeneratedAssets . Add ( Texture ) ;
//Assign opacity to the material
UMaterialExpressionTextureSample * OpacityExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
OpacityExpression - > Texture = Texture ;
2016-01-14 08:11:47 -05:00
OpacityExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_Color ;
2015-10-28 19:18:20 -04:00
OpacityExpression - > MaterialExpressionEditorX = - 400 ;
OpacityExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( OpacityExpression ) ;
MaterialEditorOnly - > Opacity . Expression = OpacityExpression ;
2015-10-28 19:18:20 -04:00
MaterialNodeY + = MaterialNodeStepY ;
}
2015-11-12 18:11:48 -05:00
2022-10-24 11:03:51 -04:00
if ( InFlattenMaterial . IsPropertyConstant ( EFlattenMaterialProperties : : OpacityMask ) )
{
// Set OpacityMask to constant
FLinearColor OpacityMask = FLinearColor ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : OpacityMask ) [ 0 ] ) ;
auto OpacityMaskExpression = NewObject < UMaterialExpressionConstant > ( Material ) ;
OpacityMaskExpression - > R = OpacityMask . R ;
OpacityMaskExpression - > MaterialExpressionEditorX = - 400 ;
OpacityMaskExpression - > MaterialExpressionEditorY = MaterialNodeY ;
Material - > GetExpressionCollection ( ) . AddExpression ( OpacityMaskExpression ) ;
MaterialEditorOnly - > OpacityMask . Expression = OpacityMaskExpression ;
MaterialNodeY + = MaterialNodeStepY ;
}
else if ( InFlattenMaterial . DoesPropertyContainData ( EFlattenMaterialProperties : : OpacityMask ) )
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _OM " ) ;
const bool bSRGB = true ;
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath / AssetName , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : OpacityMask ) , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : OpacityMask ) , TC_Default , InTextureGroup , Flags , bSRGB ) ;
OutGeneratedAssets . Add ( Texture ) ;
//Assign opacity to the material
UMaterialExpressionTextureSample * OpacityMaskExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
OpacityMaskExpression - > Texture = Texture ;
OpacityMaskExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_Color ;
OpacityMaskExpression - > MaterialExpressionEditorX = - 400 ;
OpacityMaskExpression - > MaterialExpressionEditorY = MaterialNodeY ;
Material - > GetExpressionCollection ( ) . AddExpression ( OpacityMaskExpression ) ;
MaterialEditorOnly - > OpacityMask . Expression = OpacityMaskExpression ;
MaterialNodeY + = MaterialNodeStepY ;
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . IsPropertyConstant ( EFlattenMaterialProperties : : SubSurface ) )
2015-11-12 18:11:48 -05:00
{
// Set Emissive to constant
2016-09-22 15:33:34 -04:00
FColor SubSurfaceColor = InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : SubSurface ) [ 0 ] ;
2015-11-12 18:11:48 -05:00
// Don't have to deal with black sub surface color
if ( SubSurfaceColor ! = FColor ( 0 , 0 , 0 , 255 ) )
{
auto SubSurfaceColorExpression = NewObject < UMaterialExpressionConstant4Vector > ( Material ) ;
SubSurfaceColorExpression - > Constant = ( SubSurfaceColor . ReinterpretAsLinear ( ) ) ;
SubSurfaceColorExpression - > MaterialExpressionEditorX = - 400 ;
SubSurfaceColorExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( SubSurfaceColorExpression ) ;
MaterialEditorOnly - > SubsurfaceColor . Expression = SubSurfaceColorExpression ;
2015-11-12 18:11:48 -05:00
MaterialNodeY + = MaterialNodeStepY ;
}
Material - > SetShadingModel ( MSM_Subsurface ) ;
}
2016-09-22 15:33:34 -04:00
else if ( InFlattenMaterial . DoesPropertyContainData ( EFlattenMaterialProperties : : SubSurface ) )
2015-11-12 18:11:48 -05:00
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _SSC " ) ;
const bool bSRGB = true ;
2019-01-23 17:01:56 -05:00
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath / AssetName , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : SubSurface ) , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : SubSurface ) , TC_Default , InTextureGroup , Flags , bSRGB ) ;
2015-11-12 18:11:48 -05:00
OutGeneratedAssets . Add ( Texture ) ;
//Assign emissive color to the material
UMaterialExpressionTextureSample * SubSurfaceColorExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
SubSurfaceColorExpression - > Texture = Texture ;
SubSurfaceColorExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_Color ;
SubSurfaceColorExpression - > MaterialExpressionEditorX = - 400 ;
SubSurfaceColorExpression - > MaterialExpressionEditorY = MaterialNodeY ;
2022-05-04 12:21:52 -04:00
Material - > GetExpressionCollection ( ) . AddExpression ( SubSurfaceColorExpression ) ;
2015-11-12 18:11:48 -05:00
2022-05-04 12:21:52 -04:00
MaterialEditorOnly - > SubsurfaceColor . Expression = SubSurfaceColorExpression ;
2015-11-12 18:11:48 -05:00
MaterialNodeY + = MaterialNodeStepY ;
Material - > SetShadingModel ( MSM_Subsurface ) ;
}
2015-04-29 22:39:01 -04:00
Material - > PostEditChange ( ) ;
return Material ;
}
2018-02-22 11:25:06 -05:00
UMaterialInstanceConstant * FMaterialUtilities : : CreateInstancedMaterial ( UMaterialInterface * BaseMaterial , UPackage * InOuter , const FString & BaseName , EObjectFlags Flags )
2016-07-20 18:23:54 -04:00
{
// Base name for a new assets
// In case outer is null BaseName has to be long package name
if ( InOuter = = nullptr & & FPackageName : : IsShortPackageName ( BaseName ) )
{
UE_LOG ( LogMaterialUtilities , Warning , TEXT ( " Invalid long package name: '%s'. " ) , * BaseName ) ;
return nullptr ;
}
const FString AssetBaseName = FPackageName : : GetShortName ( BaseName ) ;
2019-01-23 17:01:56 -05:00
const FString AssetBasePath = InOuter ? TEXT ( " " ) : FPackageName : : GetLongPackagePath ( BaseName ) ;
2016-07-20 18:23:54 -04:00
// Create material
const FString MaterialAssetName = TEXT ( " M_ " ) + AssetBaseName ;
UPackage * MaterialOuter = InOuter ;
if ( MaterialOuter = = NULL )
{
2020-09-24 00:43:27 -04:00
MaterialOuter = CreatePackage ( * ( AssetBasePath / MaterialAssetName ) ) ;
2016-07-20 18:23:54 -04:00
MaterialOuter - > FullyLoad ( ) ;
MaterialOuter - > Modify ( ) ;
}
// We need to check for this due to the change in material object type, this causes a clash of path/type with old assets that were generated, so we delete the old (resident) UMaterial objects
UObject * ExistingPackage = FindObject < UMaterial > ( MaterialOuter , * MaterialAssetName ) ;
if ( ExistingPackage & & ! ExistingPackage - > IsA < UMaterialInstanceConstant > ( ) )
{
2021-04-29 19:32:06 -04:00
# if WITH_AUTOMATION_TESTS
2016-08-09 11:28:56 -04:00
FAutomationEditorCommonUtils : : NullReferencesToObject ( ExistingPackage ) ;
2021-04-29 19:32:06 -04:00
# endif // WITH_AUTOMATION_TESTS
2021-11-18 14:37:34 -05:00
ExistingPackage - > MarkAsGarbage ( ) ;
2016-07-20 18:23:54 -04:00
CollectGarbage ( GARBAGE_COLLECTION_KEEPFLAGS , true ) ;
}
UMaterialInstanceConstant * MaterialInstance = NewObject < UMaterialInstanceConstant > ( MaterialOuter , FName ( * MaterialAssetName ) , Flags ) ;
checkf ( MaterialInstance , TEXT ( " Failed to create instanced material " ) ) ;
2018-02-22 11:25:06 -05:00
MaterialInstance - > Parent = BaseMaterial ;
2016-07-20 18:23:54 -04:00
return MaterialInstance ;
}
2015-04-29 22:39:01 -04:00
UTexture2D * FMaterialUtilities : : CreateTexture ( UPackage * Outer , const FString & AssetLongName , FIntPoint Size , const TArray < FColor > & Samples , TextureCompressionSettings CompressionSettings , TextureGroup LODGroup , EObjectFlags Flags , bool bSRGB , const FGuid & SourceGuidHash )
{
FCreateTexture2DParameters TexParams ;
TexParams . bUseAlpha = false ;
TexParams . CompressionSettings = CompressionSettings ;
TexParams . bDeferCompression = true ;
TexParams . bSRGB = bSRGB ;
TexParams . SourceGuidHash = SourceGuidHash ;
2022-02-14 12:01:24 -05:00
TexParams . TextureGroup = LODGroup ;
2015-04-29 22:39:01 -04:00
2022-02-14 12:01:24 -05:00
return CreateTexture ( Outer , AssetLongName , Size , Samples , TexParams , Flags ) ;
}
UTexture2D * FMaterialUtilities : : CreateTexture ( UPackage * Outer , const FString & AssetLongName , FIntPoint Size , const TArray < FColor > & Samples , const FCreateTexture2DParameters & CreateParams , EObjectFlags Flags )
{
2015-04-29 22:39:01 -04:00
if ( Outer = = nullptr )
{
2022-02-14 12:01:24 -05:00
Outer = CreatePackage ( * AssetLongName ) ;
2015-04-29 22:39:01 -04:00
Outer - > FullyLoad ( ) ;
Outer - > Modify ( ) ;
}
2022-02-14 12:01:24 -05:00
return FImageUtils : : CreateTexture2D ( Size . X , Size . Y , Samples , Outer , FPackageName : : GetShortName ( AssetLongName ) , Flags , CreateParams ) ;
2015-04-29 22:39:01 -04:00
}
bool FMaterialUtilities : : ExportBaseColor ( ULandscapeComponent * LandscapeComponent , int32 TextureSize , TArray < FColor > & OutSamples )
{
ALandscapeProxy * LandscapeProxy = LandscapeComponent - > GetLandscapeProxy ( ) ;
FIntPoint ComponentOrigin = LandscapeComponent - > GetSectionBase ( ) - LandscapeProxy - > LandscapeSectionOffset ;
FIntPoint ComponentSize ( LandscapeComponent - > ComponentSizeQuads , LandscapeComponent - > ComponentSizeQuads ) ;
FVector MidPoint = FVector ( ComponentOrigin , 0.f ) + FVector ( ComponentSize , 0.f ) * 0.5f ;
FVector LandscapeCenter = LandscapeProxy - > GetTransform ( ) . TransformPosition ( MidPoint ) ;
FVector LandscapeExtent = FVector ( ComponentSize , 0.f ) * LandscapeProxy - > GetActorScale ( ) * 0.5f ;
FVector ViewOrigin = LandscapeCenter ;
FMatrix ViewRotationMatrix = FInverseRotationMatrix ( LandscapeProxy - > GetActorRotation ( ) ) ;
ViewRotationMatrix * = FMatrix ( FPlane ( 1 , 0 , 0 , 0 ) ,
FPlane ( 0 , - 1 , 0 , 0 ) ,
FPlane ( 0 , 0 , - 1 , 0 ) ,
FPlane ( 0 , 0 , 0 , 1 ) ) ;
2022-06-09 07:03:13 -04:00
const FMatrix : : FReal ZOffset = UE_OLD_WORLD_MAX ;
2015-04-29 22:39:01 -04:00
FMatrix ProjectionMatrix = FReversedZOrthoMatrix (
LandscapeExtent . X ,
LandscapeExtent . Y ,
0.5f / ZOffset ,
ZOffset ) ;
FSceneInterface * Scene = LandscapeProxy - > GetWorld ( ) - > Scene ;
// Hide all but the component
2022-02-14 12:01:24 -05:00
TSet < FPrimitiveComponentId > ShowOnlyPrimitives = { LandscapeComponent - > SceneProxy - > GetPrimitiveComponentId ( ) } ;
2015-04-29 22:39:01 -04:00
TSet < FPrimitiveComponentId > HiddenPrimitives ;
FIntPoint TargetSize ( TextureSize , TextureSize ) ;
// Render diffuse texture using BufferVisualizationMode=BaseColor
static const FName BaseColorName ( " BaseColor " ) ;
const float BaseColorGamma = 2.2f ;
2022-02-14 12:01:24 -05:00
RenderSceneToTexture ( Scene , BaseColorName , ViewOrigin , ViewRotationMatrix , ProjectionMatrix , ShowOnlyPrimitives , HiddenPrimitives , TargetSize , BaseColorGamma , true , OutSamples ) ;
2015-04-29 22:39:01 -04:00
return true ;
2015-09-24 09:04:18 -04:00
}
2015-10-28 19:18:20 -04:00
FFlattenMaterial FMaterialUtilities : : CreateFlattenMaterialWithSettings ( const FMaterialProxySettings & InMaterialLODSettings )
2015-09-24 09:04:18 -04:00
{
2015-10-28 19:18:20 -04:00
// Create new material.
FFlattenMaterial Material ;
2022-09-20 01:40:59 -04:00
FIntPoint MaximumSize = FIntPoint : : ZeroValue ;
2015-11-12 18:11:48 -05:00
if ( InMaterialLODSettings . TextureSizingType = = TextureSizingType_UseManualOverrideTextureSize )
{
2022-09-20 01:40:59 -04:00
// If the user is manually overriding the texture size, make sure we have the max texture size to render with
2017-09-30 03:42:01 -04:00
MaximumSize = ( MaximumSize . X < InMaterialLODSettings . DiffuseTextureSize . X ) ? InMaterialLODSettings . DiffuseTextureSize : MaximumSize ;
MaximumSize = ( InMaterialLODSettings . bSpecularMap & & ( MaximumSize . X < InMaterialLODSettings . SpecularTextureSize . X ) ) ? InMaterialLODSettings . SpecularTextureSize : MaximumSize ;
MaximumSize = ( InMaterialLODSettings . bMetallicMap & & ( MaximumSize . X < InMaterialLODSettings . MetallicTextureSize . X ) ) ? InMaterialLODSettings . MetallicTextureSize : MaximumSize ;
MaximumSize = ( InMaterialLODSettings . bRoughnessMap & & ( MaximumSize . X < InMaterialLODSettings . RoughnessTextureSize . X ) ) ? InMaterialLODSettings . RoughnessTextureSize : MaximumSize ;
MaximumSize = ( InMaterialLODSettings . bNormalMap & & ( MaximumSize . X < InMaterialLODSettings . NormalTextureSize . X ) ) ? InMaterialLODSettings . NormalTextureSize : MaximumSize ;
MaximumSize = ( InMaterialLODSettings . bEmissiveMap & & ( MaximumSize . X < InMaterialLODSettings . EmissiveTextureSize . X ) ) ? InMaterialLODSettings . EmissiveTextureSize : MaximumSize ;
MaximumSize = ( InMaterialLODSettings . bOpacityMap & & ( MaximumSize . X < InMaterialLODSettings . OpacityTextureSize . X ) ) ? InMaterialLODSettings . OpacityTextureSize : MaximumSize ;
2022-10-24 11:03:51 -04:00
MaximumSize = ( InMaterialLODSettings . bOpacityMaskMap & & ( MaximumSize . X < InMaterialLODSettings . OpacityMaskTextureSize . X ) ) ? InMaterialLODSettings . OpacityMaskTextureSize : MaximumSize ;
2015-11-12 18:11:48 -05:00
Material . RenderSize = MaximumSize ;
2016-09-22 15:33:34 -04:00
Material . SetPropertySize ( EFlattenMaterialProperties : : Diffuse , InMaterialLODSettings . DiffuseTextureSize ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Specular , InMaterialLODSettings . bSpecularMap ? InMaterialLODSettings . SpecularTextureSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Metallic , InMaterialLODSettings . bMetallicMap ? InMaterialLODSettings . MetallicTextureSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Roughness , InMaterialLODSettings . bRoughnessMap ? InMaterialLODSettings . RoughnessTextureSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Normal , InMaterialLODSettings . bNormalMap ? InMaterialLODSettings . NormalTextureSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Emissive , InMaterialLODSettings . bEmissiveMap ? InMaterialLODSettings . EmissiveTextureSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Opacity , InMaterialLODSettings . bOpacityMap ? InMaterialLODSettings . OpacityTextureSize : FIntPoint : : ZeroValue ) ;
2022-10-24 11:03:51 -04:00
Material . SetPropertySize ( EFlattenMaterialProperties : : OpacityMask , InMaterialLODSettings . bOpacityMaskMap ? InMaterialLODSettings . OpacityMaskTextureSize : FIntPoint : : ZeroValue ) ;
2015-11-12 18:11:48 -05:00
}
else if ( InMaterialLODSettings . TextureSizingType = = TextureSizingType_UseAutomaticBiasedSizes )
{
Material . RenderSize = InMaterialLODSettings . TextureSize ;
2022-09-20 01:40:59 -04:00
int NormalSize = InMaterialLODSettings . TextureSize . X ;
int DiffuseSize = FMath : : Max ( InMaterialLODSettings . TextureSize . X > > 1 , 32 ) ;
int OtherSize = FMath : : Max ( InMaterialLODSettings . TextureSize . X > > 2 , 16 ) ;
FIntPoint PropertiesSize = FIntPoint ( OtherSize , OtherSize ) ;
2015-11-12 18:11:48 -05:00
2022-09-20 01:40:59 -04:00
Material . SetPropertySize ( EFlattenMaterialProperties : : Diffuse , FIntPoint ( DiffuseSize , DiffuseSize ) ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Normal , ( InMaterialLODSettings . bNormalMap ) ? FIntPoint ( NormalSize , NormalSize ) : FIntPoint : : ZeroValue ) ;
2016-09-22 15:33:34 -04:00
Material . SetPropertySize ( EFlattenMaterialProperties : : Specular , ( InMaterialLODSettings . bSpecularMap ) ? PropertiesSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Metallic , ( InMaterialLODSettings . bMetallicMap ) ? PropertiesSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Roughness , ( InMaterialLODSettings . bRoughnessMap ) ? PropertiesSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Emissive , ( InMaterialLODSettings . bEmissiveMap ) ? PropertiesSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Opacity , ( InMaterialLODSettings . bOpacityMap ) ? PropertiesSize : FIntPoint : : ZeroValue ) ;
2022-10-24 11:03:51 -04:00
Material . SetPropertySize ( EFlattenMaterialProperties : : OpacityMask , ( InMaterialLODSettings . bOpacityMaskMap ) ? PropertiesSize : FIntPoint : : ZeroValue ) ;
2015-11-12 18:11:48 -05:00
}
2017-09-30 03:42:01 -04:00
else if ( InMaterialLODSettings . TextureSizingType = = TextureSizingType_UseSingleTextureSize )
{
Material . RenderSize = InMaterialLODSettings . TextureSize ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Diffuse , InMaterialLODSettings . TextureSize ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Specular , ( InMaterialLODSettings . bSpecularMap ) ? InMaterialLODSettings . TextureSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Metallic , ( InMaterialLODSettings . bMetallicMap ) ? InMaterialLODSettings . TextureSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Roughness , ( InMaterialLODSettings . bRoughnessMap ) ? InMaterialLODSettings . TextureSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Normal , ( InMaterialLODSettings . bNormalMap ) ? InMaterialLODSettings . TextureSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Emissive , ( InMaterialLODSettings . bEmissiveMap ) ? InMaterialLODSettings . TextureSize : FIntPoint : : ZeroValue ) ;
Material . SetPropertySize ( EFlattenMaterialProperties : : Opacity , ( InMaterialLODSettings . bOpacityMap ) ? InMaterialLODSettings . TextureSize : FIntPoint : : ZeroValue ) ;
2022-10-24 11:03:51 -04:00
Material . SetPropertySize ( EFlattenMaterialProperties : : OpacityMask , ( InMaterialLODSettings . bOpacityMaskMap ) ? InMaterialLODSettings . TextureSize : FIntPoint : : ZeroValue ) ;
2017-09-30 03:42:01 -04:00
}
2022-09-20 01:40:59 -04:00
else
{
UE_LOG ( LogMaterialUtilities , Error , TEXT ( " Unsupported TextureSizingType value. You should resolve the material texture size first with ResolveTextureSize() " ) ) ;
}
2015-10-28 19:18:20 -04:00
return Material ;
2015-09-24 09:04:18 -04:00
}
2015-11-12 18:11:48 -05:00
void FMaterialUtilities : : AnalyzeMaterial ( UMaterialInterface * InMaterial , const struct FMaterialProxySettings & InMaterialSettings , int32 & OutNumTexCoords , bool & OutRequiresVertexData )
2015-10-28 19:18:20 -04:00
{
2015-11-12 18:11:48 -05:00
OutRequiresVertexData = false ;
2015-10-28 19:18:20 -04:00
OutNumTexCoords = 0 ;
2020-02-12 13:27:19 -05:00
bool PropertyBeingBaked [ MP_Tangent + 1 ] ;
2015-10-28 19:18:20 -04:00
PropertyBeingBaked [ MP_BaseColor ] = true ;
PropertyBeingBaked [ MP_Specular ] = InMaterialSettings . bSpecularMap ;
PropertyBeingBaked [ MP_Roughness ] = InMaterialSettings . bRoughnessMap ;
2020-02-12 13:27:19 -05:00
PropertyBeingBaked [ MP_Anisotropy ] = InMaterialSettings . bAnisotropyMap ;
2015-10-28 19:18:20 -04:00
PropertyBeingBaked [ MP_Metallic ] = InMaterialSettings . bMetallicMap ;
PropertyBeingBaked [ MP_Normal ] = InMaterialSettings . bNormalMap ;
2020-02-12 13:27:19 -05:00
PropertyBeingBaked [ MP_Tangent ] = InMaterialSettings . bTangentMap ;
2017-06-21 10:25:35 -04:00
PropertyBeingBaked [ MP_Metallic ] = InMaterialSettings . bOpacityMap ;
2015-10-28 19:18:20 -04:00
PropertyBeingBaked [ MP_EmissiveColor ] = InMaterialSettings . bEmissiveMap ;
2019-09-28 08:19:35 -04:00
for ( int32 PropertyIndex = 0 ; PropertyIndex < UE_ARRAY_COUNT ( PropertyBeingBaked ) ; + + PropertyIndex )
2015-10-28 19:18:20 -04:00
{
if ( PropertyBeingBaked [ PropertyIndex ] )
{
EMaterialProperty Property = ( EMaterialProperty ) PropertyIndex ;
if ( PropertyIndex = = MP_Opacity )
{
2022-12-13 10:44:43 -05:00
if ( IsMaskedBlendMode ( * InMaterial ) )
2015-10-28 19:18:20 -04:00
{
Property = MP_OpacityMask ;
}
2022-12-13 10:44:43 -05:00
else if ( IsTranslucentBlendMode ( * InMaterial ) )
2015-10-28 19:18:20 -04:00
{
Property = MP_Opacity ;
}
else
{
continue ;
}
}
// Analyze this material channel.
int32 NumTextureCoordinates = 0 ;
2015-11-12 18:11:48 -05:00
bool bUseVertexData = false ;
InMaterial - > AnalyzeMaterialProperty ( Property , NumTextureCoordinates , bUseVertexData ) ;
2015-10-28 19:18:20 -04:00
// Accumulate data.
OutNumTexCoords = FMath : : Max ( NumTextureCoordinates , OutNumTexCoords ) ;
2015-11-12 18:11:48 -05:00
OutRequiresVertexData | = bUseVertexData ;
2015-10-28 19:18:20 -04:00
}
}
}
2017-06-21 10:25:35 -04:00
void FMaterialUtilities : : AnalyzeMaterial ( class UMaterialInterface * InMaterial , const TArray < EMaterialProperty > & Properties , int32 & OutNumTexCoords , bool & OutRequiresVertexData )
{
OutRequiresVertexData = false ;
OutNumTexCoords = 0 ;
for ( EMaterialProperty Property : Properties )
{
if ( Property = = MP_Opacity )
{
2022-12-13 10:44:43 -05:00
if ( IsMaskedBlendMode ( * InMaterial ) )
2017-06-21 10:25:35 -04:00
{
Property = MP_OpacityMask ;
}
2022-12-13 10:44:43 -05:00
else if ( IsTranslucentBlendMode ( * InMaterial ) )
2017-06-21 10:25:35 -04:00
{
Property = MP_Opacity ;
}
else
{
continue ;
}
}
// Analyze this material channel.
int32 NumTextureCoordinates = 0 ;
bool bUseVertexData = false ;
InMaterial - > AnalyzeMaterialProperty ( Property , NumTextureCoordinates , bUseVertexData ) ;
// Accumulate data.
OutNumTexCoords = FMath : : Max ( NumTextureCoordinates , OutNumTexCoords ) ;
OutRequiresVertexData | = bUseVertexData ;
}
}
2016-10-06 12:11:11 -04:00
void FMaterialUtilities : : RemapUniqueMaterialIndices ( const TArray < FSectionInfo > & InSections , const TArray < FRawMeshExt > & InMeshData , const TMap < FMeshIdAndLOD , TArray < int32 > > & InMaterialMap , const FMaterialProxySettings & InMaterialProxySettings , const bool bBakeVertexData , const bool bMergeMaterials , TArray < bool > & OutMeshShouldBakeVertexData , TMap < FMeshIdAndLOD , TArray < int32 > > & OutMaterialMap , TArray < FSectionInfo > & OutSections )
2015-10-28 19:18:20 -04:00
{
// Gather material properties
TMap < UMaterialInterface * , int32 > MaterialNumTexCoords ;
2015-11-12 18:11:48 -05:00
TMap < UMaterialInterface * , bool > MaterialUseVertexData ;
2015-10-28 19:18:20 -04:00
2016-10-06 12:11:11 -04:00
for ( int32 SectionIndex = 0 ; SectionIndex < InSections . Num ( ) ; SectionIndex + + )
2015-10-28 19:18:20 -04:00
{
2016-10-06 12:11:11 -04:00
const FSectionInfo & Section = InSections [ SectionIndex ] ;
if ( MaterialNumTexCoords . Find ( Section . Material ) ! = nullptr )
2015-10-28 19:18:20 -04:00
{
// This material was already processed.
continue ;
}
if ( ! bBakeVertexData | | ! bMergeMaterials )
{
// We are not baking vertex data at all, don't analyze materials.
2016-10-06 12:11:11 -04:00
MaterialNumTexCoords . Add ( Section . Material , 0 ) ;
MaterialUseVertexData . Add ( Section . Material , false ) ;
2015-10-28 19:18:20 -04:00
continue ;
}
int32 NumTexCoords = 0 ;
2015-11-12 18:11:48 -05:00
bool bUseVertexData = false ;
2016-10-06 12:11:11 -04:00
FMaterialUtilities : : AnalyzeMaterial ( Section . Material , InMaterialProxySettings , NumTexCoords , bUseVertexData ) ;
MaterialNumTexCoords . Add ( Section . Material , NumTexCoords ) ;
MaterialUseVertexData . Add ( Section . Material , bUseVertexData ) ;
2015-10-28 19:18:20 -04:00
}
for ( int32 MeshIndex = 0 ; MeshIndex < InMeshData . Num ( ) ; MeshIndex + + )
{
2016-08-05 17:47:48 -04:00
for ( int32 LODIndex = 0 ; LODIndex < MAX_STATIC_MESH_LODS ; + + LODIndex )
2015-10-28 19:18:20 -04:00
{
2021-05-05 15:07:25 -04:00
TVertexAttributesRef < FVector3f > VertexPositions = InMeshData [ MeshIndex ] . MeshLODData [ LODIndex ] . RawMesh - > GetVertexPositions ( ) ;
2019-01-03 19:28:34 -05:00
2016-08-05 17:47:48 -04:00
if ( InMeshData [ MeshIndex ] . bShouldExportLOD [ LODIndex ] )
{
2019-01-03 19:28:34 -05:00
checkf ( VertexPositions . GetNumElements ( ) , TEXT ( " No vertex data found in mesh LOD " ) ) ;
2017-06-21 10:25:35 -04:00
2016-08-05 17:47:48 -04:00
const TArray < int32 > & MeshMaterialMap = InMaterialMap [ FMeshIdAndLOD ( MeshIndex , LODIndex ) ] ;
2017-06-21 10:25:35 -04:00
int32 NumTexCoords = 0 ;
bool bUseVertexData = false ;
// Accumulate data of all materials.
for ( int32 LocalMaterialIndex = 0 ; LocalMaterialIndex < MeshMaterialMap . Num ( ) ; LocalMaterialIndex + + )
{
2016-10-06 12:11:11 -04:00
UMaterialInterface * Material = InSections [ MeshMaterialMap [ LocalMaterialIndex ] ] . Material ;
2017-06-21 10:25:35 -04:00
NumTexCoords = FMath : : Max ( NumTexCoords , MaterialNumTexCoords [ Material ] ) ;
bUseVertexData | = MaterialUseVertexData [ Material ] ;
}
2016-10-06 12:11:11 -04:00
2017-06-21 10:25:35 -04:00
// Store data.
2016-10-06 12:11:11 -04:00
OutMeshShouldBakeVertexData [ MeshIndex ] | = bUseVertexData | | ( NumTexCoords > = 2 ) ;
2016-08-05 17:47:48 -04:00
}
2015-10-28 19:18:20 -04:00
}
}
// Build new material map.
// Structure used to simplify material merging.
struct FMeshMaterialData
{
2016-10-06 12:11:11 -04:00
FSectionInfo SectionInfo ;
2015-10-28 19:18:20 -04:00
UStaticMesh * Mesh ;
bool bHasVertexColors ;
2016-10-06 12:11:11 -04:00
FMeshMaterialData ( const FSectionInfo & InSection , UStaticMesh * InMesh , bool bInHasVertexColors )
: SectionInfo ( InSection )
2015-10-28 19:18:20 -04:00
, Mesh ( InMesh )
, bHasVertexColors ( bInHasVertexColors )
{
}
bool operator = = ( const FMeshMaterialData & Other ) const
{
2016-10-06 12:11:11 -04:00
return SectionInfo = = Other . SectionInfo & & Mesh = = Other . Mesh & & bHasVertexColors = = Other . bHasVertexColors ;
2015-10-28 19:18:20 -04:00
}
} ;
TArray < FMeshMaterialData > MeshMaterialData ;
OutMaterialMap . Empty ( ) ;
for ( int32 MeshIndex = 0 ; MeshIndex < InMeshData . Num ( ) ; MeshIndex + + )
{
2016-08-05 17:47:48 -04:00
for ( int32 LODIndex = 0 ; LODIndex < MAX_STATIC_MESH_LODS ; + + LODIndex )
2015-10-28 19:18:20 -04:00
{
2021-05-05 15:07:25 -04:00
TVertexAttributesRef < FVector3f > VertexPositions = InMeshData [ MeshIndex ] . MeshLODData [ LODIndex ] . RawMesh - > GetVertexPositions ( ) ;
2019-01-03 19:28:34 -05:00
2016-08-05 17:47:48 -04:00
if ( InMeshData [ MeshIndex ] . bShouldExportLOD [ LODIndex ] )
2015-10-28 19:18:20 -04:00
{
2019-01-03 19:28:34 -05:00
checkf ( VertexPositions . GetNumElements ( ) , TEXT ( " No vertex data found in mesh LOD " ) ) ;
2016-10-06 12:11:11 -04:00
2017-06-21 10:25:35 -04:00
const TArray < int32 > & MeshMaterialMap = InMaterialMap [ FMeshIdAndLOD ( MeshIndex , LODIndex ) ] ;
TArray < int32 > & NewMeshMaterialMap = OutMaterialMap . Add ( FMeshIdAndLOD ( MeshIndex , LODIndex ) ) ;
UStaticMesh * StaticMesh = InMeshData [ MeshIndex ] . SourceStaticMesh ;
2016-05-06 15:20:28 -04:00
2022-02-17 13:52:22 -05:00
if ( ! OutMeshShouldBakeVertexData [ MeshIndex ] )
{
// No vertex data needed - could merge materials with other meshes.
// Set to 'nullptr' if don't need to bake vertex data to be able to merge materials with any meshes
// which don't require vertex data baking too.
StaticMesh = nullptr ;
2016-10-06 12:11:11 -04:00
2017-06-21 10:25:35 -04:00
for ( int32 LocalMaterialIndex = 0 ; LocalMaterialIndex < MeshMaterialMap . Num ( ) ; LocalMaterialIndex + + )
{
2016-10-06 12:11:11 -04:00
FMeshMaterialData Data ( InSections [ MeshMaterialMap [ LocalMaterialIndex ] ] , StaticMesh , false ) ;
2017-06-21 10:25:35 -04:00
int32 Index = MeshMaterialData . Find ( Data ) ;
if ( Index = = INDEX_NONE )
{
// Not found, add new entry.
Index = MeshMaterialData . Add ( Data ) ;
}
NewMeshMaterialMap . Add ( Index ) ;
}
2016-10-06 12:11:11 -04:00
}
2017-06-21 10:25:35 -04:00
else
{
// Mesh with vertex data baking, and with vertex colors - don't share materials at all.
for ( int32 LocalMaterialIndex = 0 ; LocalMaterialIndex < MeshMaterialMap . Num ( ) ; LocalMaterialIndex + + )
{
2016-10-06 12:11:11 -04:00
FMeshMaterialData Data ( InSections [ MeshMaterialMap [ LocalMaterialIndex ] ] , StaticMesh , true ) ;
2017-06-21 10:25:35 -04:00
int32 Index = MeshMaterialData . Add ( Data ) ;
NewMeshMaterialMap . Add ( Index ) ;
}
}
2016-10-06 12:11:11 -04:00
}
2015-10-28 19:18:20 -04:00
}
}
// Build new material list - simply extract MeshMaterialData[i].Material.
2016-10-06 12:11:11 -04:00
OutSections . Empty ( ) ;
2017-06-21 10:25:35 -04:00
OutSections . AddDefaulted ( MeshMaterialData . Num ( ) ) ;
2015-10-28 19:18:20 -04:00
for ( int32 MaterialIndex = 0 ; MaterialIndex < MeshMaterialData . Num ( ) ; MaterialIndex + + )
{
2016-10-06 12:11:11 -04:00
OutSections [ MaterialIndex ] = MeshMaterialData [ MaterialIndex ] . SectionInfo ;
2015-10-28 19:18:20 -04:00
}
}
void FMaterialUtilities : : OptimizeFlattenMaterial ( FFlattenMaterial & InFlattenMaterial )
{
// Try to optimize each individual property sample
2016-09-22 15:33:34 -04:00
for ( int32 PropertyIndex = 0 ; PropertyIndex < ( int32 ) EFlattenMaterialProperties : : NumFlattenMaterialProperties ; + + PropertyIndex )
{
EFlattenMaterialProperties Property = ( EFlattenMaterialProperties ) PropertyIndex ;
FIntPoint Size = InFlattenMaterial . GetPropertySize ( Property ) ;
OptimizeSampleArray ( InFlattenMaterial . GetPropertySamples ( Property ) , Size ) ;
InFlattenMaterial . SetPropertySize ( Property , Size ) ;
}
2015-10-28 19:18:20 -04:00
}
2015-11-12 18:11:48 -05:00
void FMaterialUtilities : : ResizeFlattenMaterial ( FFlattenMaterial & InFlattenMaterial , const struct FMeshProxySettings & InMeshProxySettings )
{
const FMaterialProxySettings & MaterialSettings = InMeshProxySettings . MaterialSettings ;
if ( MaterialSettings . TextureSizingType = = TextureSizingType_UseAutomaticBiasedSizes )
{
int NormalSizeX , DiffuseSizeX , PropertiesSizeX ;
NormalSizeX = MaterialSettings . TextureSize . X ;
DiffuseSizeX = FMath : : Max ( MaterialSettings . TextureSize . X > > 1 , 32 ) ;
PropertiesSizeX = FMath : : Max ( MaterialSettings . TextureSize . X > > 2 , 16 ) ;
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Diffuse ) . X ! = DiffuseSizeX )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Diffuse ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Diffuse ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Diffuse ) , DiffuseSizeX , DiffuseSizeX , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Diffuse ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Diffuse ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Diffuse , FIntPoint ( DiffuseSizeX , DiffuseSizeX ) ) ;
2015-11-12 18:11:48 -05:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Specular ) . Num ( ) & & MaterialSettings . bSpecularMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Specular ) . X ! = PropertiesSizeX )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Specular ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Specular ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Specular ) , PropertiesSizeX , PropertiesSizeX , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Specular ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Specular ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Specular , FIntPoint ( PropertiesSizeX , PropertiesSizeX ) ) ;
2015-11-12 18:11:48 -05:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Metallic ) . Num ( ) & & MaterialSettings . bMetallicMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Metallic ) . X ! = PropertiesSizeX )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Metallic ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Metallic ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Metallic ) , PropertiesSizeX , PropertiesSizeX , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Metallic ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Metallic ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Metallic , FIntPoint ( PropertiesSizeX , PropertiesSizeX ) ) ;
2015-11-12 18:11:48 -05:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Roughness ) . Num ( ) & & MaterialSettings . bRoughnessMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Roughness ) . X ! = PropertiesSizeX )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Roughness ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Roughness ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Roughness ) , PropertiesSizeX , PropertiesSizeX , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Roughness ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Roughness ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Roughness , FIntPoint ( PropertiesSizeX , PropertiesSizeX ) ) ;
2015-11-12 18:11:48 -05:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Normal ) . Num ( ) & & MaterialSettings . bNormalMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Normal ) . X ! = NormalSizeX )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Normal ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Normal ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Normal ) , NormalSizeX , NormalSizeX , NewSamples , true ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Normal ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Normal ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Normal , FIntPoint ( NormalSizeX , NormalSizeX ) ) ;
2015-11-12 18:11:48 -05:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Emissive ) . Num ( ) & & MaterialSettings . bEmissiveMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Emissive ) . X ! = PropertiesSizeX )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Emissive ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Emissive ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Emissive ) , PropertiesSizeX , PropertiesSizeX , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Emissive ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Emissive ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Emissive , FIntPoint ( PropertiesSizeX , PropertiesSizeX ) ) ;
2015-11-12 18:11:48 -05:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Opacity ) . Num ( ) & & MaterialSettings . bOpacityMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Opacity ) . X ! = PropertiesSizeX )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Opacity ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Opacity ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Opacity ) , PropertiesSizeX , PropertiesSizeX , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Opacity ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Opacity ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Opacity , FIntPoint ( PropertiesSizeX , PropertiesSizeX ) ) ;
2015-11-12 18:11:48 -05:00
}
2022-10-24 11:03:51 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : OpacityMask ) . Num ( ) & & MaterialSettings . bOpacityMaskMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : OpacityMask ) . X ! = PropertiesSizeX )
{
TArray < FColor > NewSamples ;
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : OpacityMask ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : OpacityMask ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : OpacityMask ) , PropertiesSizeX , PropertiesSizeX , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : OpacityMask ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : OpacityMask ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : OpacityMask , FIntPoint ( PropertiesSizeX , PropertiesSizeX ) ) ;
}
2015-11-12 18:11:48 -05:00
}
else if ( MaterialSettings . TextureSizingType = = TextureSizingType_UseManualOverrideTextureSize )
{
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Diffuse ) ! = MaterialSettings . DiffuseTextureSize )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Diffuse ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Diffuse ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Diffuse ) , MaterialSettings . DiffuseTextureSize . X , MaterialSettings . DiffuseTextureSize . Y , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Diffuse ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Diffuse ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Diffuse , MaterialSettings . DiffuseTextureSize ) ;
2015-11-12 18:11:48 -05:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Specular ) . Num ( ) & & MaterialSettings . bSpecularMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Specular ) ! = MaterialSettings . SpecularTextureSize )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Specular ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Specular ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Specular ) , MaterialSettings . SpecularTextureSize . X , MaterialSettings . SpecularTextureSize . Y , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Specular ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Specular ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Specular , MaterialSettings . SpecularTextureSize ) ;
2015-11-12 18:11:48 -05:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Metallic ) . Num ( ) & & MaterialSettings . bMetallicMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Metallic ) ! = MaterialSettings . MetallicTextureSize )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Metallic ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Metallic ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Metallic ) , MaterialSettings . MetallicTextureSize . X , MaterialSettings . MetallicTextureSize . Y , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Metallic ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Metallic ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Metallic , MaterialSettings . MetallicTextureSize ) ;
2015-11-12 18:11:48 -05:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Roughness ) . Num ( ) & & MaterialSettings . bRoughnessMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Roughness ) ! = MaterialSettings . RoughnessTextureSize )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Roughness ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Roughness ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Roughness ) , MaterialSettings . RoughnessTextureSize . X , MaterialSettings . RoughnessTextureSize . Y , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Roughness ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Roughness ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Roughness , MaterialSettings . RoughnessTextureSize ) ;
2015-11-12 18:11:48 -05:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Normal ) . Num ( ) & & MaterialSettings . bNormalMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Normal ) ! = MaterialSettings . NormalTextureSize )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Normal ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Normal ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Normal ) , MaterialSettings . NormalTextureSize . X , MaterialSettings . NormalTextureSize . Y , NewSamples , true ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Normal ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Normal ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Normal , MaterialSettings . NormalTextureSize ) ;
2015-11-12 18:11:48 -05:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Emissive ) . Num ( ) & & MaterialSettings . bEmissiveMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Emissive ) ! = MaterialSettings . EmissiveTextureSize )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Emissive ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Emissive ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Emissive ) , MaterialSettings . EmissiveTextureSize . X , MaterialSettings . EmissiveTextureSize . Y , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Emissive ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Emissive ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Emissive , MaterialSettings . EmissiveTextureSize ) ;
2015-11-12 18:11:48 -05:00
}
2016-09-22 15:33:34 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Opacity ) . Num ( ) & & MaterialSettings . bOpacityMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Opacity ) ! = MaterialSettings . OpacityTextureSize )
2015-11-12 18:11:48 -05:00
{
TArray < FColor > NewSamples ;
2016-09-22 15:33:34 -04:00
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Opacity ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Opacity ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Opacity ) , MaterialSettings . OpacityTextureSize . X , MaterialSettings . OpacityTextureSize . Y , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Opacity ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Opacity ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Opacity , MaterialSettings . OpacityTextureSize ) ;
2015-11-12 18:11:48 -05:00
}
2022-10-24 11:03:51 -04:00
if ( InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : OpacityMask ) . Num ( ) & & MaterialSettings . bOpacityMaskMap & & InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : OpacityMask ) ! = MaterialSettings . OpacityMaskTextureSize )
{
TArray < FColor > NewSamples ;
FImageUtils : : ImageResize ( InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : OpacityMask ) . X , InFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : OpacityMask ) . Y , InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : OpacityMask ) , MaterialSettings . OpacityMaskTextureSize . X , MaterialSettings . OpacityMaskTextureSize . Y , NewSamples , false ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : OpacityMask ) . Reset ( NewSamples . Num ( ) ) ;
InFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : OpacityMask ) . Append ( NewSamples ) ;
InFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : OpacityMask , MaterialSettings . OpacityMaskTextureSize ) ;
}
2015-11-12 18:11:48 -05:00
}
}
2016-04-04 18:44:59 -04:00
/** Computes the uniform scale from the input scales, if one exists. */
2016-10-20 20:09:22 -04:00
static float GetUniformScale ( const TArray < float > Scales )
2016-04-04 18:44:59 -04:00
{
if ( Scales . Num ( ) )
{
float Average = 0 ;
float Mean = 0 ;
for ( float V : Scales )
{
Average + = V ;
}
Average / = ( float ) Scales . Num ( ) ;
for ( float V : Scales )
{
Mean + = FMath : : Abs ( V - Average ) ;
}
Mean / = ( float ) Scales . Num ( ) ;
if ( Mean * 15.f < Average ) // If they are almost all the same
{
2016-10-20 20:09:22 -04:00
return Average ;
2016-04-04 18:44:59 -04:00
}
else // Otherwise do a much more expensive test by counting the number of similar values
{
// Try to find a small range where 80% of values fit within.
const int32 TryThreshold = FMath : : CeilToInt ( .80f * ( float ) Scales . Num ( ) ) ;
int32 NextTryDomain = Scales . Num ( ) ;
float NextTryMinV = 1024 ;
for ( float V : Scales )
{
NextTryMinV = FMath : : Min < float > ( V , NextTryMinV ) ;
}
while ( NextTryDomain > = TryThreshold ) // Stop the search it is garantied to fail.
{
float TryMinV = NextTryMinV ;
float TryMaxV = TryMinV * 1.25f ;
int32 TryMatches = 0 ;
NextTryMinV = 1024 ;
NextTryDomain = 0 ;
for ( float V : Scales )
{
if ( TryMinV < = V & & V < = TryMaxV )
{
+ + TryMatches ;
}
if ( V > TryMinV )
{
NextTryMinV = FMath : : Min < float > ( V , NextTryMinV ) ;
+ + NextTryDomain ;
}
}
if ( TryMatches > = TryThreshold )
{
2016-10-20 20:09:22 -04:00
return TryMinV ;
2016-04-04 18:44:59 -04:00
}
}
}
}
2016-10-20 20:09:22 -04:00
return 0 ;
2016-04-04 18:44:59 -04:00
}
2016-07-18 17:17:08 -04:00
uint32 GetTypeHash ( const FMaterialUtilities : : FExportErrorManager : : FError & Error )
{
return GetTypeHash ( Error . Material ) ;
}
bool FMaterialUtilities : : FExportErrorManager : : FError : : operator = = ( const FError & Rhs ) const
{
return Material = = Rhs . Material & & RegisterIndex = = Rhs . RegisterIndex & & ErrorType = = Rhs . ErrorType ;
}
2016-10-07 10:20:36 -04:00
void FMaterialUtilities : : FExportErrorManager : : Register ( const UMaterialInterface * Material , FName TextureName , int32 RegisterIndex , EErrorType ErrorType )
2016-07-18 17:17:08 -04:00
{
2016-10-07 10:20:36 -04:00
if ( ! Material | | TextureName = = NAME_None ) return ;
2016-07-18 17:17:08 -04:00
FError Error ;
Error . Material = Material - > GetMaterialResource ( FeatureLevel ) ;
if ( ! Error . Material ) return ;
Error . RegisterIndex = RegisterIndex ;
Error . ErrorType = ErrorType ;
FInstance Instance ;
Instance . Material = Material ;
2016-10-07 10:20:36 -04:00
Instance . TextureName = TextureName ;
2016-07-18 17:17:08 -04:00
ErrorInstances . FindOrAdd ( Error ) . Push ( Instance ) ;
}
void FMaterialUtilities : : FExportErrorManager : : OutputToLog ( )
{
const UMaterialInterface * CurrentMaterial = nullptr ;
int32 MaxInstanceCount = 0 ;
FString TextureErrors ;
for ( TMap < FError , TArray < FInstance > > : : TIterator It ( ErrorInstances ) ; ; + + It )
{
if ( It & & ! It - > Value . Num ( ) ) continue ;
// Here we pack texture list per material.
if ( ! It | | CurrentMaterial ! = It - > Value [ 0 ] . Material )
{
// Flush
if ( CurrentMaterial )
{
FString SimilarCount ( TEXT ( " " ) ) ;
if ( MaxInstanceCount > 1 )
{
SimilarCount = FString : : Printf ( TEXT ( " , %d similar " ) , MaxInstanceCount - 1 ) ;
}
if ( CurrentMaterial = = CurrentMaterial - > GetMaterial ( ) )
{
2016-08-18 20:28:33 -04:00
UE_LOG ( TextureStreamingBuild , Verbose , TEXT ( " Incomplete texcoord scale analysis for %s%s: %s " ) , * CurrentMaterial - > GetName ( ) , * SimilarCount , * TextureErrors ) ;
2016-07-18 17:17:08 -04:00
}
else
{
2016-08-18 20:28:33 -04:00
UE_LOG ( TextureStreamingBuild , Verbose , TEXT ( " Incomplete texcoord scale analysis for %s, UMaterial=%s%s: %s " ) , * CurrentMaterial - > GetName ( ) , * CurrentMaterial - > GetMaterial ( ) - > GetName ( ) , * SimilarCount , * TextureErrors ) ;
2016-07-18 17:17:08 -04:00
}
}
// Exit
if ( ! It )
{
break ;
}
// Start new
CurrentMaterial = It - > Value [ 0 ] . Material ;
MaxInstanceCount = It - > Value . Num ( ) ;
TextureErrors . Empty ( ) ;
}
else
{
// Append
MaxInstanceCount = FMath : : Max < int32 > ( MaxInstanceCount , It - > Value . Num ( ) ) ;
}
const TCHAR * ErrorMsg = TEXT ( " Unkown Error " ) ;
if ( It - > Key . ErrorType = = EET_IncohorentValues )
{
ErrorMsg = TEXT ( " Incoherent " ) ;
}
else if ( It - > Key . ErrorType = = EET_NoValues )
{
ErrorMsg = TEXT ( " NoValues " ) ;
}
2016-10-07 10:20:36 -04:00
TextureErrors . Append ( FString : : Printf ( TEXT ( " (%s:%d,%s) " ) , ErrorMsg , It - > Key . RegisterIndex , * It - > Value [ 0 ] . TextureName . ToString ( ) ) ) ;
2016-07-18 17:17:08 -04:00
}
}
2016-10-20 20:09:22 -04:00
bool FMaterialUtilities : : ExportMaterialUVDensities ( UMaterialInterface * InMaterial , EMaterialQualityLevel : : Type QualityLevel , ERHIFeatureLevel : : Type FeatureLevel , FExportErrorManager & OutErrors )
2016-04-04 18:44:59 -04:00
{
2016-10-20 20:09:22 -04:00
check ( InMaterial ) ;
// Clear the build data.
TArray < FMaterialTextureInfo > TextureStreamingData ;
InMaterial - > SetTextureStreamingData ( TextureStreamingData ) ;
2016-04-04 18:44:59 -04:00
TArray < FFloat16Color > RenderedVectors ;
TArray < UTexture * > Textures ;
TArray < TArray < int32 > > Indices ;
InMaterial - > GetUsedTexturesAndIndices ( Textures , Indices , QualityLevel , FeatureLevel ) ;
2020-06-16 22:16:25 -04:00
FTextureCompilingManager : : Get ( ) . FinishCompilation ( Textures ) ;
2016-04-04 18:44:59 -04:00
check ( Textures . Num ( ) > = Indices . Num ( ) ) ; // Can't have indices if no texture.
const int32 SCALE_PRECISION = 64.f ;
int32 MaxRegisterIndex = INDEX_NONE ;
for ( const TArray < int32 > & TextureIndices : Indices )
{
for ( int32 RegisterIndex : TextureIndices )
{
MaxRegisterIndex = FMath : : Max < int32 > ( RegisterIndex , MaxRegisterIndex ) ;
}
}
if ( MaxRegisterIndex = = INDEX_NONE )
{
return false ;
}
2016-10-20 20:09:22 -04:00
// Find the streaming texture for each material texture register index.
TArray < UTexture2D * > RegisterIndexToTextures ;
RegisterIndexToTextures . AddZeroed ( MaxRegisterIndex + 1 ) ;
for ( int32 TextureIndex = 0 ; TextureIndex < Textures . Num ( ) ; + + TextureIndex )
2016-04-04 18:44:59 -04:00
{
2016-10-20 20:09:22 -04:00
UTexture2D * Texture2D = Cast < UTexture2D > ( Textures [ TextureIndex ] ) ;
if ( Texture2D ) // Don't check IsStreamingTexture() yet as this could change before cooking.
2016-04-04 18:44:59 -04:00
{
2016-10-20 20:09:22 -04:00
for ( int32 RegisterIndex : Indices [ TextureIndex ] )
{
RegisterIndexToTextures [ RegisterIndex ] = Texture2D ;
}
2016-04-04 18:44:59 -04:00
}
}
const int32 NumTileX = ( MaxRegisterIndex / 4 + 1 ) ;
2016-10-07 10:20:36 -04:00
const int32 NumTileY = TEXSTREAM_MAX_NUM_UVCHANNELS ;
FIntPoint RenderTargetSize ( TEXSTREAM_TILE_RESOLUTION * NumTileX , TEXSTREAM_TILE_RESOLUTION * NumTileY ) ;
2016-04-04 18:44:59 -04:00
// Render the vectors
{
// The rendertarget contain factors stored in XYZW. Every X tile maps to another group : (0, 1, 2, 3), (4, 5, 6, 7), ...
UTextureRenderTarget2D * RenderTarget = CreateRenderTarget ( true , false , PF_FloatRGBA , RenderTargetSize ) ;
// Allocate the render output.
RenderedVectors . Empty ( RenderTargetSize . X * RenderTargetSize . Y ) ;
2018-12-11 22:25:04 -05:00
FMaterialRenderProxy * MaterialProxy = InMaterial - > GetRenderProxy ( ) ;
2016-04-04 18:44:59 -04:00
if ( ! MaterialProxy )
{
return false ;
}
FBox2D DummyBounds ( FVector2D ( 0 , 0 ) , FVector2D ( 1 , 1 ) ) ;
TArray < FVector2D > EmptyTexCoords ;
FMaterialMergeData MaterialData ( InMaterial , nullptr , nullptr , 0 , DummyBounds , EmptyTexCoords ) ;
CurrentlyRendering = true ;
bool bResult = FMeshRenderer : : RenderMaterialTexCoordScales ( MaterialData , MaterialProxy , RenderTarget , RenderedVectors ) ;
CurrentlyRendering = false ;
if ( ! bResult )
{
return false ;
}
}
2016-10-20 20:09:22 -04:00
// Now compute the scale for each texture index (several indices could map to the same texture)
2016-04-04 18:44:59 -04:00
for ( int32 RegisterIndex = 0 ; RegisterIndex < = MaxRegisterIndex ; + + RegisterIndex )
{
2016-10-20 20:09:22 -04:00
UTexture2D * Texture2D = RegisterIndexToTextures [ RegisterIndex ] ;
if ( ! Texture2D ) continue ; // Only handle streaming textures
2016-04-04 18:44:59 -04:00
int32 TextureTile = RegisterIndex / 4 ;
int32 ComponentIndex = RegisterIndex % 4 ;
bool bSuccess = false ;
2016-10-20 20:09:22 -04:00
bool bHadAnyValues = false ;
2016-10-07 10:20:36 -04:00
for ( int32 CoordIndex = 0 ; CoordIndex < TEXSTREAM_MAX_NUM_UVCHANNELS & & ! bSuccess ; + + CoordIndex )
2016-04-04 18:44:59 -04:00
{
2016-10-20 20:09:22 -04:00
TArray < float > TextureScales ;
TextureScales . Empty ( TEXSTREAM_TILE_RESOLUTION * TEXSTREAM_TILE_RESOLUTION ) ;
2016-10-07 10:20:36 -04:00
for ( int32 TexelX = 0 ; TexelX < TEXSTREAM_TILE_RESOLUTION ; + + TexelX )
2016-04-04 18:44:59 -04:00
{
2016-10-07 10:20:36 -04:00
for ( int32 TexelY = 0 ; TexelY < TEXSTREAM_TILE_RESOLUTION ; + + TexelY )
2016-04-04 18:44:59 -04:00
{
2016-10-07 10:20:36 -04:00
int32 TexelIndex = TextureTile * TEXSTREAM_TILE_RESOLUTION + TexelX + ( TexelY + CoordIndex * TEXSTREAM_TILE_RESOLUTION ) * RenderTargetSize . X ;
2016-04-04 18:44:59 -04:00
FFloat16Color & Scale16 = RenderedVectors [ TexelIndex ] ;
float TexelScale = 0 ;
if ( ComponentIndex = = 0 ) TexelScale = Scale16 . R . GetFloat ( ) ;
if ( ComponentIndex = = 1 ) TexelScale = Scale16 . G . GetFloat ( ) ;
if ( ComponentIndex = = 2 ) TexelScale = Scale16 . B . GetFloat ( ) ;
if ( ComponentIndex = = 3 ) TexelScale = Scale16 . A . GetFloat ( ) ;
// Quantize scale to converge faster in the TryLogic
TexelScale = FMath : : RoundToFloat ( TexelScale * SCALE_PRECISION ) / SCALE_PRECISION ;
2016-10-07 10:20:36 -04:00
if ( TexelScale > 0 & & TexelScale < TEXSTREAM_INITIAL_GPU_SCALE )
2016-04-04 18:44:59 -04:00
{
2016-10-20 20:09:22 -04:00
TextureScales . Push ( TexelScale ) ;
2016-04-04 18:44:59 -04:00
}
}
}
2016-10-20 20:09:22 -04:00
const float SamplingScale = GetUniformScale ( TextureScales ) ;
if ( SamplingScale > 0 )
2016-04-04 18:44:59 -04:00
{
2016-10-20 20:09:22 -04:00
FMaterialTextureInfo TextureInfo ;
TextureInfo . SamplingScale = SamplingScale ;
2016-10-07 10:20:36 -04:00
TextureInfo . UVChannelIndex = CoordIndex ;
2017-08-11 12:43:42 -04:00
TextureInfo . TextureReference = FSoftObjectPath ( Texture2D ) ;
2016-10-20 20:09:22 -04:00
TextureInfo . TextureIndex = RegisterIndex ;
TextureStreamingData . Add ( TextureInfo ) ;
2016-04-04 18:44:59 -04:00
bSuccess = true ;
}
2016-10-20 20:09:22 -04:00
else if ( TextureScales . Num ( ) )
{
bHadAnyValues = true ;
}
2016-04-04 18:44:59 -04:00
}
// If we couldn't find the scale, then output a warning detailing which index, texture, material is having an issue.
if ( ! bSuccess )
{
2016-10-20 20:09:22 -04:00
OutErrors . Register ( InMaterial , Texture2D - > GetFName ( ) , RegisterIndex , bHadAnyValues ? FExportErrorManager : : EErrorType : : EET_IncohorentValues : FExportErrorManager : : EErrorType : : EET_NoValues ) ;
2016-04-04 18:44:59 -04:00
}
}
2016-10-20 20:09:22 -04:00
// Update to the final data.
InMaterial - > SetTextureStreamingData ( TextureStreamingData ) ;
2016-04-04 18:44:59 -04:00
return true ;
}
2015-10-28 19:18:20 -04:00
bool FMaterialUtilities : : ExportMaterial ( struct FMaterialMergeData & InMaterialData , FFlattenMaterial & OutFlattenMaterial , struct FExportMaterialProxyCache * ProxyCache )
{
UMaterialInterface * Material = InMaterialData . Material ;
UE_LOG ( LogMaterialUtilities , Log , TEXT ( " Flattening material: %s " ) , * Material - > GetName ( ) ) ;
if ( ProxyCache )
{
// ExportMaterial was called with non-null CompiledMaterial. This means compiled shaders
// should be stored outside, and could be re-used in next call to ExportMaterial.
// FMaterialData already has "proxy cache" fiels, should swap it with CompiledMaterial,
// and swap back before returning from this function.
// Purpose of the following line: use compiled material cached from previous call.
Exchange ( ProxyCache , InMaterialData . ProxyCache ) ;
}
2016-02-04 10:55:30 -05:00
2015-10-28 19:18:20 -04:00
// Precache all used textures, otherwise could get everything rendered with low-res textures.
TArray < UTexture * > MaterialTextures ;
Material - > GetUsedTextures ( MaterialTextures , EMaterialQualityLevel : : Num , true , GMaxRHIFeatureLevel , true ) ;
2020-06-16 22:16:25 -04:00
FTextureCompilingManager : : Get ( ) . FinishCompilation ( MaterialTextures ) ;
2015-10-28 19:18:20 -04:00
for ( UTexture * Texture : MaterialTextures )
{
if ( Texture ! = NULL )
{
UTexture2D * Texture2D = Cast < UTexture2D > ( Texture ) ;
if ( Texture2D )
{
Texture2D - > SetForceMipLevelsToBeResident ( 30.0f , true ) ;
Texture2D - > WaitForStreaming ( ) ;
}
}
}
// Determine whether or not certain properties can be rendered
2016-09-22 15:33:34 -04:00
const bool bRenderNormal = ( Material - > GetMaterial ( ) - > HasNormalConnected ( ) | | Material - > GetMaterial ( ) - > bUseMaterialAttributes ) & & OutFlattenMaterial . ShouldGenerateDataForProperty ( EFlattenMaterialProperties : : Normal ) ;
2022-05-04 12:21:52 -04:00
const bool bRenderTangent = ( Material - > GetMaterial ( ) - > IsPropertyConnected ( MP_Tangent ) | | Material - > GetMaterial ( ) - > bUseMaterialAttributes ) & & OutFlattenMaterial . ShouldGenerateDataForProperty ( EFlattenMaterialProperties : : Tangent ) ;
const bool bRenderEmissive = ( Material - > GetMaterial ( ) - > IsPropertyConnected ( MP_EmissiveColor ) | | Material - > GetMaterial ( ) - > bUseMaterialAttributes ) & & OutFlattenMaterial . ShouldGenerateDataForProperty ( EFlattenMaterialProperties : : Emissive ) ;
2022-12-13 10:44:43 -05:00
const bool bRenderOpacityMask = Material - > IsPropertyActive ( MP_OpacityMask ) & & IsMaskedBlendMode ( * Material ) & & OutFlattenMaterial . ShouldGenerateDataForProperty ( EFlattenMaterialProperties : : OpacityMask ) ;
const bool bRenderOpacity = Material - > IsPropertyActive ( MP_Opacity ) & & IsTranslucentBlendMode ( * Material ) & & OutFlattenMaterial . ShouldGenerateDataForProperty ( EFlattenMaterialProperties : : Opacity ) ;
2016-09-22 15:33:34 -04:00
const bool bRenderSubSurface = Material - > IsPropertyActive ( MP_SubsurfaceColor ) & & OutFlattenMaterial . ShouldGenerateDataForProperty ( EFlattenMaterialProperties : : SubSurface ) ;
const bool bRenderMetallic = Material - > IsPropertyActive ( MP_Metallic ) & & OutFlattenMaterial . ShouldGenerateDataForProperty ( EFlattenMaterialProperties : : Metallic ) ;
const bool bRenderSpecular = Material - > IsPropertyActive ( MP_Specular ) & & OutFlattenMaterial . ShouldGenerateDataForProperty ( EFlattenMaterialProperties : : Specular ) ;
const bool bRenderRoughness = Material - > IsPropertyActive ( MP_Roughness ) & & OutFlattenMaterial . ShouldGenerateDataForProperty ( EFlattenMaterialProperties : : Roughness ) ;
2020-02-12 13:27:19 -05:00
const bool bRenderAnisotropy = Material - > IsPropertyActive ( MP_Anisotropy ) & & OutFlattenMaterial . ShouldGenerateDataForProperty ( EFlattenMaterialProperties : : Anisotropy ) ;
2015-11-12 18:11:48 -05:00
2015-10-28 19:18:20 -04:00
check ( ! bRenderOpacity | | ! bRenderOpacityMask ) ;
2016-09-22 15:33:34 -04:00
FIntPoint Size ;
2016-10-06 12:11:11 -04:00
// Compile shaders and render flatten material.
2016-09-22 15:33:34 -04:00
Size = OutFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Diffuse ) ;
2017-12-13 16:02:45 -05:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2016-09-22 15:33:34 -04:00
RenderMaterialPropertyToTexture ( InMaterialData , MP_BaseColor , false , PF_B8G8R8A8 , OutFlattenMaterial . RenderSize , Size , OutFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Diffuse ) ) ;
2017-12-13 16:02:45 -05:00
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2016-09-22 15:33:34 -04:00
OutFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Diffuse , Size ) ;
2015-11-12 18:11:48 -05:00
if ( bRenderMetallic )
{
2016-09-22 15:33:34 -04:00
Size = OutFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Metallic ) ;
2017-12-13 16:02:45 -05:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
RenderMaterialPropertyToTexture ( InMaterialData , MP_Metallic , false , PF_B8G8R8A8 , OutFlattenMaterial . RenderSize , Size ,
OutFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Metallic ) ) ;
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2016-09-22 15:33:34 -04:00
OutFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Metallic , Size ) ;
2020-02-12 13:27:19 -05:00
}
2015-11-12 18:11:48 -05:00
if ( bRenderSpecular )
{
2016-09-22 15:33:34 -04:00
Size = OutFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Specular ) ;
2017-12-13 16:02:45 -05:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2016-09-22 15:33:34 -04:00
RenderMaterialPropertyToTexture ( InMaterialData , MP_Specular , false , PF_B8G8R8A8 , OutFlattenMaterial . RenderSize , Size , OutFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Specular ) ) ;
2017-12-13 16:02:45 -05:00
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2016-09-22 15:33:34 -04:00
OutFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Specular , Size ) ;
2015-11-12 18:11:48 -05:00
}
2020-02-12 13:27:19 -05:00
2015-11-12 18:11:48 -05:00
if ( bRenderRoughness )
{
2016-09-22 15:33:34 -04:00
Size = OutFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Roughness ) ;
2017-12-13 16:02:45 -05:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2016-09-22 15:33:34 -04:00
RenderMaterialPropertyToTexture ( InMaterialData , MP_Roughness , false , PF_B8G8R8A8 , OutFlattenMaterial . RenderSize , Size , OutFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Roughness ) ) ;
2017-12-13 16:02:45 -05:00
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2016-09-22 15:33:34 -04:00
OutFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Roughness , Size ) ;
2015-11-12 18:11:48 -05:00
}
2020-02-12 13:27:19 -05:00
if ( bRenderAnisotropy )
{
Size = OutFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Anisotropy ) ;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
RenderMaterialPropertyToTexture ( InMaterialData , MP_Anisotropy , false , PF_B8G8R8A8 , OutFlattenMaterial . RenderSize , Size , OutFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Anisotropy ) ) ;
PRAGMA_ENABLE_DEPRECATION_WARNINGS
OutFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Anisotropy , Size ) ;
}
2015-10-28 19:18:20 -04:00
if ( bRenderNormal )
{
2016-09-22 15:33:34 -04:00
Size = OutFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Normal ) ;
2017-12-13 16:02:45 -05:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2016-09-22 15:33:34 -04:00
RenderMaterialPropertyToTexture ( InMaterialData , MP_Normal , true , PF_B8G8R8A8 , OutFlattenMaterial . RenderSize , Size , OutFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Normal ) ) ;
2017-12-13 16:02:45 -05:00
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2016-09-22 15:33:34 -04:00
OutFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Normal , Size ) ;
2015-10-28 19:18:20 -04:00
}
2016-10-06 12:11:11 -04:00
else
{
// Make sure we output a default normal value in case the material does not generate one (to prevent issues with combining meshes with and without normal maps being atlassed together)
TArray < FColor > & Samples = OutFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Normal ) ;
Samples . Add ( FColor ( 128 , 128 , 255 ) ) ;
OutFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Normal , FIntPoint ( 1 , 1 ) ) ;
}
2020-02-12 13:27:19 -05:00
if ( bRenderTangent )
{
Size = OutFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Tangent ) ;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
RenderMaterialPropertyToTexture ( InMaterialData , MP_Tangent , true , PF_B8G8R8A8 , OutFlattenMaterial . RenderSize , Size , OutFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Tangent ) ) ;
PRAGMA_ENABLE_DEPRECATION_WARNINGS
OutFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Tangent , Size ) ;
}
else
{
// Make sure we output a default tangent value in case the material does not generate one (to prevent issues with combining meshes with and without tangent maps being atlassed together)
TArray < FColor > & Samples = OutFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Tangent ) ;
Samples . Add ( FColor ( 255 , 128 , 128 ) ) ;
OutFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Tangent , FIntPoint ( 1 , 1 ) ) ;
}
2015-10-28 19:18:20 -04:00
if ( bRenderOpacityMask )
{
2017-12-13 16:02:45 -05:00
Size = OutFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : OpacityMask ) ;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
RenderMaterialPropertyToTexture ( InMaterialData , MP_OpacityMask , true , PF_B8G8R8A8 , OutFlattenMaterial . RenderSize , Size , OutFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : OpacityMask ) ) ;
PRAGMA_ENABLE_DEPRECATION_WARNINGS
OutFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : OpacityMask , Size ) ;
2015-10-28 19:18:20 -04:00
}
2022-10-24 11:03:51 -04:00
2015-10-28 19:18:20 -04:00
if ( bRenderOpacity )
{
2016-09-22 15:33:34 -04:00
Size = OutFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Opacity ) ;
2015-10-28 19:18:20 -04:00
// Number of blend modes, let's UMaterial decide whether it wants this property
2017-12-13 16:02:45 -05:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2016-09-22 15:33:34 -04:00
RenderMaterialPropertyToTexture ( InMaterialData , MP_Opacity , true , PF_B8G8R8A8 , OutFlattenMaterial . RenderSize , Size , OutFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Opacity ) ) ;
2017-12-13 16:02:45 -05:00
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2016-09-22 15:33:34 -04:00
OutFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Opacity , Size ) ;
2015-10-28 19:18:20 -04:00
}
2022-10-24 11:03:51 -04:00
2015-10-28 19:18:20 -04:00
if ( bRenderEmissive )
{
2016-09-22 15:33:34 -04:00
Size = OutFlattenMaterial . GetPropertySize ( EFlattenMaterialProperties : : Emissive ) ;
2015-10-28 19:18:20 -04:00
// PF_FloatRGBA is here to be able to render and read HDR image using ReadFloat16Pixels()
2017-12-13 16:02:45 -05:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2016-09-22 15:33:34 -04:00
RenderMaterialPropertyToTexture ( InMaterialData , MP_EmissiveColor , false , PF_FloatRGBA , OutFlattenMaterial . RenderSize , Size , OutFlattenMaterial . GetPropertySamples ( EFlattenMaterialProperties : : Emissive ) ) ;
2017-12-13 16:02:45 -05:00
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2015-10-28 19:18:20 -04:00
OutFlattenMaterial . EmissiveScale = InMaterialData . EmissiveScale ;
2016-09-22 15:33:34 -04:00
OutFlattenMaterial . SetPropertySize ( EFlattenMaterialProperties : : Emissive , Size ) ;
2016-10-06 12:11:11 -04:00
}
2015-10-28 19:18:20 -04:00
2015-11-12 18:11:48 -05:00
if ( bRenderSubSurface )
{
// TODO support rendering out sub surface color property
/*RenderMaterialPropertyToTexture(InMaterialData, MP_SubsurfaceColor, false, PF_B8G8R8A8, OutFlattenMaterial.RenderSize, OutFlattenMaterial.SubSurfaceSize, OutFlattenMaterial.SubSurfaceSamples);*/
}
2015-10-28 19:18:20 -04:00
OutFlattenMaterial . MaterialId = Material - > GetLightingGuid ( ) ;
// Swap back the proxy cache
if ( ProxyCache )
{
// Store compiled material to external cache.
Exchange ( ProxyCache , InMaterialData . ProxyCache ) ;
}
UE_LOG ( LogMaterialUtilities , Log , TEXT ( " Material flattening done. (%s) " ) , * Material - > GetName ( ) ) ;
return true ;
}
2016-09-22 15:33:34 -04:00
bool FMaterialUtilities : : RenderMaterialPropertyToTexture ( struct FMaterialMergeData & InMaterialData , EMaterialProperty InMaterialProperty , bool bInForceLinearGamma , EPixelFormat InPixelFormat , const FIntPoint InTargetSize , FIntPoint & OutSampleSize , TArray < FColor > & OutSamples )
2015-10-28 19:18:20 -04:00
{
if ( InTargetSize . X = = 0 | | InTargetSize . Y = = 0 )
{
return false ;
}
2015-11-12 18:11:48 -05:00
OutSampleSize = InTargetSize ;
2015-10-28 19:18:20 -04:00
FMaterialRenderProxy * MaterialProxy = nullptr ;
2019-09-28 08:19:35 -04:00
check ( InMaterialProperty > = 0 & & InMaterialProperty < UE_ARRAY_COUNT ( InMaterialData . ProxyCache - > Proxies ) ) ;
2015-10-28 19:18:20 -04:00
if ( InMaterialData . ProxyCache - > Proxies [ InMaterialProperty ] )
{
MaterialProxy = InMaterialData . ProxyCache - > Proxies [ InMaterialProperty ] ;
}
else
{
MaterialProxy = InMaterialData . ProxyCache - > Proxies [ InMaterialProperty ] = new FExportMaterialProxy ( InMaterialData . Material , InMaterialProperty ) ;
}
if ( MaterialProxy = = nullptr )
{
return false ;
}
// Disallow garbage collection of RenderTarget.
check ( CurrentlyRendering = = false ) ;
CurrentlyRendering = true ;
2016-02-04 10:55:30 -05:00
const bool bNormalMap = ( InMaterialProperty = = MP_Normal ) ;
UTextureRenderTarget2D * RenderTarget = CreateRenderTarget ( bInForceLinearGamma , bNormalMap , InPixelFormat , OutSampleSize ) ;
2015-10-28 19:18:20 -04:00
OutSamples . Empty ( InTargetSize . X * InTargetSize . Y ) ;
bool bResult = FMeshRenderer : : RenderMaterial (
InMaterialData ,
MaterialProxy ,
InMaterialProperty ,
RenderTarget ,
OutSamples ) ;
2016-01-14 08:11:47 -05:00
/** Disabled for now, see comment below */
2015-10-28 19:18:20 -04:00
// Check for uniform value, perhaps this can be determined before rendering the material, see WillGenerateUniformData (LightmassRender)
2016-01-14 08:11:47 -05:00
/*bool bIsUniform = true;
2015-10-28 19:18:20 -04:00
FColor MaxColor(0, 0, 0, 0);
if (bResult)
{
// Find maximal color value
int32 MaxColorValue = 0;
for (int32 Index = 0; Index < OutSamples.Num(); Index++)
{
FColor Color = OutSamples[Index];
int32 ColorValue = Color.R + Color.G + Color.B + Color.A;
if (ColorValue > MaxColorValue)
{
MaxColorValue = ColorValue;
MaxColor = Color;
}
}
// Fill background with maximal color value and render again
RenderTarget->ClearColor = FLinearColor(MaxColor);
TArray<FColor> OutSamples2;
FMeshRenderer::RenderMaterial(
InMaterialData,
MaterialProxy,
InMaterialProperty,
RenderTarget,
OutSamples2);
for (int32 Index = 0; Index < OutSamples2.Num(); Index++)
{
FColor Color = OutSamples2[Index];
if (Color != MaxColor)
{
bIsUniform = false;
break;
}
}
}
// Uniform value
if (bIsUniform)
{
2015-11-12 18:11:48 -05:00
OutSampleSize = FIntPoint(1, 1);
2015-10-28 19:18:20 -04:00
OutSamples.Empty();
OutSamples.Add(MaxColor);
2016-01-14 08:11:47 -05:00
}*/
2015-10-28 19:18:20 -04:00
CurrentlyRendering = false ;
return bResult ;
}
2016-02-04 10:55:30 -05:00
UTextureRenderTarget2D * FMaterialUtilities : : CreateRenderTarget ( bool bInForceLinearGamma , bool bNormalMap , EPixelFormat InPixelFormat , FIntPoint & InTargetSize )
2015-10-28 19:18:20 -04:00
{
2016-02-04 10:55:30 -05:00
const FLinearColor ClearColour = bNormalMap ? FLinearColor ( 0.0f , 0.0f , 0.0f , 0.0f ) : FLinearColor ( 1.0f , 0.0f , 1.0f , 0.0f ) ;
2015-10-28 19:18:20 -04:00
// Find any pooled render target with suitable properties.
for ( int32 RTIndex = 0 ; RTIndex < RenderTargetPool . Num ( ) ; RTIndex + + )
{
UTextureRenderTarget2D * RenderTarget = RenderTargetPool [ RTIndex ] ;
if ( RenderTarget - > SizeX = = InTargetSize . X & &
RenderTarget - > SizeY = = InTargetSize . Y & &
RenderTarget - > OverrideFormat = = InPixelFormat & &
2016-02-04 10:55:30 -05:00
RenderTarget - > bForceLinearGamma = = bInForceLinearGamma & &
2016-10-06 12:11:11 -04:00
RenderTarget - > ClearColor = = ClearColour )
2015-10-28 19:18:20 -04:00
{
return RenderTarget ;
}
}
// Not found - create a new one.
UTextureRenderTarget2D * NewRenderTarget = NewObject < UTextureRenderTarget2D > ( ) ;
check ( NewRenderTarget ) ;
NewRenderTarget - > AddToRoot ( ) ;
2016-02-04 10:55:30 -05:00
NewRenderTarget - > ClearColor = ClearColour ;
2015-10-28 19:18:20 -04:00
NewRenderTarget - > TargetGamma = 0.0f ;
NewRenderTarget - > InitCustomFormat ( InTargetSize . X , InTargetSize . Y , InPixelFormat , bInForceLinearGamma ) ;
RenderTargetPool . Add ( NewRenderTarget ) ;
return NewRenderTarget ;
}
void FMaterialUtilities : : ClearRenderTargetPool ( )
{
if ( CurrentlyRendering )
{
// Just in case - if garbage collection will happen during rendering, don't allow to GC used render target.
return ;
}
// Allow garbage collecting of all render targets.
for ( int32 RTIndex = 0 ; RTIndex < RenderTargetPool . Num ( ) ; RTIndex + + )
{
RenderTargetPool [ RTIndex ] - > RemoveFromRoot ( ) ;
}
RenderTargetPool . Empty ( ) ;
}
void FMaterialUtilities : : OptimizeSampleArray ( TArray < FColor > & InSamples , FIntPoint & InSampleSize )
{
if ( InSamples . Num ( ) > 1 )
{
2017-06-21 10:25:35 -04:00
TArray < FColor > Colors ;
for ( const FColor & Sample : InSamples )
{
if ( Colors . AddUnique ( Sample ) ! = 0 )
{
break ;
}
}
if ( Colors . Num ( ) = = 1 )
{
InSamples . Empty ( 1 ) ;
InSamples . Add ( Colors [ 0 ] ) ;
InSampleSize = FIntPoint ( 1 , 1 ) ;
}
2016-10-06 12:11:11 -04:00
}
2015-10-28 19:18:20 -04:00
}
FExportMaterialProxyCache : : FExportMaterialProxyCache ( )
{
FMemory : : Memzero ( Proxies ) ;
}
FExportMaterialProxyCache : : ~ FExportMaterialProxyCache ( )
{
Release ( ) ;
}
void FExportMaterialProxyCache : : Release ( )
{
2019-09-28 08:19:35 -04:00
for ( int32 PropertyIndex = 0 ; PropertyIndex < UE_ARRAY_COUNT ( Proxies ) ; PropertyIndex + + )
2015-10-28 19:18:20 -04:00
{
FMaterialRenderProxy * Proxy = Proxies [ PropertyIndex ] ;
if ( Proxy )
{
delete Proxy ;
Proxies [ PropertyIndex ] = nullptr ;
}
}
}
2015-09-24 09:04:18 -04:00
2016-09-22 15:33:34 -04:00
void FMaterialUtilities : : DetermineMaterialImportance ( const TArray < UMaterialInterface * > & InMaterials , TArray < float > & OutImportance )
{
TArray < int32 > MaterialImportance ;
int32 SummedSize = 0 ;
for ( UMaterialInterface * Material : InMaterials )
{
2020-02-06 13:13:41 -05:00
TArray < UObject * > UsedTextures ( Material - > GetReferencedTextures ( ) ) ;
2016-09-22 15:33:34 -04:00
if ( UMaterialInstance * MaterialInstance = Cast < UMaterialInstance > ( Material ) )
{
for ( const FTextureParameterValue & TextureParameter : MaterialInstance - > TextureParameterValues )
{
if ( TextureParameter . ParameterValue ! = nullptr )
{
UsedTextures . Add ( TextureParameter . ParameterValue ) ;
}
}
}
int32 MaxSize = 64 * 64 ;
2019-06-11 18:27:07 -04:00
for ( UObject * Texture : UsedTextures )
2016-09-22 15:33:34 -04:00
{
if ( UTexture2D * Texture2D = Cast < UTexture2D > ( Texture ) )
{
2017-09-09 16:29:11 -04:00
const int32 MaxResMipBias = Texture2D - > GetNumMips ( ) - Texture2D - > GetNumMipsAllowed ( true ) ;
const int32 MaxResSize = FMath : : Max < int32 > ( Texture2D - > GetSizeX ( ) > > MaxResMipBias , 1 ) * FMath : : Max < int32 > ( Texture2D - > GetSizeY ( ) > > MaxResMipBias , 1 ) ;
MaxSize = FMath : : Max < int32 > ( MaxSize , MaxResSize ) ;
2016-09-22 15:33:34 -04:00
}
}
MaterialImportance . Add ( MaxSize ) ;
SummedSize + = MaxSize ;
}
float WeightPerPixel = 1.0f / SummedSize ;
for ( int32 MaterialIndex = 0 ; MaterialIndex < InMaterials . Num ( ) ; + + MaterialIndex )
{
OutImportance . Add ( ( float ) MaterialImportance [ MaterialIndex ] * WeightPerPixel ) ;
}
}
void FMaterialUtilities : : GeneratedBinnedTextureSquares ( const FVector2D DestinationSize , TArray < float > & InTexureWeights , TArray < FBox2D > & OutGeneratedBoxes )
{
typedef FBox2D FTextureArea ;
struct FWeightedTexture
{
FTextureArea Area ;
int32 TextureIndex ;
float Weight ;
} ;
TArray < FWeightedTexture > WeightedTextures ;
const float TotalArea = DestinationSize . X * DestinationSize . Y ;
// Generate textures with their size calculated according to their weight
for ( int32 WeightIndex = 0 ; WeightIndex < InTexureWeights . Num ( ) ; + + WeightIndex )
{
const float Weight = InTexureWeights [ WeightIndex ] ;
FWeightedTexture Texture ;
float TextureSize = FMath : : Sqrt ( TotalArea * Weight ) ;
Texture . Area = FTextureArea ( FVector2D ( 0.0f , 0.0f ) , FVector2D ( TextureSize , TextureSize ) ) ;
Texture . TextureIndex = WeightIndex ;
Texture . Weight = Weight ;
WeightedTextures . Add ( Texture ) ;
}
// Sort textures by their weight (high to low) which influences the insert order
WeightedTextures . Sort ( [ ] ( const FWeightedTexture & One , const FWeightedTexture & Two ) { return One . Weight > Two . Weight ; } ) ;
TArray < FWeightedTexture > InsertedTextures ;
typedef FBox2D FUnusedArea ;
TArray < FUnusedArea > UnusedAreas ;
bool bSuccess = true ;
do
{
// Reset state
bSuccess = true ;
UnusedAreas . Empty ( ) ;
InsertedTextures . Empty ( ) ;
FUnusedArea StartArea ( FVector2D ( 0 , 0 ) , DestinationSize ) ;
UnusedAreas . Add ( StartArea ) ;
for ( const FWeightedTexture & Texture : WeightedTextures )
{
int32 BestAreaIndex = - 1 ;
float RemainingArea = FLT_MAX ;
FVector2D TextureSize = Texture . Area . GetSize ( ) ;
float TextureSurface = TextureSize . X * TextureSize . Y ;
// Find best area to insert this texture in (determined by tightest fit)
for ( int32 AreaIndex = 0 ; AreaIndex < UnusedAreas . Num ( ) ; + + AreaIndex )
{
const FUnusedArea & UnusedArea = UnusedAreas [ AreaIndex ] ;
2022-07-20 18:23:11 -04:00
if ( UnusedArea . GetSize ( ) . ComponentwiseAllGreaterOrEqual ( TextureSize ) )
2016-09-22 15:33:34 -04:00
{
const float Remainder = UnusedArea . GetArea ( ) - TextureSurface ;
if ( Remainder < RemainingArea & & Remainder > = 0 )
{
BestAreaIndex = AreaIndex ;
RemainingArea = Remainder ;
}
}
}
// Insert the texture in case we found an appropriate area
if ( BestAreaIndex ! = - 1 )
{
FUnusedArea & UnusedArea = UnusedAreas [ BestAreaIndex ] ;
FVector2D UnusedSize = UnusedArea . GetSize ( ) ;
// Push back texture
FWeightedTexture WeightedTexture ;
WeightedTexture . Area = FTextureArea ( UnusedArea . Min , UnusedArea . Min + TextureSize ) ;
WeightedTexture . TextureIndex = Texture . TextureIndex ;
InsertedTextures . Add ( WeightedTexture ) ;
// Generate two new resulting unused areas from splitting up the result
/*
___________
| | |
| | V |
|_____| |
| H | |
|_____|___|
*/
FUnusedArea HorizontalArea , VerticalArea ;
HorizontalArea . Min . X = UnusedArea . Min . X ;
HorizontalArea . Min . Y = UnusedArea . Min . Y + TextureSize . Y ;
HorizontalArea . Max . X = HorizontalArea . Min . X + TextureSize . X ;
HorizontalArea . Max . Y = HorizontalArea . Min . Y + ( UnusedSize . Y - TextureSize . Y ) ;
VerticalArea . Min . X = UnusedArea . Min . X + TextureSize . X ;
VerticalArea . Min . Y = UnusedArea . Min . Y ;
VerticalArea . Max . X = VerticalArea . Min . X + ( UnusedSize . X - TextureSize . X ) ;
VerticalArea . Max . Y = UnusedSize . Y ;
// Append valid new areas to list (replace original one with either one of the new ones)
const bool bValidHorizontal = HorizontalArea . GetArea ( ) > 0.0f ;
const bool bValidVertical = VerticalArea . GetArea ( ) > 0.0f ;
if ( bValidVertical & & bValidHorizontal )
{
UnusedAreas [ BestAreaIndex ] = HorizontalArea ;
UnusedAreas . Add ( VerticalArea ) ;
}
else if ( bValidVertical )
{
UnusedAreas [ BestAreaIndex ] = VerticalArea ;
}
else if ( bValidHorizontal )
{
UnusedAreas [ BestAreaIndex ] = HorizontalArea ;
}
2016-10-06 12:11:11 -04:00
else
{
// Make sure we remove the area entry
UnusedAreas . RemoveAtSwap ( BestAreaIndex ) ;
}
2016-09-22 15:33:34 -04:00
}
else
{
bSuccess = false ;
break ;
}
}
// This means we failed to find a fit, in this case we resize the textures and try again until we find one
if ( bSuccess = = false )
{
for ( FWeightedTexture & Texture : WeightedTextures )
{
Texture . Area . Max * = .99f ;
}
}
} while ( ! bSuccess ) ;
// Now generate boxes
OutGeneratedBoxes . Empty ( InTexureWeights . Num ( ) ) ;
OutGeneratedBoxes . AddZeroed ( InTexureWeights . Num ( ) ) ;
// Generate boxes according to the inserted textures
for ( const FWeightedTexture & Texture : InsertedTextures )
{
FBox2D & Box = OutGeneratedBoxes [ Texture . TextureIndex ] ;
Box = Texture . Area ;
}
}
2021-06-10 21:50:21 -04:00
float FMaterialUtilities : : ComputeRequiredTexelDensityFromScreenSize ( const float InScreenSize , float InWorldSpaceRadius )
{
static const float ScreenX = 1920 ;
float WorldSizeCM = InWorldSpaceRadius * 2 ;
float WorldSizeMeter = WorldSizeCM / 100 ;
float ScreenSizePercent = InScreenSize ;
float ScreenSizePixel = ScreenSizePercent * ScreenX ;
float TexelDensityPerMeter = ScreenSizePixel / WorldSizeMeter ;
return TexelDensityPerMeter ;
}
float FMaterialUtilities : : ComputeRequiredTexelDensityFromDrawDistance ( const float InDrawDistance , float InWorldSpaceRadius )
{
// Generate a projection matrix.
static const float ScreenX = 1920 ;
static const float ScreenY = 1080 ;
static const float HalfFOVRad = FMath : : DegreesToRadians ( 45.0f ) ;
static const FMatrix ProjectionMatrix = FPerspectiveMatrix ( HalfFOVRad , ScreenX , ScreenY , 0.01f ) ;
float WorldSizeCM = InWorldSpaceRadius * 2 ;
float WorldSizeMeter = WorldSizeCM / 100 ;
float ScreenSizePercent = ComputeBoundsScreenSize ( FVector : : ZeroVector , InWorldSpaceRadius , FVector ( 0.0f , 0.0f , InDrawDistance ) , ProjectionMatrix ) ;
float ScreenSizePixel = ScreenSizePercent * ScreenX ;
float TexelDensityPerMeter = ScreenSizePixel / WorldSizeMeter ;
return TexelDensityPerMeter ;
}
2022-09-20 01:40:59 -04:00
static int32 ComputeTextureSizeFromTexelRatio ( const double TexelRatio , const double TargetTexelDensity )
{
// Compute the perfect texture size that would get us to our texture density
// Also compute the nearest power of two sizes (below and above our target)
const int32 SizePerfect = FMath : : CeilToInt ( TargetTexelDensity / TexelRatio ) ;
const int32 SizeHi = FMath : : RoundUpToPowerOfTwo ( SizePerfect ) ;
const int32 SizeLo = SizeHi > > 1 ;
// Compute the texel density we achieve with these two texture sizes
const double TexelDensityLo = SizeLo * TexelRatio ;
const double TexelDensityHi = SizeHi * TexelRatio ;
// Select best match between low & high res textures.
const double TexelDensityLoDiff = TargetTexelDensity - TexelDensityLo ;
const double TexelDensityHiDiff = TexelDensityHi - TargetTexelDensity ;
const int32 BestTextureSize = TexelDensityLoDiff < TexelDensityHiDiff ? SizeLo : SizeHi ;
return BestTextureSize ;
}
int32 FMaterialUtilities : : GetTextureSizeFromTargetTexelDensity ( const UE : : Geometry : : FDynamicMesh3 & Mesh , float InTargetTexelDensity )
{
const UE : : Geometry : : FDynamicMeshUVOverlay * UVOverlay = Mesh . Attributes ( ) - > PrimaryUV ( ) ;
double Mesh3DArea = 0 ;
double MeshUVArea = 0 ;
// If no UVs, assume perfect UV space usage.
const bool bHasUVs = UVOverlay ! = nullptr ;
if ( ! bHasUVs )
{
MeshUVArea = 1.0 ;
}
for ( int TriangleID : Mesh . TriangleIndicesItr ( ) )
{
// World space area
Mesh3DArea + = Mesh . GetTriArea ( TriangleID ) ;
// UV space area
if ( bHasUVs )
{
UE : : Geometry : : FIndex3i UVVertices = UVOverlay - > GetTriangle ( TriangleID ) ;
UE : : Geometry : : FTriangle2d TriangleUV = UE : : Geometry : : FTriangle2d (
( FVector2d ) UVOverlay - > GetElement ( UVVertices . A ) ,
( FVector2d ) UVOverlay - > GetElement ( UVVertices . B ) ,
( FVector2d ) UVOverlay - > GetElement ( UVVertices . C ) ) ;
MeshUVArea + = TriangleUV . Area ( ) ;
}
}
return GetTextureSizeFromTargetTexelDensity ( Mesh3DArea , MeshUVArea , InTargetTexelDensity ) ;
}
int32 FMaterialUtilities : : GetTextureSizeFromTargetTexelDensity ( const FMeshDescription & InMesh , float InTargetTexelDensity )
{
FStaticMeshConstAttributes Attributes ( InMesh ) ;
TVertexAttributesConstRef < FVector3f > Positions = Attributes . GetVertexPositions ( ) ;
TUVAttributesConstRef < FVector2f > UVs = Attributes . GetUVCoordinates ( 0 ) ;
double Mesh3DArea = 0 ;
double MeshUVArea = 0 ;
// If no UVs, assume perfect UV space usage.
const bool bHasUVs = UVs . IsValid ( ) & & UVs . GetNumElements ( ) ! = 0 ;
if ( ! bHasUVs )
{
MeshUVArea = 1.0 ;
}
for ( const FTriangleID TriangleID : InMesh . Triangles ( ) . GetElementIDs ( ) )
{
// World space area
TArrayView < const FVertexID > TriVertices = InMesh . GetTriangleVertices ( TriangleID ) ;
Mesh3DArea + = UE : : Geometry : : VectorUtil : : Area ( Positions [ TriVertices [ 0 ] ] , Positions [ TriVertices [ 1 ] ] , Positions [ TriVertices [ 2 ] ] ) ;
// UV space area
if ( bHasUVs )
{
TArrayView < const FUVID > TriUVs = InMesh . GetTriangleUVIndices ( TriangleID ) ;
MeshUVArea + = UE : : Geometry : : VectorUtil : : Area ( UVs [ 0 ] , UVs [ 1 ] , UVs [ 2 ] ) ;
}
}
return GetTextureSizeFromTargetTexelDensity ( Mesh3DArea , MeshUVArea , InTargetTexelDensity ) ;
}
int32 FMaterialUtilities : : GetTextureSizeFromTargetTexelDensity ( double InMesh3DArea , double InMeshUVArea , double InTargetTexelDensity )
{
double TexelRatio = FMath : : Sqrt ( InMeshUVArea / InMesh3DArea ) * 100 ;
static const int32 MinTextureSize = 16 ;
static const int32 MaxTextureSize = 8192 ;
int32 TextureSize = ComputeTextureSizeFromTexelRatio ( TexelRatio , InTargetTexelDensity ) ;
if ( TextureSize > MaxTextureSize )
{
UE_LOG ( LogMaterialUtilities , Warning , TEXT ( " Mesh would require %d x %d textures, clamping down to maximum (%d x %d) " ) , TextureSize , TextureSize , MaxTextureSize , MaxTextureSize ) ;
}
return FMath : : Clamp ( TextureSize , MinTextureSize , MaxTextureSize ) ;
}