Announcement

Collapse
No announcement yet.

How to write to UCanvasRenderTarget2D in C++

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • replied
    No responses for two years??? I'm also looking into this topic, and found an article that looks very useful:

    https://www.ue4community.wiki/Legacy...RenderTarget2D

    Leave a comment:


  • started a topic How to write to UCanvasRenderTarget2D in C++

    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:



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


    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:

    HDRWriter.h

    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"
    
    UCLASS()
    class DRAWLINEBP_API AHDRWriter : public AActor
    {
        GENERATED_BODY()
    
    public:    
        // Sets default values for this actor's properties
        AHDRWriter();
    
        // The Canvas Render Target 2D
        UPROPERTY(EditAnywhere, BlueprintReadWrite)
        UCanvasRenderTarget2D* CanvasRenderTarget;
    
        // Update Function
        UFUNCTION()
        void WhenCanvasUpdated(UCanvas* Canvas, int32 Width, int32 Height);
    
        UFUNCTION(BlueprintCallable)
        void CallUpdate();
    
        UFUNCTION(BlueprintCallable)
        void SetupCanvas();
    
    protected:
        // Called when the game starts or when spawned
        virtual void BeginPlay() override;
    
    };
    HDRWriter.cpp

    Code:
    #include "HDRWriter.h"
    
    // Sets default values
    AHDRWriter::AHDRWriter()
    {
         // 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()
    {
        CanvasRenderTarget->UpdateResource();
    }
    
    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()
    {
        Super::BeginPlay();
    }
    
    // Called every frame
    void AHDRWriter::Tick(float DeltaTime)
    {
        Super::Tick(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?

    Thanks!
Working...
X