Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

How to write to UCanvasRenderTarget2D in C++

I have a pretty simple setup for a RenderCanvasTarget2D in Blueprint which I am trying to recreate in C++, but it's not working for some reason.

Here is the BP version:

In a BP derived from RenderCanvasTarget2D, this is the 'Event Receive Update' delegate function:

alt text

And then in a BP actor, I have this in BeginPlay:

alt text

This successfully creates a CanvasRenderTarget2D of 128x128 pixels, writes a diagonal line across it, and saves it to the hard disk. All working perfectly.

In the C++ version, I am doing everything in a single actor called 'HDRWriter'. Here is the full relevant code:


 #include "CoreMinimal.h"
 #include "GameFramework/Actor.h"
 #include "Runtime/Engine/Classes/Engine/CanvasRenderTarget2D.h"
 #include "Runtime/Core/Public/Delegates/Delegate.h"
 #include "Runtime/Engine/Classes/Engine/Canvas.h"
 #include "Runtime/Engine/Classes/Kismet/KismetRenderingLibrary.h"
 #include "HDRWriter.generated.h"
 class DRAWLINEBP_API AHDRWriter : public AActor
     // Sets default values for this actor's properties
     // The Canvas Render Target 2D
     UPROPERTY(EditAnywhere, BlueprintReadWrite)
     UCanvasRenderTarget2D* CanvasRenderTarget;
     // Update Function
     void WhenCanvasUpdated(UCanvas* Canvas, int32 Width, int32 Height);
     void CallUpdate();
     void SetupCanvas();
     // Called when the game starts or when spawned
     virtual void BeginPlay() override;


 #include "HDRWriter.h"
 // Sets default values
      // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
     PrimaryActorTick.bCanEverTick = false;
 void AHDRWriter::WhenCanvasUpdated(UCanvas* Canvas, int32 Width, int32 Height)
     Canvas->K2_DrawLine(FVector2D(0.0f, 0.0f), FVector2D(Width, Height));
     UKismetRenderingLibrary::ExportRenderTarget(GEngine->GetWorld(), CanvasRenderTarget, "D:\\", "CPPLine.hdr");
 void AHDRWriter::CallUpdate()
 void AHDRWriter::SetupCanvas()
     CanvasRenderTarget = UCanvasRenderTarget2D::CreateCanvasRenderTarget2D(GEngine->GetWorld(), UCanvasRenderTarget2D::StaticClass(), 128, 128);
     CanvasRenderTarget->OnCanvasRenderTargetUpdate.AddDynamic(this, &AHDRWriter::WhenCanvasUpdated);
 // Called when the game starts or when spawned
 void AHDRWriter::BeginPlay()
 // Called every frame
 void AHDRWriter::Tick(float DeltaTime)

So I run SetupCanvas to create the CanvasRenderTarget2D and bind a function (WhenCanvasUpdated) to the delegate OnCanvasRenderTargetUpdate. When I then call CallUpdate() it calls UpdateResource() on the CanvasRenderTarget.

When the function WhenCanvasUpdated() is then run, it should draw a line and save the file to the hard disk, as with the Blueprint version.

However, a file is indeed saved, but it is totally black - no line is drawn. I feel like I'm missing some important connection between the RenderCanvasTarget and the UCanvas that is passed in the delegate function, but I can't see how they should be connected.

I tried nativizing the BP into C++ code, but found it to be completely illegible.

Does anyone know what I'm doing wrong here?


Product Version: UE 4.18
more ▼

asked Mar 12 '18 at 06:03 PM in C++ Programming

avatar image

68 16 22 31

avatar image Beriol Apr 09 '18 at 05:15 PM

Got the same problem as you! Did you find a solution?

avatar image Velrin Apr 09 '18 at 05:21 PM

Have you tried calling UpdateResources() after K2_DrawLine() before you ExportRenderTarget?

That will force the canvas to redraw.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

Is there a reason you're using OnCanvasRenderTargetUpdate rather than manually controlling the drawing yourself? I'm using a CanvasRenderTarget2D successfully in C++, but my flow looks like:

 UCanvas * canvas;
 FVector2D canvasSize;
 FDrawToRenderTargetContext context;
 FVector location = GetActorLocation();
 UKismetRenderingLibrary::BeginDrawCanvasToRenderTarget(this, MiniMapCanvasRenderTarget, canvas, canvasSize, context);
 FVector2D lineLocStart = FVector2D(location.X / 300 * 16, location.Y / 300 * 16);
 FVector2D lineLocEnd = lineLocStart + FVector2D(15, 0);
 canvas->K2_DrawLine(lineLocStart, lineLocEnd, 2.0f, FLinearColor::Yellow);
 UKismetRenderingLibrary::EndDrawCanvasToRenderTarget(this, context);

Granted, I'm not using ExportRenderTarget, but rather generating a dynamic material instance with the contents, but still, it's properly updating the canvas.

more ▼

answered May 09 '19 at 01:39 AM

avatar image


(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question