2015-04-29 22:39:01 -04:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
# include "MaterialUtilitiesPrivatePCH.h"
# include "Runtime/Engine/Classes/Engine/World.h"
# include "Runtime/Engine/Classes/Materials/MaterialInterface.h"
# include "Runtime/Engine/Classes/Materials/MaterialExpressionConstant.h"
# include "Runtime/Engine/Classes/Engine/TextureRenderTarget2D.h"
# include "Runtime/Engine/Classes/Engine/Texture2D.h"
2015-04-30 02:24:37 -04:00
# include "Runtime/Engine/Classes/Engine/TextureCube.h"
2015-04-29 22:39:01 -04:00
# include "Runtime/Engine/Public/TileRendering.h"
# include "Runtime/Engine/Public/EngineModule.h"
# include "Runtime/Engine/Public/ImageUtils.h"
2015-04-30 02:24:37 -04:00
# include "Runtime/Engine/Public/CanvasTypes.h"
2015-04-29 22:39:01 -04:00
# include "Runtime/Engine/Public/MaterialCompiler.h"
2015-04-30 02:24:37 -04:00
# include "Runtime/Engine/Classes/Engine/TextureLODSettings.h"
# include "Runtime/Engine/Classes/DeviceProfiles/DeviceProfileManager.h"
2015-04-29 22:39:01 -04:00
# include "RendererInterface.h"
# include "LandscapeProxy.h"
# include "LandscapeComponent.h"
2015-05-04 03:40:20 -04:00
IMPLEMENT_MODULE ( FDefaultModuleImpl , MaterialUtilities ) ;
2015-04-30 02:24:37 -04:00
DEFINE_LOG_CATEGORY_STATIC ( LogMaterialUtilities , Log , All ) ;
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 ;
}
virtual int32 ParticleRelativeTime ( ) override
{
return Compiler - > Constant ( 0.0f ) ;
}
virtual int32 ParticleMotionBlurFade ( ) override
{
return Compiler - > Constant ( 1.0f ) ;
}
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 ) ;
}
virtual int32 ObjectRadius ( ) override
{
return Compiler - > Constant ( 500 ) ;
}
virtual int32 ObjectBounds ( ) override
{
return Compiler - > Constant3 ( 0 , 0 , 0 ) ;
}
virtual int32 CameraVector ( ) override
{
return Compiler - > Constant3 ( 0.0f , 0.0f , 1.0f ) ;
}
virtual int32 ReflectionAboutCustomWorldNormal ( int32 CustomWorldNormal , int32 bNormalizeCustomWorldNormal ) override
{
return Compiler - > Constant3 ( 0.0f , 0.0f , - 1.0f ) ;
}
virtual int32 VertexColor ( ) override
{
return Compiler - > Constant4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
}
} ;
2015-04-29 22:39:01 -04:00
class FExportMaterialProxy : public FMaterial , public FMaterialRenderProxy
{
public :
FExportMaterialProxy ( )
: FMaterial ( )
{
SetQualityLevelProperties ( EMaterialQualityLevel : : High , false , GMaxRHIFeatureLevel ) ;
}
FExportMaterialProxy ( UMaterialInterface * InMaterialInterface , EMaterialProperty InPropertyToCompile )
: FMaterial ( )
, MaterialInterface ( InMaterialInterface )
, PropertyToCompile ( InPropertyToCompile )
{
SetQualityLevelProperties ( EMaterialQualityLevel : : High , false , GMaxRHIFeatureLevel ) ;
Material = InMaterialInterface - > GetMaterial ( ) ;
Material - > AppendReferencedTextures ( ReferencedTextures ) ;
FPlatformMisc : : CreateGuid ( Id ) ;
FMaterialResource * Resource = InMaterialInterface - > GetMaterialResource ( GMaxRHIFeatureLevel ) ;
FMaterialShaderMapId ResourceId ;
Resource - > GetShaderMapId ( GMaxRHIShaderPlatform , ResourceId ) ;
2015-05-04 16:32:50 -04:00
{
TArray < FShaderType * > ShaderTypes ;
TArray < FVertexFactoryType * > VFTypes ;
GetDependentShaderAndVFTypes ( GMaxRHIShaderPlatform , ShaderTypes , VFTypes ) ;
// Overwrite the shader map Id's dependencies with ones that came from the FMaterial actually being compiled (this)
// This is necessary as we change FMaterial attributes like GetShadingModel(), which factor into the ShouldCache functions that determine dependent shader types
ResourceId . SetShaderDependencies ( ShaderTypes , VFTypes ) ;
}
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 ;
case MP_Metallic : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportMetallic ; break ;
case MP_Roughness : ResourceId . Usage = EMaterialShaderMapUsage : : MaterialExportRoughness ; break ;
} ;
CacheShaders ( ResourceId , GMaxRHIShaderPlatform , true ) ;
}
/** 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 ;
}
virtual const TArray < UTexture * > & GetReferencedTextures ( ) const override
{
return ReferencedTextures ;
}
////////////////
// FMaterialRenderProxy interface.
virtual const FMaterial * GetMaterial ( ERHIFeatureLevel : : Type FeatureLevel ) const override
{
if ( GetRenderingThreadShaderMap ( ) )
{
return this ;
}
else
{
return UMaterial : : GetDefaultMaterial ( MD_Surface ) - > GetRenderProxy ( false ) - > GetMaterial ( FeatureLevel ) ;
}
}
virtual bool GetVectorValue ( const FName ParameterName , FLinearColor * OutValue , const FMaterialRenderContext & Context ) const override
{
return MaterialInterface - > GetRenderProxy ( 0 ) - > GetVectorValue ( ParameterName , OutValue , Context ) ;
}
virtual bool GetScalarValue ( const FName ParameterName , float * OutValue , const FMaterialRenderContext & Context ) const override
{
return MaterialInterface - > GetRenderProxy ( 0 ) - > GetScalarValue ( ParameterName , OutValue , Context ) ;
}
virtual bool GetTextureValue ( const FName ParameterName , const UTexture * * OutValue , const FMaterialRenderContext & Context ) const override
{
return MaterialInterface - > GetRenderProxy ( 0 ) - > GetTextureValue ( ParameterName , OutValue , Context ) ;
}
// 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 ) ;
return Compiler - > ForceCast ( Ret , GetMaterialPropertyType ( Property ) ) ;
}
/** helper for CompilePropertyAndSetMaterialProperty() */
int32 CompilePropertyAndSetMaterialPropertyWithoutCast ( EMaterialProperty Property , FMaterialCompiler * Compiler ) const
{
if ( Property = = MP_EmissiveColor )
{
UMaterial * ProxyMaterial = MaterialInterface - > GetMaterial ( ) ;
2015-05-11 07:08:08 -04:00
check ( ProxyMaterial ) ;
2015-04-29 22:39:01 -04:00
EBlendMode BlendMode = MaterialInterface - > GetBlendMode ( ) ;
EMaterialShadingModel ShadingModel = MaterialInterface - > GetShadingModel ( ) ;
2015-05-11 07:08:08 -04:00
FExportMaterialCompiler ProxyCompiler ( Compiler ) ;
2015-04-29 22:39:01 -04:00
switch ( PropertyToCompile )
{
case MP_EmissiveColor :
// Emissive is ALWAYS returned...
2015-05-11 07:08:08 -04:00
return Compiler - > ForceCast ( MaterialInterface - > CompileProperty ( & ProxyCompiler , MP_EmissiveColor ) , MCT_Float3 , true , true ) ;
2015-04-29 22:39:01 -04:00
case MP_BaseColor :
// Only return for Opaque and Masked...
if ( BlendMode = = BLEND_Opaque | | BlendMode = = BLEND_Masked )
{
2015-05-11 07:08:08 -04:00
return Compiler - > ForceCast ( MaterialInterface - > CompileProperty ( & ProxyCompiler , MP_BaseColor ) , MCT_Float3 , true , true ) ;
2015-04-29 22:39:01 -04:00
}
break ;
case MP_Specular :
case MP_Roughness :
case MP_Metallic :
// Only return for Opaque and Masked...
if ( BlendMode = = BLEND_Opaque | | BlendMode = = BLEND_Masked )
{
2015-05-11 07:08:08 -04:00
return Compiler - > ForceCast ( MaterialInterface - > CompileProperty ( & ProxyCompiler , PropertyToCompile ) , MCT_Float , true , true ) ;
2015-04-29 22:39:01 -04:00
}
break ;
case MP_Normal :
// Only return for Opaque and Masked...
if ( BlendMode = = BLEND_Opaque | | BlendMode = = BLEND_Masked )
{
return Compiler - > ForceCast (
Compiler - > Add (
2015-05-11 07:08:08 -04:00
Compiler - > Mul ( MaterialInterface - > CompileProperty ( & ProxyCompiler , MP_Normal ) , Compiler - > Constant ( 0.5f ) ) , // [-1,1] * 0.5
2015-04-29 22:39:01 -04:00
Compiler - > Constant ( 0.5f ) ) , // [-0.5,0.5] + 0.5
MCT_Float3 , true , true ) ;
}
break ;
default :
return Compiler - > Constant ( 1.0f ) ;
}
return Compiler - > Constant ( 0.0f ) ;
}
else if ( Property = = MP_WorldPositionOffset )
{
//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 ) ;
}
else
{
return Compiler - > Constant ( 1.0f ) ;
}
}
virtual FString GetMaterialUsageDescription ( ) const override
{
return FString : : Printf ( TEXT ( " FExportMaterialRenderer %s " ) , MaterialInterface ? * MaterialInterface - > GetName ( ) : TEXT ( " NULL " ) ) ;
}
virtual int32 GetMaterialDomain ( ) const override
{
if ( Material )
{
return Material - > MaterialDomain ;
}
return MD_Surface ;
}
virtual bool IsTwoSided ( ) const override
{
if ( MaterialInterface )
{
return MaterialInterface - > IsTwoSided ( ) ;
}
return false ;
}
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 ;
}
virtual bool IsUsedWithDeferredDecal ( ) const override
{
return Material & &
Material - > MaterialDomain = = MD_DeferredDecal ;
}
virtual bool IsSpecialEngineMaterial ( ) const override
{
if ( Material )
{
return ( Material - > bUsedAsSpecialEngineMaterial = = 1 ) ;
}
return false ;
}
virtual bool IsWireframe ( ) const override
{
if ( Material )
{
return ( Material - > Wireframe = = 1 ) ;
}
return false ;
}
virtual bool IsMasked ( ) const override { return false ; }
virtual enum EBlendMode GetBlendMode ( ) const override { return BLEND_Opaque ; }
virtual enum EMaterialShadingModel GetShadingModel ( ) const override { return MSM_Unlit ; }
virtual float GetOpacityMaskClipValue ( ) const override { return 0.5f ; }
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 ; }
const UMaterialInterface * GetMaterialInterface ( ) const
{
return MaterialInterface ;
}
friend FArchive & operator < < ( FArchive & Ar , FExportMaterialProxy & V )
{
return Ar < < V . MaterialInterface ;
}
bool IsMaterialInputConnected ( UMaterial * InMaterial , EMaterialProperty MaterialInput )
{
bool bConnected = false ;
switch ( MaterialInput )
{
case MP_EmissiveColor :
bConnected = InMaterial - > EmissiveColor . Expression ! = NULL ;
break ;
case MP_BaseColor :
bConnected = InMaterial - > BaseColor . Expression ! = NULL ;
break ;
case MP_Specular :
bConnected = InMaterial - > Specular . Expression ! = NULL ;
break ;
case MP_Normal :
bConnected = InMaterial - > Normal . Expression ! = NULL ;
break ;
case MP_Metallic :
bConnected = InMaterial - > Metallic . Expression ! = NULL ;
break ;
case MP_Roughness :
bConnected = InMaterial - > Roughness . Expression ! = NULL ;
break ;
default :
break ;
}
// Note: only checking to see whether the entire material attributes connection exists.
// This means materials using the material attributes input will export more attributes than is necessary.
bConnected = InMaterial - > bUseMaterialAttributes ? InMaterial - > MaterialAttributes . Expression ! = NULL : bConnected ;
return bConnected ;
}
/**
* Checks if the configuration of the material proxy will generate a uniform
* value across the sampling . . . ( Ie , nothing is hooked to the property )
*
* @ param OutUniformValue The value that will be returned .
*
* @ return bool true if a single value would be generated .
* false if not .
*/
bool WillGenerateUniformData ( FColor & OutUniformValue )
{
// Pre-fill the value...
OutUniformValue . R = 0 ;
OutUniformValue . G = 0 ;
OutUniformValue . B = 0 ;
OutUniformValue . A = 0 ;
EBlendMode BlendMode = MaterialInterface - > GetBlendMode ( ) ;
EMaterialShadingModel ShadingModel = MaterialInterface - > GetShadingModel ( ) ;
check ( Material ) ;
bool bExpressionIsNULL = false ;
switch ( PropertyToCompile )
{
case MP_EmissiveColor :
// Emissive is ALWAYS returned...
bExpressionIsNULL = ! IsMaterialInputConnected ( Material , PropertyToCompile ) ;
break ;
case MP_BaseColor :
// Only return for Opaque and Masked...
if ( BlendMode = = BLEND_Opaque | | BlendMode = = BLEND_Masked )
{
bExpressionIsNULL = ! IsMaterialInputConnected ( Material , PropertyToCompile ) ;
}
break ;
case MP_Specular :
case MP_Metallic :
case MP_Roughness :
// Only return for Opaque and Masked...
if ( BlendMode = = BLEND_Opaque | | BlendMode = = BLEND_Masked )
{
bExpressionIsNULL = ! IsMaterialInputConnected ( Material , PropertyToCompile ) ;
OutUniformValue . A = 255 ;
}
break ;
case MP_Normal :
// Only return for Opaque and Masked...
if ( BlendMode = = BLEND_Opaque | | BlendMode = = BLEND_Masked )
{
bExpressionIsNULL = ! IsMaterialInputConnected ( Material , PropertyToCompile ) ;
OutUniformValue . B = 255 ; // Default normal is (0,0,1)
}
break ;
}
return bExpressionIsNULL ;
}
/**
* Iterate through all textures used by the material and return the maximum texture resolution used
* ( ideally this could be made dependent of the material property )
*
* @ param MaterialInterface The material to scan for texture size
*
* @ return Size ( width and height )
*/
FIntPoint FindMaxTextureSize ( UMaterialInterface * InMaterialInterface , FIntPoint MinimumSize = FIntPoint ( 1 , 1 ) ) const
{
// static lod settings so that we only initialize them once
UTextureLODSettings * GameTextureLODSettings = UDeviceProfileManager : : Get ( ) . GetActiveProfile ( ) - > GetTextureLODSettings ( ) ;
TArray < UTexture * > MaterialTextures ;
InMaterialInterface - > GetUsedTextures ( MaterialTextures , EMaterialQualityLevel : : Num , false , GMaxRHIFeatureLevel , false ) ;
// 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 ( ) ) ;
}
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 ;
}
static bool WillFillData ( EBlendMode InBlendMode , EMaterialProperty InMaterialProperty )
{
if ( InMaterialProperty = = MP_EmissiveColor )
{
return true ;
}
switch ( InBlendMode )
{
case BLEND_Opaque :
{
switch ( InMaterialProperty )
{
case MP_BaseColor : return true ;
case MP_Specular : return true ;
case MP_Normal : return true ;
case MP_Metallic : return true ;
case MP_Roughness : return true ;
}
}
break ;
}
return false ;
}
private :
/** The material interface for this proxy */
UMaterialInterface * MaterialInterface ;
UMaterial * Material ;
TArray < UTexture * > ReferencedTextures ;
/** The property to compile for rendering the sample */
EMaterialProperty PropertyToCompile ;
FGuid Id ;
} ;
static void RenderMaterialTile ( UWorld * InWorld , FMaterialRenderProxy * InMaterialProxy , UTextureRenderTarget2D * InRenderTarget , bool bFrontView )
{
float CurrentRealTime = 0.f ;
float CurrentWorldTime = 0.f ;
float DeltaWorldTime = 0.f ;
if ( InWorld )
{
CurrentRealTime = InWorld - > GetRealTimeSeconds ( ) ;
CurrentWorldTime = InWorld - > GetTimeSeconds ( ) ;
DeltaWorldTime = InWorld - > GetDeltaSeconds ( ) ;
}
else
{
CurrentRealTime = FApp : : GetCurrentTime ( ) - GStartTime ;
CurrentWorldTime = FApp : : GetDeltaTime ( ) ;
DeltaWorldTime = FApp : : GetCurrentTime ( ) - GStartTime ;
}
const FRenderTarget * RenderTargetResource = InRenderTarget - > GameThread_GetRenderTargetResource ( ) ;
FSceneViewFamily * ViewFamily = new FSceneViewFamily ( FSceneViewFamily : : ConstructionValues (
RenderTargetResource ,
InWorld ? InWorld - > Scene : nullptr ,
FEngineShowFlags ( ESFIM_Game ) )
. SetWorldTimes ( CurrentWorldTime , DeltaWorldTime , CurrentRealTime )
. SetGammaCorrection ( RenderTargetResource - > GetDisplayGamma ( ) ) ) ;
FIntPoint ViewSize = RenderTargetResource - > GetSizeXY ( ) ;
FIntRect ViewRect ( FIntPoint ( 0 , 0 ) , ViewSize ) ;
// By default render tile in top view
FMatrix ViewMatrix = FMatrix (
FPlane ( 1 , 0 , 0 , 0 ) ,
FPlane ( 0 , - 1 , 0 , 0 ) ,
FPlane ( 0 , 0 , - 1 , 0 ) ,
FPlane ( 0 , 0 , 0 , 1 ) ) ;
FQuat Rotation = FQuat : : Identity ;
if ( bFrontView )
{
ViewMatrix = FMatrix (
FPlane ( 1 , 0 , 0 , 0 ) ,
FPlane ( 0 , 0 , - 1 , 0 ) ,
FPlane ( 0 , 1 , 0 , 0 ) ,
FPlane ( 0 , 0 , 0 , 1 ) ) ;
// Tile mesh was created on XY plane
Rotation = FRotator ( 0.0f , 0.0f , 90.0f ) . Quaternion ( ) ;
}
// make a temporary view
FSceneViewInitOptions ViewInitOptions ;
ViewInitOptions . ViewFamily = ViewFamily ;
ViewInitOptions . SetViewRectangle ( ViewRect ) ;
ViewInitOptions . ViewOrigin = FVector ( ViewSize . X / 2.f , ViewSize . Y / 2.f , 0.0f ) ;
ViewInitOptions . ViewRotationMatrix = ViewMatrix ;
ViewInitOptions . ProjectionMatrix = FReversedZOrthoMatrix ( ViewSize . X / 2.f , ViewSize . Y / 2.f , 0.5f / HALF_WORLD_MAX , HALF_WORLD_MAX ) ;
ViewInitOptions . BackgroundColor = FLinearColor : : Black ;
ViewInitOptions . OverlayColor = FLinearColor : : White ;
FSceneView * View = new FSceneView ( ViewInitOptions ) ;
ENQUEUE_UNIQUE_RENDER_COMMAND_FIVEPARAMETER (
RenderMaterialTileCommand ,
FSceneView * , InView , View ,
FMaterialRenderProxy * , InProxy , InMaterialProxy ,
const FRenderTarget * , InRenderTarget , RenderTargetResource ,
FIntPoint , InSize , ViewSize ,
FQuat , InRotation , Rotation ,
{
: : SetRenderTarget ( RHICmdList , InRenderTarget - > GetRenderTargetTexture ( ) , FTextureRHIRef ( ) ) ;
FIntRect ViewportRect = FIntRect ( FIntPoint : : ZeroValue , InSize ) ;
RHICmdList . SetViewport ( ViewportRect . Min . X , ViewportRect . Min . Y , 0.0f , ViewportRect . Max . X , ViewportRect . Max . Y , 1.0f ) ;
FTileRenderer : : DrawRotatedTile ( RHICmdList , * InView , InProxy , false , InRotation , 0.f , 0.f , InSize . X , InSize . Y , 0.f , 0.f , 1.f , 1.f ) ;
} ) ;
FlushRenderingCommands ( ) ;
delete View ;
}
static void RenderSceneToTexture (
FSceneInterface * Scene ,
const FName & VisualizationMode ,
const FVector & ViewOrigin ,
const FMatrix & ViewRotationMatrix ,
const FMatrix & ProjectionMatrix ,
const TSet < FPrimitiveComponentId > & HiddenPrimitives ,
FIntPoint TargetSize ,
float TargetGamma ,
TArray < FColor > & OutSamples )
{
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 ) )
. SetWorldTimes ( FApp : : GetCurrentTime ( ) - GStartTime , FApp : : GetDeltaTime ( ) , FApp : : GetCurrentTime ( ) - GStartTime )
) ;
// To enable visualization mode
ViewFamily . EngineShowFlags . SetPostProcessing ( true ) ;
ViewFamily . EngineShowFlags . SetVisualizeBuffer ( true ) ;
ViewFamily . EngineShowFlags . SetTonemapper ( false ) ;
FSceneViewInitOptions ViewInitOptions ;
ViewInitOptions . SetViewRectangle ( FIntRect ( 0 , 0 , TargetSize . X , TargetSize . Y ) ) ;
ViewInitOptions . ViewFamily = & ViewFamily ;
ViewInitOptions . HiddenPrimitives = HiddenPrimitives ;
ViewInitOptions . ViewOrigin = ViewOrigin ;
ViewInitOptions . ViewRotationMatrix = ViewRotationMatrix ;
ViewInitOptions . ProjectionMatrix = ProjectionMatrix ;
FSceneView * NewView = new FSceneView ( ViewInitOptions ) ;
NewView - > CurrentBufferVisualizationMode = VisualizationMode ;
ViewFamily . Views . Add ( NewView ) ;
FCanvas Canvas ( RenderTargetResource , NULL , FApp : : GetCurrentTime ( ) - GStartTime , FApp : : GetDeltaTime ( ) , FApp : : GetCurrentTime ( ) - GStartTime , Scene - > GetFeatureLevel ( ) ) ;
Canvas . Clear ( FLinearColor : : Transparent ) ;
GetRendererModule ( ) . BeginRenderingViewFamily ( & Canvas , & ViewFamily ) ;
// 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 ) ) ;
FlushRenderingCommands ( ) ;
RenderTargetTexture - > RemoveFromRoot ( ) ;
RenderTargetTexture = nullptr ;
}
bool FMaterialUtilities : : SupportsExport ( EBlendMode InBlendMode , EMaterialProperty InMaterialProperty )
{
return FExportMaterialProxy : : WillFillData ( InBlendMode , InMaterialProperty ) ;
}
bool FMaterialUtilities : : ExportMaterialProperty ( UWorld * InWorld , UMaterialInterface * InMaterial , EMaterialProperty InMaterialProperty , UTextureRenderTarget2D * InRenderTarget , TArray < FColor > & OutBMP )
{
TScopedPointer < FExportMaterialProxy > MaterialProxy ( new FExportMaterialProxy ( InMaterial , InMaterialProperty ) ) ;
if ( MaterialProxy = = NULL )
{
return false ;
}
FColor UniformValue ;
if ( MaterialProxy - > WillGenerateUniformData ( UniformValue ) )
{
// Single value... fill it in.
OutBMP . Empty ( ) ;
OutBMP . Add ( UniformValue ) ;
return true ;
}
bool bNormalmap = ( InMaterialProperty = = MP_Normal ) ;
RenderMaterialTile ( InWorld , MaterialProxy , InRenderTarget , ! bNormalmap ) ;
FReadSurfaceDataFlags ReadPixelFlags ( bNormalmap ? RCM_SNorm : RCM_UNorm ) ;
ReadPixelFlags . SetLinearToGamma ( false ) ;
FTextureRenderTargetResource * RTResource = InRenderTarget - > GameThread_GetRenderTargetResource ( ) ;
return RTResource - > ReadPixels ( OutBMP , ReadPixelFlags ) ;
}
bool FMaterialUtilities : : ExportMaterialProperty ( UWorld * InWorld , UMaterialInterface * InMaterial , EMaterialProperty InMaterialProperty , FIntPoint & OutSize , TArray < FColor > & OutBMP )
{
TScopedPointer < FExportMaterialProxy > MaterialProxy ( new FExportMaterialProxy ( InMaterial , InMaterialProperty ) ) ;
if ( MaterialProxy = = NULL )
{
return false ;
}
FColor UniformValue ;
if ( MaterialProxy - > WillGenerateUniformData ( UniformValue ) )
{
// Single value... fill it in.
OutBMP . Empty ( ) ;
OutBMP . Add ( UniformValue ) ;
return true ;
}
bool bNormalmap = ( InMaterialProperty = = MP_Normal ) ;
EPixelFormat Format = PF_FloatRGB ;
OutSize = MaterialProxy - > FindMaxTextureSize ( InMaterial ) ;
OutBMP . Reserve ( OutSize . X * OutSize . Y ) ;
OutBMP . SetNumUninitialized ( OutSize . X * OutSize . Y ) ;
UTextureRenderTarget2D * RenderTarget = NewObject < UTextureRenderTarget2D > ( ) ;
check ( RenderTarget ) ;
RenderTarget - > AddToRoot ( ) ;
RenderTarget - > ClearColor = FLinearColor ( 0.0f , 0.0f , 0.0f , 0.0f ) ;
RenderTarget - > InitCustomFormat ( OutSize . X , OutSize . Y , Format , bNormalmap ) ;
RenderMaterialTile ( InWorld , MaterialProxy , RenderTarget , ! bNormalmap ) ;
FReadSurfaceDataFlags ReadPixelFlags ( bNormalmap ? RCM_SNorm : RCM_UNorm ) ;
ReadPixelFlags . SetLinearToGamma ( false ) ;
FTextureRenderTargetResource * RTResource = RenderTarget - > GameThread_GetRenderTargetResource ( ) ;
bool bResult = RTResource - > ReadPixels ( OutBMP , ReadPixelFlags ) ;
RenderTarget - > RemoveFromRoot ( ) ;
return bResult ;
}
bool FMaterialUtilities : : ExportMaterial ( UWorld * InWorld , UMaterialInterface * InMaterial , FFlattenMaterial & OutFlattenMaterial )
{
// Render diffuse property
if ( OutFlattenMaterial . DiffuseSize . X > 0 & &
OutFlattenMaterial . DiffuseSize . Y > 0 )
{
// Create temporary render target
auto RenderTargetDiffuse = NewObject < UTextureRenderTarget2D > ( ) ;
check ( RenderTargetDiffuse ) ;
RenderTargetDiffuse - > AddToRoot ( ) ;
RenderTargetDiffuse - > ClearColor = FLinearColor ( 0.0f , 0.0f , 0.0f , 0.0f ) ;
RenderTargetDiffuse - > InitCustomFormat (
OutFlattenMaterial . DiffuseSize . X ,
OutFlattenMaterial . DiffuseSize . Y , PF_B8G8R8A8 , false ) ;
//
OutFlattenMaterial . DiffuseSamples . Empty ( OutFlattenMaterial . DiffuseSize . X * OutFlattenMaterial . DiffuseSize . Y ) ;
bool bResult = ExportMaterialProperty ( InWorld , InMaterial , MP_BaseColor , RenderTargetDiffuse , OutFlattenMaterial . DiffuseSamples ) ;
// Uniform value
if ( OutFlattenMaterial . DiffuseSamples . Num ( ) = = 1 )
{
OutFlattenMaterial . DiffuseSize = FIntPoint ( 1 , 1 ) ;
}
RenderTargetDiffuse - > RemoveFromRoot ( ) ;
RenderTargetDiffuse = nullptr ;
if ( ! bResult )
{
return false ;
}
}
// Render normal property
if ( OutFlattenMaterial . NormalSize . X > 0 & &
2015-05-11 07:08:08 -04:00
OutFlattenMaterial . NormalSize . Y > 0 )
2015-04-29 22:39:01 -04:00
{
// Create temporary render target
auto RenderTargetNormal = NewObject < UTextureRenderTarget2D > ( ) ;
check ( RenderTargetNormal ) ;
RenderTargetNormal - > AddToRoot ( ) ;
RenderTargetNormal - > ClearColor = FLinearColor ( 0.0f , 0.0f , 0.0f , 0.0f ) ;
RenderTargetNormal - > InitCustomFormat (
OutFlattenMaterial . NormalSize . X ,
OutFlattenMaterial . NormalSize . Y , PF_FloatRGB , true ) ;
//
OutFlattenMaterial . NormalSamples . Empty ( OutFlattenMaterial . NormalSize . X * OutFlattenMaterial . NormalSize . Y ) ;
bool bResult = ExportMaterialProperty ( InWorld , InMaterial , MP_Normal , RenderTargetNormal , OutFlattenMaterial . NormalSamples ) ;
// Uniform value
if ( OutFlattenMaterial . NormalSamples . Num ( ) = = 1 )
{
OutFlattenMaterial . NormalSize = FIntPoint ( 1 , 1 ) ;
}
RenderTargetNormal - > RemoveFromRoot ( ) ;
RenderTargetNormal = nullptr ;
if ( ! bResult )
{
return false ;
}
}
// Render metallic property
if ( OutFlattenMaterial . MetallicSize . X > 0 & &
OutFlattenMaterial . MetallicSize . Y > 0 )
{
// Create temporary render target
auto RenderTargetMetallic = NewObject < UTextureRenderTarget2D > ( ) ;
check ( RenderTargetMetallic ) ;
RenderTargetMetallic - > AddToRoot ( ) ;
RenderTargetMetallic - > ClearColor = FLinearColor ( 0.0f , 0.0f , 0.0f , 0.0f ) ;
RenderTargetMetallic - > InitCustomFormat (
OutFlattenMaterial . MetallicSize . X ,
OutFlattenMaterial . MetallicSize . Y , PF_B8G8R8A8 , true ) ;
//
OutFlattenMaterial . MetallicSamples . Empty ( OutFlattenMaterial . MetallicSize . X * OutFlattenMaterial . MetallicSize . Y ) ;
bool bResult = ExportMaterialProperty ( InWorld , InMaterial , MP_Metallic , RenderTargetMetallic , OutFlattenMaterial . MetallicSamples ) ;
// Uniform value
if ( OutFlattenMaterial . MetallicSamples . Num ( ) = = 1 )
{
OutFlattenMaterial . MetallicSize = FIntPoint ( 1 , 1 ) ;
}
RenderTargetMetallic - > RemoveFromRoot ( ) ;
RenderTargetMetallic = nullptr ;
if ( ! bResult )
{
return false ;
}
}
// Render roughness property
if ( OutFlattenMaterial . RoughnessSize . X > 0 & &
OutFlattenMaterial . RoughnessSize . Y > 0 )
{
// Create temporary render target
auto RenderTargetRoughness = NewObject < UTextureRenderTarget2D > ( ) ;
check ( RenderTargetRoughness ) ;
RenderTargetRoughness - > AddToRoot ( ) ;
RenderTargetRoughness - > ClearColor = FLinearColor ( 0.0f , 0.0f , 0.0f , 0.0f ) ;
RenderTargetRoughness - > InitCustomFormat (
OutFlattenMaterial . RoughnessSize . X ,
OutFlattenMaterial . RoughnessSize . Y , PF_B8G8R8A8 , true ) ;
//
OutFlattenMaterial . RoughnessSamples . Empty ( OutFlattenMaterial . RoughnessSize . X * OutFlattenMaterial . RoughnessSize . Y ) ;
bool bResult = ExportMaterialProperty ( InWorld , InMaterial , MP_Roughness , RenderTargetRoughness , OutFlattenMaterial . RoughnessSamples ) ;
// Uniform value
if ( OutFlattenMaterial . RoughnessSamples . Num ( ) = = 1 )
{
OutFlattenMaterial . RoughnessSize = FIntPoint ( 1 , 1 ) ;
}
RenderTargetRoughness - > RemoveFromRoot ( ) ;
RenderTargetRoughness = nullptr ;
if ( ! bResult )
{
return false ;
}
}
// Render specular property
if ( OutFlattenMaterial . SpecularSize . X > 0 & &
OutFlattenMaterial . SpecularSize . Y > 0 )
{
// Create temporary render target
auto RenderTargetSpecular = NewObject < UTextureRenderTarget2D > ( ) ;
check ( RenderTargetSpecular ) ;
RenderTargetSpecular - > AddToRoot ( ) ;
RenderTargetSpecular - > ClearColor = FLinearColor ( 0.0f , 0.0f , 0.0f , 0.0f ) ;
RenderTargetSpecular - > InitCustomFormat (
OutFlattenMaterial . SpecularSize . X ,
OutFlattenMaterial . SpecularSize . Y , PF_B8G8R8A8 , true ) ;
//
OutFlattenMaterial . SpecularSamples . Empty ( OutFlattenMaterial . SpecularSize . X * OutFlattenMaterial . SpecularSize . Y ) ;
bool bResult = ExportMaterialProperty ( InWorld , InMaterial , MP_Specular , RenderTargetSpecular , OutFlattenMaterial . SpecularSamples ) ;
// Uniform value
if ( OutFlattenMaterial . SpecularSamples . Num ( ) = = 1 )
{
OutFlattenMaterial . SpecularSize = FIntPoint ( 1 , 1 ) ;
}
RenderTargetSpecular - > RemoveFromRoot ( ) ;
RenderTargetSpecular = nullptr ;
if ( ! bResult )
{
return false ;
}
}
OutFlattenMaterial . MaterialId = InMaterial - > GetLightingGuid ( ) ;
return true ;
}
bool FMaterialUtilities : : ExportLandscapeMaterial ( ALandscapeProxy * InLandscape , const TSet < FPrimitiveComponentId > & HiddenPrimitives , FFlattenMaterial & OutFlattenMaterial )
{
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 ) ) ;
const float ZOffset = WORLD_MAX ;
FMatrix ProjectionMatrix = FReversedZOrthoMatrix (
LandscapeExtent . X ,
LandscapeExtent . Y ,
0.5f / ZOffset ,
ZOffset ) ;
FSceneInterface * Scene = InLandscape - > GetWorld ( ) - > Scene ;
// Render diffuse texture using BufferVisualizationMode=BaseColor
if ( OutFlattenMaterial . DiffuseSize . X > 0 & &
OutFlattenMaterial . DiffuseSize . Y > 0 )
{
static const FName BaseColorName ( " BaseColor " ) ;
const float BaseColorGamma = 2.2f ; // BaseColor to gamma space
RenderSceneToTexture ( Scene , BaseColorName , ViewOrigin , ViewRotationMatrix , ProjectionMatrix , HiddenPrimitives ,
OutFlattenMaterial . DiffuseSize , BaseColorGamma , OutFlattenMaterial . DiffuseSamples ) ;
}
// Render normal map using BufferVisualizationMode=WorldNormal
// Final material should use world space instead of tangent space for normals
if ( OutFlattenMaterial . NormalSize . X > 0 & &
OutFlattenMaterial . NormalSize . Y > 0 )
{
static const FName WorldNormalName ( " WorldNormal " ) ;
const float NormalColorGamma = 1.0f ; // Dump normal texture in linear space
RenderSceneToTexture ( Scene , WorldNormalName , ViewOrigin , ViewRotationMatrix , ProjectionMatrix , HiddenPrimitives ,
OutFlattenMaterial . NormalSize , NormalColorGamma , OutFlattenMaterial . NormalSamples ) ;
}
// Render metallic map using BufferVisualizationMode=Metallic
if ( OutFlattenMaterial . MetallicSize . X > 0 & &
OutFlattenMaterial . MetallicSize . Y > 0 )
{
static const FName MetallicName ( " Metallic " ) ;
const float MetallicColorGamma = 1.0f ; // Dump metallic texture in linear space
RenderSceneToTexture ( Scene , MetallicName , ViewOrigin , ViewRotationMatrix , ProjectionMatrix , HiddenPrimitives ,
OutFlattenMaterial . MetallicSize , MetallicColorGamma , OutFlattenMaterial . MetallicSamples ) ;
}
// Render roughness map using BufferVisualizationMode=Roughness
if ( OutFlattenMaterial . RoughnessSize . X > 0 & &
OutFlattenMaterial . RoughnessSize . Y > 0 )
{
static const FName RoughnessName ( " Roughness " ) ;
const float RoughnessColorGamma = 2.2f ; // Roughness material powers color by 2.2, transform it back to linear
RenderSceneToTexture ( Scene , RoughnessName , ViewOrigin , ViewRotationMatrix , ProjectionMatrix , HiddenPrimitives ,
OutFlattenMaterial . RoughnessSize , RoughnessColorGamma , OutFlattenMaterial . RoughnessSamples ) ;
}
// Render specular map using BufferVisualizationMode=Specular
if ( OutFlattenMaterial . SpecularSize . X > 0 & &
OutFlattenMaterial . SpecularSize . Y > 0 )
{
static const FName SpecularName ( " Specular " ) ;
const float SpecularColorGamma = 1.0f ; // Dump specular texture in linear space
RenderSceneToTexture ( Scene , SpecularName , ViewOrigin , ViewRotationMatrix , ProjectionMatrix , HiddenPrimitives ,
OutFlattenMaterial . SpecularSize , SpecularColorGamma , OutFlattenMaterial . SpecularSamples ) ;
}
OutFlattenMaterial . MaterialId = InLandscape - > GetLandscapeGuid ( ) ;
return true ;
}
UMaterial * FMaterialUtilities : : CreateMaterial ( const FFlattenMaterial & InFlattenMaterial , UPackage * InOuter , const FString & BaseName , EObjectFlags Flags , TArray < UObject * > & OutGeneratedAssets )
{
// 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 ) ;
const FString AssetBasePath = InOuter ? TEXT ( " " ) : FPackageName : : GetLongPackagePath ( BaseName ) + TEXT ( " / " ) ;
// Create material
const FString MaterialAssetName = TEXT ( " M_ " ) + AssetBaseName ;
UPackage * MaterialOuter = InOuter ;
if ( MaterialOuter = = NULL )
{
MaterialOuter = CreatePackage ( NULL , * ( AssetBasePath + MaterialAssetName ) ) ;
MaterialOuter - > FullyLoad ( ) ;
MaterialOuter - > Modify ( ) ;
}
UMaterial * Material = NewObject < UMaterial > ( MaterialOuter , FName ( * MaterialAssetName ) , Flags ) ;
Material - > TwoSided = false ;
Material - > SetShadingModel ( MSM_DefaultLit ) ;
OutGeneratedAssets . Add ( Material ) ;
int32 MaterialNodeY = - 150 ;
int32 MaterialNodeStepY = 180 ;
// BaseColor
if ( InFlattenMaterial . DiffuseSamples . Num ( ) > 1 )
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _D " ) ;
const FString AssetLongName = AssetBasePath + AssetName ;
const bool bSRGB = true ;
UTexture2D * Texture = CreateTexture ( InOuter , AssetLongName , InFlattenMaterial . DiffuseSize , InFlattenMaterial . DiffuseSamples , TC_Default , TEXTUREGROUP_World , Flags , bSRGB ) ;
OutGeneratedAssets . Add ( Texture ) ;
auto BasecolorExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
BasecolorExpression - > Texture = Texture ;
BasecolorExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_Color ;
BasecolorExpression - > MaterialExpressionEditorX = - 400 ;
BasecolorExpression - > MaterialExpressionEditorY = MaterialNodeY ;
Material - > Expressions . Add ( BasecolorExpression ) ;
Material - > BaseColor . Expression = BasecolorExpression ;
MaterialNodeY + = MaterialNodeStepY ;
}
// Metallic
if ( InFlattenMaterial . MetallicSamples . Num ( ) > 1 )
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _M " ) ;
const bool bSRGB = false ;
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath + AssetName , InFlattenMaterial . MetallicSize , InFlattenMaterial . MetallicSamples , TC_Grayscale , TEXTUREGROUP_World , Flags , bSRGB ) ;
OutGeneratedAssets . Add ( Texture ) ;
auto MetallicExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
MetallicExpression - > Texture = Texture ;
MetallicExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_LinearGrayscale ;
MetallicExpression - > MaterialExpressionEditorX = - 400 ;
MetallicExpression - > MaterialExpressionEditorY = MaterialNodeY ;
Material - > Expressions . Add ( MetallicExpression ) ;
Material - > Metallic . Expression = MetallicExpression ;
MaterialNodeY + = MaterialNodeStepY ;
}
else
{
// Set Metallic to constant
float Metallic = InFlattenMaterial . MetallicSamples . Num ( ) ? InFlattenMaterial . MetallicSamples [ 0 ] . R : 0.0f ;
auto MetallicExpression = NewObject < UMaterialExpressionConstant > ( Material ) ;
MetallicExpression - > R = Metallic ;
MetallicExpression - > MaterialExpressionEditorX = - 400 ;
MetallicExpression - > MaterialExpressionEditorY = MaterialNodeY ;
Material - > Expressions . Add ( MetallicExpression ) ;
Material - > Metallic . Expression = MetallicExpression ;
MaterialNodeY + = MaterialNodeStepY ;
}
// Specular
if ( InFlattenMaterial . SpecularSamples . Num ( ) > 1 )
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _S " ) ;
const bool bSRGB = false ;
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath + AssetName , InFlattenMaterial . SpecularSize , InFlattenMaterial . SpecularSamples , TC_Grayscale , TEXTUREGROUP_World , Flags , bSRGB ) ;
OutGeneratedAssets . Add ( Texture ) ;
auto SpecularExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
SpecularExpression - > Texture = Texture ;
SpecularExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_LinearGrayscale ;
SpecularExpression - > MaterialExpressionEditorX = - 400 ;
SpecularExpression - > MaterialExpressionEditorY = MaterialNodeY ;
Material - > Expressions . Add ( SpecularExpression ) ;
Material - > Specular . Expression = SpecularExpression ;
MaterialNodeY + = MaterialNodeStepY ;
}
// Roughness
if ( InFlattenMaterial . RoughnessSamples . Num ( ) > 1 )
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _R " ) ;
const bool bSRGB = false ;
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath + AssetName , InFlattenMaterial . RoughnessSize , InFlattenMaterial . RoughnessSamples , TC_Grayscale , TEXTUREGROUP_World , Flags , bSRGB ) ;
OutGeneratedAssets . Add ( Texture ) ;
auto RoughnessExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
RoughnessExpression - > Texture = Texture ;
RoughnessExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_LinearGrayscale ;
RoughnessExpression - > MaterialExpressionEditorX = - 400 ;
RoughnessExpression - > MaterialExpressionEditorY = MaterialNodeY ;
Material - > Expressions . Add ( RoughnessExpression ) ;
Material - > Roughness . Expression = RoughnessExpression ;
MaterialNodeY + = MaterialNodeStepY ;
}
else
{
// Set Roughness to constant
float Roughness = InFlattenMaterial . RoughnessSamples . Num ( ) ? InFlattenMaterial . RoughnessSamples [ 0 ] . R : 0.8f ;
auto RoughnessExpression = NewObject < UMaterialExpressionConstant > ( Material ) ;
RoughnessExpression - > R = Roughness ;
RoughnessExpression - > MaterialExpressionEditorX = - 400 ;
RoughnessExpression - > MaterialExpressionEditorY = MaterialNodeY ;
Material - > Expressions . Add ( RoughnessExpression ) ;
Material - > Roughness . Expression = RoughnessExpression ;
MaterialNodeY + = MaterialNodeStepY ;
}
// Normal
if ( InFlattenMaterial . NormalSamples . Num ( ) > 1 )
{
const FString AssetName = TEXT ( " T_ " ) + AssetBaseName + TEXT ( " _N " ) ;
const bool bSRGB = false ;
UTexture2D * Texture = CreateTexture ( InOuter , AssetBasePath + AssetName , InFlattenMaterial . NormalSize , InFlattenMaterial . NormalSamples , TC_Normalmap , TEXTUREGROUP_WorldNormalMap , Flags , bSRGB ) ;
OutGeneratedAssets . Add ( Texture ) ;
auto NormalExpression = NewObject < UMaterialExpressionTextureSample > ( Material ) ;
NormalExpression - > Texture = Texture ;
NormalExpression - > SamplerType = EMaterialSamplerType : : SAMPLERTYPE_Normal ;
NormalExpression - > MaterialExpressionEditorX = - 400 ;
NormalExpression - > MaterialExpressionEditorY = MaterialNodeY ;
Material - > Expressions . Add ( NormalExpression ) ;
Material - > Normal . Expression = NormalExpression ;
MaterialNodeY + = MaterialNodeStepY ;
}
Material - > PostEditChange ( ) ;
return Material ;
}
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 ;
if ( Outer = = nullptr )
{
Outer = CreatePackage ( NULL , * AssetLongName ) ;
Outer - > FullyLoad ( ) ;
Outer - > Modify ( ) ;
}
UTexture2D * Texture = FImageUtils : : CreateTexture2D ( Size . X , Size . Y , Samples , Outer , FPackageName : : GetShortName ( AssetLongName ) , Flags , TexParams ) ;
Texture - > LODGroup = LODGroup ;
Texture - > PostEditChange ( ) ;
return Texture ;
}
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 ) ) ;
const float ZOffset = WORLD_MAX ;
FMatrix ProjectionMatrix = FReversedZOrthoMatrix (
LandscapeExtent . X ,
LandscapeExtent . Y ,
0.5f / ZOffset ,
ZOffset ) ;
FSceneInterface * Scene = LandscapeProxy - > GetWorld ( ) - > Scene ;
// Hide all but the component
TSet < FPrimitiveComponentId > HiddenPrimitives ;
for ( auto PrimitiveComponentId : Scene - > GetScenePrimitiveComponentIds ( ) )
{
HiddenPrimitives . Add ( PrimitiveComponentId ) ;
}
HiddenPrimitives . Remove ( LandscapeComponent - > SceneProxy - > GetPrimitiveComponentId ( ) ) ;
FIntPoint TargetSize ( TextureSize , TextureSize ) ;
// Render diffuse texture using BufferVisualizationMode=BaseColor
static const FName BaseColorName ( " BaseColor " ) ;
const float BaseColorGamma = 2.2f ;
RenderSceneToTexture ( Scene , BaseColorName , ViewOrigin , ViewRotationMatrix , ProjectionMatrix , HiddenPrimitives , TargetSize , BaseColorGamma , OutSamples ) ;
return true ;
}