DefaultMaterialName
DefaultMaterialName
#Overview
name: DefaultMaterialName
The value of this variable can be defined or overridden in .ini config files. 1
.ini config file referencing this setting variable.
It is referenced in 6
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of DefaultMaterialName is to specify the default material used by the Unreal Engine when no other material is assigned or available. This setting is primarily used in the rendering system to ensure that objects always have a valid material to render with, even if one hasn’t been explicitly set.
Based on the Callsites section, this variable is used in several Unreal Engine subsystems and modules:
- DatasmithCADImporter plugin
- CoreUObject module
- MeshMergeUtilities module
- ReplicationSystemTest program
The value of this variable is typically set in the engine configuration files (GEngineIni). In the provided code snippets, we can see it being set in test environments or mock scenarios:
GConfig->SetString(TEXT("/Script/Engine.Engine"), TEXT("DefaultMaterialName"), TEXT("/Engine/Transient.MockDefaultMaterial"), GEngineIni);
This variable interacts with other default material-related variables, such as DefaultLightFunctionMaterialName, DefaultDeferredDecalMaterialName, and DefaultPostProcessMaterialName.
Developers should be aware that:
- This variable is crucial for ensuring all objects have a valid material to render.
- Changing this value can affect the entire rendering pipeline.
- It’s used as a fallback in various scenarios, such as mesh merging and CAD importing.
Best practices when using this variable include:
- Avoid changing it unless absolutely necessary, as it can have wide-ranging effects on the engine’s rendering.
- When setting a custom default material, ensure it’s compatible with all potential use cases in the engine.
- In test environments, use a mock or transient material to avoid dependencies on actual assets.
- Be cautious when merging meshes or importing CAD files, as this default material may be used for undefined or empty material slots.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseEngine.ini:148, section: [/Script/Engine.Engine]
- INI Section:
/Script/Engine.Engine
- Raw value:
/Engine/EngineMaterials/WorldGridMaterial.WorldGridMaterial
- Is Array:
False
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADInterfaces/Private/TechSoftUtils.cpp:296
Scope (from outer to inner):
file
namespace CADLibrary
namespace TechSoftUtils
function void RestoreMaterials
Source code excerpt:
{
FMaterialUId DefaultColorName = 0;
FMaterialUId DefaultMaterialName = 0;
#ifndef CADKERNEL_DEV
DefaultValues->TryGetNumberField(JSON_ENTRY_COLOR_NAME, DefaultColorName);
DefaultValues->TryGetNumberField(JSON_ENTRY_MATERIAL_NAME, DefaultMaterialName);
#endif
BodyMesh.MaterialSet.Empty();
BodyMesh.ColorSet.Empty();
for (FTessellationData& Tessellation : BodyMesh.Faces)
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADInterfaces/Private/TechSoftUtils.cpp:313
Scope (from outer to inner):
file
namespace CADLibrary
namespace TechSoftUtils
function void RestoreMaterials
Source code excerpt:
FMaterialUId ColorUId = DefaultColorName;
FMaterialUId MaterialUId = DefaultMaterialName;
GetMaterialValues(CachedStyleIndex, ColorUId, MaterialUId);
if (ColorUId)
{
Tessellation.ColorUId = ColorUId;
#Loc: <Workspace>/Engine/Source/Developer/LowLevelTestsRunner/Private/TestCommon/CoreUObjectUtilities.cpp:65
Scope (from outer to inner):
file
function void InitCoreUObject
Source code excerpt:
#if WITH_ENGINE && UE_LLT_WITH_MOCK_ENGINE_DEFAULTS
GConfig->SetString(TEXT("/Script/Engine.Engine"), TEXT("AIControllerClassName"), TEXT("/Script/AIModule.AIController"), GEngineIni);
GConfig->SetString(TEXT("/Script/Engine.Engine"), TEXT("DefaultMaterialName"), TEXT("/Engine/Transient.MockDefaultMaterial"), GEngineIni);
GConfig->SetString(TEXT("/Script/Engine.Engine"), TEXT("DefaultLightFunctionMaterialName"), TEXT("/Engine/Transient.MockDefaultMaterial"), GEngineIni);
GConfig->SetString(TEXT("/Script/Engine.Engine"), TEXT("DefaultDeferredDecalMaterialName"), TEXT("/Engine/Transient.MockDefaultMaterial"), GEngineIni);
GConfig->SetString(TEXT("/Script/Engine.Engine"), TEXT("DefaultPostProcessMaterialName"), TEXT("/Engine/Transient.MockDefaultMaterial"), GEngineIni);
#endif // WITH_ENGINE && UE_LLT_WITH_MOCK_ENGINE_DEFAULTS
FModuleManager::Get().LoadModule(TEXT("CoreUObject"));
#Loc: <Workspace>/Engine/Source/Developer/MeshMergeUtilities/Private/MeshMergeUtilities.cpp:3206
Scope (from outer to inner):
file
function void FMeshMergeUtilities::CreateMergedRawMeshes
lambda-function
Source code excerpt:
{
TargetMesh.CreatePolygonGroupWithID(PolygonGroupID);
TargetImportedMaterialSlotNames[PolygonGroupID] = SourceMesh.PolygonGroups().IsValid(PolygonGroupID) ? SourceImportedMaterialSlotNames[PolygonGroupID] : FName(TEXT("DefaultMaterialName"));
}
for (FPolygonGroupID SourcePolygonGroupID : SourceMesh.PolygonGroups().GetElementIDs())
{
RemapPolygonGroups.Add(SourcePolygonGroupID, PolygonGroupID);
}
}
else
{
TArray<SectionRemapPair> SectionMappings;
InDataTracker.GetMappingsForMeshLOD(FMeshLODKey(ComponentIndex, LODIndex), SectionMappings);
for (FPolygonGroupID SourcePolygonGroupID : SourceMesh.PolygonGroups().GetElementIDs())
{
// First map from original section index to unique material index
int32 UniqueIndex = INDEX_NONE;
// then map to the output material map, if any
if (InOutputMaterialsMap.Num() > 0)
{
TArray<MaterialRemapPair> MaterialMappings;
InOutputMaterialsMap.MultiFind(FMeshLODKey(ComponentIndex, LODIndex), MaterialMappings);
for (MaterialRemapPair& Pair : MaterialMappings)
{
if (Pair.Key == SourcePolygonGroupID.GetValue())
{
UniqueIndex = Pair.Value;
break;
}
}
// Note that at this point UniqueIndex is NOT a material index, but a unique section index!
}
if(UniqueIndex == INDEX_NONE)
{
UniqueIndex = SourcePolygonGroupID.GetValue();
}
FPolygonGroupID TargetPolygonGroupID(UniqueIndex);
if (!TargetMesh.PolygonGroups().IsValid(TargetPolygonGroupID))
{
while (TargetMesh.PolygonGroups().Num() <= UniqueIndex)
{
TargetPolygonGroupID = TargetMesh.CreatePolygonGroup();
}
check(TargetPolygonGroupID.GetValue() == UniqueIndex);
TargetImportedMaterialSlotNames[TargetPolygonGroupID] = SourceImportedMaterialSlotNames[SourcePolygonGroupID];
}
RemapPolygonGroups.Add(SourcePolygonGroupID, TargetPolygonGroupID);
}
}
});
AppendSettings.bMergeVertexColor = InSettings.bBakeVertexDataToMesh;
AppendSettings.MergedAssetPivot = InMergedAssetPivot;
for (int32 ChannelIdx = 0; ChannelIdx < FStaticMeshOperations::FAppendSettings::MAX_NUM_UV_CHANNELS; ++ChannelIdx)
{
AppendSettings.bMergeUVChannels[ChannelIdx] = InDataTracker.DoesUVChannelContainData(ChannelIdx, LODIndex) && InSettings.OutputUVs[ChannelIdx] == EUVOutput::OutputChannel;
}
FStaticMeshOperations::AppendMeshDescription(*RawMeshPtr, MergedMesh, AppendSettings);
}
}
//Cleanup the empty material to avoid empty section later
TArray<FPolygonGroupID> PolygonGroupToRemove;
for (FPolygonGroupID PolygonGroupID : MergedMesh.PolygonGroups().GetElementIDs())
{
if (MergedMesh.GetPolygonGroupPolygonIDs(PolygonGroupID).Num() < 1)
{
PolygonGroupToRemove.Add(PolygonGroupID);
#Loc: <Workspace>/Engine/Source/Developer/MeshMergeUtilities/Private/MeshMergeUtilities.cpp:3313
Scope (from outer to inner):
file
function void FMeshMergeUtilities::CreateMergedRawMeshes
lambda-function
Source code excerpt:
{
TargetMesh.CreatePolygonGroupWithID(PolygonGroupID);
TargetImportedMaterialSlotNames[PolygonGroupID] = SourceMesh.PolygonGroups().IsValid(PolygonGroupID) ? SourceImportedMaterialSlotNames[PolygonGroupID] : FName(TEXT("DefaultMaterialName"));
}
for (FPolygonGroupID SourcePolygonGroupID : SourceMesh.PolygonGroups().GetElementIDs())
{
RemapPolygonGroups.Add(SourcePolygonGroupID, PolygonGroupID);
}
}
else
{
TArray<SectionRemapPair> SectionMappings;
InDataTracker.GetMappingsForMeshLOD(FMeshLODKey(ComponentIndex, LODIndex), SectionMappings);
for (FPolygonGroupID SourcePolygonGroupID : SourceMesh.PolygonGroups().GetElementIDs())
{
// First map from original section index to unique material index
int32 UniqueIndex = INDEX_NONE;
// then map to the output material map, if any
if (InOutputMaterialsMap.Num() > 0)
{
TArray<MaterialRemapPair> MaterialMappings;
InOutputMaterialsMap.MultiFind(FMeshLODKey(ComponentIndex, LODIndex), MaterialMappings);
for (MaterialRemapPair& Pair : MaterialMappings)
{
if (Pair.Key == SourcePolygonGroupID.GetValue())
{
UniqueIndex = Pair.Value;
break;
}
}
// Note that at this point UniqueIndex is NOT a material index, but a unique section index!
}
//Fallback
if(UniqueIndex == INDEX_NONE)
{
UniqueIndex = SourcePolygonGroupID.GetValue();
}
FPolygonGroupID TargetPolygonGroupID(UniqueIndex);
if (!TargetMesh.PolygonGroups().IsValid(TargetPolygonGroupID))
{
while (TargetMesh.PolygonGroups().Num() <= UniqueIndex)
{
TargetPolygonGroupID = TargetMesh.CreatePolygonGroup();
}
check(TargetPolygonGroupID.GetValue() == UniqueIndex);
TargetImportedMaterialSlotNames[TargetPolygonGroupID] = SourceImportedMaterialSlotNames[SourcePolygonGroupID];
}
RemapPolygonGroups.Add(SourcePolygonGroupID, TargetPolygonGroupID);
}
}
});
AppendSettings.bMergeVertexColor = InSettings.bBakeVertexDataToMesh;
AppendSettings.MergedAssetPivot = InMergedAssetPivot;
for (int32 ChannelIdx = 0; ChannelIdx < FStaticMeshOperations::FAppendSettings::MAX_NUM_UV_CHANNELS; ++ChannelIdx)
{
AppendSettings.bMergeUVChannels[ChannelIdx] = InDataTracker.DoesUVChannelContainData(ChannelIdx, LODIndex) && InSettings.OutputUVs[ChannelIdx] == EUVOutput::OutputChannel;
}
FStaticMeshOperations::AppendMeshDescription(*RawMeshPtr, MergedMesh, AppendSettings);
}
}
}
}
void FMeshMergeUtilities::MergeComponentsToInstances(const TArray<UPrimitiveComponent*>& ComponentsToMerge, UWorld* World, ULevel* Level, const FMeshInstancingSettings& InSettings, bool bActuallyMerge /*= true*/, bool bReplaceSourceActors /* = false */, FText* OutResultsText /*= nullptr*/) const
{
auto HasInstanceVertexColors = [](UStaticMeshComponent* StaticMeshComponent)
{
for (const FStaticMeshComponentLODInfo& CurrentLODInfo : StaticMeshComponent->LODData)
#Loc: <Workspace>/Engine/Source/Programs/ReplicationSystemTest/Private/ReplicationSystemTest.cpp:165
Scope (from outer to inner):
file
function static void PreInit
Source code excerpt:
GConfig->SetInt(TEXT("/Script/Engine.GarbageCollectionSettings"), TEXT("gc.MaxObjectsNotConsideredByGC"), 0, GEngineIni);
GConfig->SetString(TEXT("/Script/Engine.Engine"), TEXT("AIControllerClassName"), TEXT("/Script/AIModule.AIController"), GEngineIni);
GConfig->SetString(TEXT("/Script/Engine.Engine"), TEXT("DefaultMaterialName"), TEXT("/Engine/Transient.MockDefaultMaterial"), GEngineIni);
GConfig->SetString(TEXT("/Script/Engine.Engine"), TEXT("DefaultLightFunctionMaterialName"), TEXT("/Engine/Transient.MockDefaultMaterial"), GEngineIni);
GConfig->SetString(TEXT("/Script/Engine.Engine"), TEXT("DefaultDeferredDecalMaterialName"), TEXT("/Engine/Transient.MockDefaultMaterial"), GEngineIni);
GConfig->SetString(TEXT("/Script/Engine.Engine"), TEXT("DefaultPostProcessMaterialName"), TEXT("/Engine/Transient.MockDefaultMaterial"), GEngineIni);
// Console commands
IConsoleManager::Get().ProcessUserConsoleInput(TEXT("Net.IsPushModelEnabled 1"), *GLog, nullptr);