Downloading Image and Setting as Material through C++

Hi guys,

I have been trying to display an image on a plane via C++ for the last few days but haven’t figured it out. I feel like I am close but am not very experienced with Unreal engine; I was hoping someone could shed some light/point me in the right direction. Essentially, I am trying to download an image via a specified link and then display that image on a plane (as a material). Currently, I am manually setting the material of the plane, but want to automate it so I can just supply a link to an image and it sets the plane to show that image.

Currently, I have an Actor that has a Root component. I create a UStaticMeshComponent and attach it to the root. Next I use the FObjectFinder to find the plane. I then set that as the StaticMesh. This is in the constructor:

	Root = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
	RootComponent = Root;

	Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
	Mesh->AttachTo(Root);

	
	static ConstructorHelpers::FObjectFinder<UStaticMesh> PlaneMeshAsset(TEXT("StaticMesh'/Engine/BasicShapes/Plane.Plane'"));

	Mesh->SetStaticMesh(PlaneMeshAsset.Object);

	static ConstructorHelpers::FObjectFinder<UMaterial> Material(TEXT("Material'/Game/adv_Mat.adv_Mat'"));

	TheMaterial_Dyn = UMaterialInstanceDynamic::Create((UMaterial*)Material.Object,Mesh);

After this, I simply set the Mesh’s material using the SetMaterial function in the BeginPlay() function.

Mesh->SetMaterial(0, TheMaterial_Dyn);

Now I am trying to modify this code so I can download an Image and display it on the plane. To do this I am first using a UAsyncTaskDownloadImage to download an image. On success, it calls the function to set the texture. From my understanding, the UAsyncTaskDownloadImage OnSucess will return a UTexture2DDynamic. This is where I am stuck. I am not sure how to take this image downloaded from UAsyncTaskDownloadImage and set it as the material on the plane.

	FString mURL = TEXT("http://news.mit.edu/sites/mit.edu.newsoffice/files/styles/news_article_image_top_slideshow/public/images/2019/MIT-Morphing-Wing-01_1.jpg");

	UAsyncTaskDownloadImage* mDownloadTask = NewObject<UAsyncTaskDownloadImage>();
	mDownloadTask->OnSuccess.AddDynamic(this, &AComputerVisionTest::OnGetTexture2D);
	mDownloadTask->Start(mURL);

	Mesh->SetMaterial(0, TheMaterial_Dyn);


void AComputerVisionTest::OnGetTexture2D(UTexture2DDynamic* _texture)
{
//
	TheMaterial_Dyn->SetTextureParameterValue(FName("T2DParam"), _texture);

}

Frankly, I’m not sure if I’m doing this the right way or if there is a better way to do it. Currently, it works when I do it manually (i.e. set the material manually) but I am now trying to do it automatically where it downloads the image. Any help/guidance would be greatly appreciated!

Thanks!

Hey,

I guess you won’t need the solution after three years but your post was a super starting point. So here’s my solution hope it helps others in the future.

void ATileBase::BeginPlay()
{
	Super::BeginPlay();

	imagePlane = Cast<UStaticMeshComponent>(GetDefaultSubobjectByName(TEXT("imagePlane")));


	FString mURL = TEXT("https://www.cooperhewitt.org/wp-content/uploads/2019/10/2016-54-146_01.jpg");

	mDownloadTask = NewObject<UAsyncTaskDownloadImage>();
	mDownloadTask->OnSuccess.AddDynamic(this, &ATileBase::OnGetTexture2D);
	mDownloadTask->Start(mURL);

}

void ATileBase::OnGetTexture2D(UTexture2DDynamic* _texture) {

	auto material = imagePlane->GetMaterial(0);
	UMaterialInstanceDynamic* DynMaterial = imagePlane->CreateDynamicMaterialInstance(0, material, TEXT("2dPlaneMaterial"));
	DynMaterial->SetTextureParameterValue("Image", _texture);
	imagePlane->SetMaterial(0, DynMaterial);

}

I’m using the plane2d material on my plane which has a parameter which you need address to set the image. In my case it’s just “Image”
So that’s what you need to call if you want to change the materials texture.

1 Like

Hello,
I don’t know if you will see it after 8 months, but SetTextureParameterValue() function doesnt take variable type UTexture2DDynamic, it takes UTexture. How did you achieved this have you set custom SetTextureParameterValue() function for this purpose? Thanks!(lol I forgot the header I feel stupid)

How do I setup includes for that? I’m getting a linker error (LNK2019) when I try to use NewObject()