Is there an existing way to dynamically update textures on landscape materials?

I’m looking for a way to write to a texture in my landscape material.

I got this working with static meshes by creating an actor which takes in a mesh and a material that contains the texture i want to modify, during initialization i create a dynamic material and apply it to the mesh.

UMaterialInstanceDynamic* DynamicMaterialInstance = UMaterialInstanceDynamic::Create(MasterMaterial, this);

		RenderedTexture = CastChecked<UScriptedTexture>(StaticConstructObject(UScriptedTexture::StaticClass()));
		RenderedTexture->AddToRoot();
		RenderedTexture->ClearColor = FLinearColor::White;
		RenderedTexture->bNeedsTwoCopies = false;
		RenderedTexture->bHDR = false;
		RenderedTexture->InitAutoFormat(1024, 1024);
		RenderedTexture->SetOnScriptedTextureRender(this); //James uses callbacks for this but i prefer interfaces so i modified his implementation of ScriptedTexture.

		CanvasItem = new FCanvasTileItem(FVector2D(0.0f, 0.0f), Texture->Resource, FLinearColor::White);
		DynamicMaterialInstance->SetTextureParameterValue(FName("WriteableTextureParam"), RenderedTexture);
		Mesh->SetMaterial(0, DynamicMaterialInstance);

I don’t see a way to do add a landscape to a class blueprint like we can with static meshes… I noticed that i can get a reference to my terrain in the level blueprint, but there is currently no way to get access to the material and create a dynamic version of it to propagate it to my actor which does the texture writing. I thought about adding functionality to expose the terrain material to the level blueprint but it looked like Epic hid this functionality from us on purpose as they implemented it as an editor only feature as seen in Landscape.h (Is there any reason why i shouldn’t expose this functionality to the landscape blueprint?);

#if WITH_EDITOR
	virtual UMaterialInterface* GetLandscapeMaterial() const OVERRIDE;
...
#endif

My next route was to use Material Parameter Collections to achieve my goal but noticed that there is currently no support for using texture paramaters (only scalers and vectors). I started to implement support for texures but stopped as there is some refactoring that needs to be done because memory alignment is important in their current implementation and adding texture params would throw it off.

Has anyone ran into this problem? Is there an existing way to dynamically update textures on landscape materials?

I tried being sneaky and Adding a landscape pointer to my actor that modifies textures

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Terrain)
class ALandscape* Landscape;

Then i assigned the landscape to my actor in my level blueprint

I had to be hacky when assigning the material because my actors PostInit() gets called before EventBeginPlay, so in my tick function i added:

if (DynamicMaterialInstance && Landscape && LandscapeInitialized == false)
{
    Landscape->LandscapeMaterial = DynamicMaterialInstance;
    landscapeInitialized = true;
}

This reassigns the landscape material at runtime but it doesn’t actually update the material that is drawing :(. I dug into the landscape creation a bit more and it looks like the landscape materials require a UMaterialInstanceConstant and is applied when you first drag your material onto the terrain.

I’m going to keep digging into this to try to make dynamic materials work for landscapes, but if anyone has any ideas that could help out please let me know!

Hello,

We have not heard from you in a while and for tracking purposes we have marked this answer as resolved. If you still have a question relating to this post, or are still experiencing this issue, please create a new post on the AnswerHub and we will be glad to assist you!

Thank you.