Adding textures to a ProceduralMeshComponent

I’m new to Unreal and I’ve been playing with the ProceduralMeshComponent the last few days, using only C++.

I wanted to import meshes at runtime, and I managed to do that with the help of the Assimp library. So, right now I can load any mesh at runtime and it works fine: the thing missing are the textures.

Suppose I have a .obj mesh, with a .mtl file and a single .png texture. Suppose that I have no idea of what mesh I’m going to create a runtime, so I don’t know how many materials there are and so on. How can I create the materials at runtime for this?

I’ve been looking all day on the internet for this kind of situation, but I couldn’t find anything related. People always use materials that are made from within the editor, they don’t create it via C++ code, but that’s what I need.

I’ve looked into instanced materials and tried to do something like this (it’s just an example in which some properties of the material get changed):


// This code is executed everytime a section is added to the procedural mesh
UMaterialInstanceDynamic* dynamic = UMaterialInstanceDynamic::Create(mMesh->GetMaterial(mSectionsCurrentlyProcessed), this);
    
FLinearColor RandomColor;
RandomColor.R = FMath::RandRange(0, 1);
RandomColor.G = FMath::RandRange(0, 1);
RandomColor.B = FMath::RandRange(0, 1);
RandomColor.A = FMath::RandRange(0, 1);
    
if(dynamic)
{
    dynamic->SetVectorParameterValue(FName("Base_Color"), RandomColor);
    dynamic->SetScalarParameterValue(FName("MetalParam"), FMath::RandRange(0, 1));
    dynamic->SetScalarParameterValue("Roughness", 1.0f);
}

The problem is that there is no starting material in my case, and the parameters I’m “modifying” in the example aren’t present since they weren’t defined in the editor.

So, to sum up, I’m running out of ideas. Is there a way to create an empty material from scratch in C++ and then fill it, in particular with a texture?

I’m relatively new to UE too, but the idea which comes to mind is to create a material in the editor, with texture samples/scalar values for diffuse and any other material outputs (normal, opacity etc). Then convert all texture samples and scalars to parameters.

Then in your C++ code, you can create multiple dynamic instances of that base material and set the textures and other parameter values as read in for each mesh.

e.g. this is just copied straight from a project of mine - HexMap_Mat would be your base material. HexMesh one of your procedural meshes. So in this case I’ve referenced the base material directly by name, but you could also create a UMaterial* UPROPERTY and assign it in the editor.


UMaterial* mat = Cast<UMaterial>(StaticLoadObject(UMaterial::StaticClass(), NULL, TEXT("Material'/Game/Map/HexMap_Mat.HexMap_Mat'")));
if (mat != nullptr)
{
	UMaterialInstanceDynamic* grassMat = UMaterialInstanceDynamic::Create(mat, this);
	grassMat->SetVectorParameterValue("HexColour", FLinearColor(1,0,0));
	HexMesh->SetMaterial(0, grassMat);
}

Just keep creating new instances for each mesh and set parameters appropriately.

I completely forgot about this topic. Since nobody anwesered in the days after I wrote here, I kept working and in the ended up doing exactly what you said. I made a “template” empty material that I fill at runtime via code as needed. I couldn’t find any other solution except this!

Hi I’m looking for the same functionality. Can you please enlighten me on how you did it?