x

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"

Modifying pixels in RenderTarget to draw bounding box

Hi,

I have a SceneCapture2D pointing to a staticmesh (the small metallic thing on the table) SceneCapture2D with plane showing the captured scene

I also have an algorithm to calculate a 2D Bounding Box around the mesh in the texture. So now I want to see whether the algorithm works, and therefore draw this bounding box onto the Rendertarget / texture.

This is my code for doing that, it is called every tick:

 static void makeRed(TArray<FLinearColor> & ImageData, int i) {
     ImageData[i].R = 1;
     ImageData[i].G = 0;
     ImageData[i].B = 0;
 };
 
 void UTryPixelAccess::drawBoundingBox(UTextureRenderTarget2D * RenderTexture, FBox2D Bounds)
 {
     TArray<FLinearColor> ImageData;
     FRenderTarget *RenderTarget = RenderTexture->GameThread_GetRenderTargetResource();
     RenderTarget->ReadLinearColorPixels(ImageData);
 
     //todo: lock data?
 
     int x1 = Bounds.Min.X;
     int y1 = Bounds.Min.Y;
     int x2 = Bounds.Max.X;
     int y2 = Bounds.Max.Y;
 
     // lambda for array access
     auto toIndex = [RenderTexture](int x, int y) {
         return x + y * RenderTexture->SizeX;
     };
     
     // horizontal lines
     for (x1 = Bounds.Min.X; x1 <= Bounds.Max.X; x1++) {
         makeRed(ImageData, toIndex(x1, y1));
         makeRed(ImageData, toIndex(x1, y2));
     }
 
     // vertical lines
     x1 = Bounds.Min.X;
     for (y1 = Bounds.Min.Y; y1 <= Bounds.Max.X; y1++) {
         makeRed(ImageData, toIndex(x1, y1));
         makeRed(ImageData, toIndex(x2, y1));
     }
 }

The problem is: it does not work! With debugging the code I can see that the pixel values are modified as wished. But the plane showing that RenderTarget Texture still does not have a red bounding box drawn onto it...

So for me there are possibilities what could be the problem:

  • I´m not accessing the real data, but only a copy of it (which is wondering, because in this post they make a copy themself after reading the pixels - so it should be the real data?)

  • The pixels are overritten by the engine before they are rendered, so I need some kind of write protection

  • maybe I completly misunderstood the concept of a RenderTarget (I´m very new to Unreal)

Or is there another, simpler way of drawing the box onto the material/texture/renderTarget itself? Maybe with blueprint scripting?

I´m thankful for any advice!

Product Version: UE 4.19
Tags:
more ▼

asked Sep 27 '18 at 08:36 AM in C++ Programming

avatar image

DaKenpachi
79 4 6 9

(comments are locked)
10|2000 characters needed characters left

2 answers: sort voted first

Found out that you can use Blueprint functions for drawing on render targets. But the do not work if the SceneCaputer is set to capture every frame.

alt text

more ▼

answered Dec 19 '18 at 01:05 PM

avatar image

DaKenpachi
79 4 6 9

(comments are locked)
10|2000 characters needed characters left

For the sake of completeness: I found a way to do this even when "capture every frame" is active. I derived an own class from USceneCaptureComponent2D and extended its UpdateSceneReferred():

 void UMySceneCaptureComponent2D::UpdateSceneCaptureContents(FSceneInterface * Scene)
 {
     Super::UpdateSceneCaptureContents(Scene);
     if (TargetActors.Num() > 0) {
         DrawTargetActorBounds();
     }
 }
 
 void UMySceneCaptureComponent2D::DrawTargetActorBounds()
 {
     UObject* WorldContext = this;
     UCanvas* Canvas;
     FVector2D Size;
     FDrawToRenderTargetContext Context;
     UKismetRenderingLibrary::BeginDrawCanvasToRenderTarget(WorldContext, this->TextureTarget, Canvas, Size, Context);
     if (Canvas) {
 
         for (size_t i = 0; i < TargetActors.Num(); i++)
         {
             FLinearColor color = (TargetColors.Num() > i ? TargetColors[i] : DefaultColor);
             FVector Origin, Extend;
             TArray<FVector> Points;
             TArray<FVector2D> Pixels;
             FBox2D Bounds;
             (TargetActors[i])->GetActorBounds(false, Origin, Extend);
             if (UMyPixelUtility::calcBoundingFromViewInfo(this, Origin, Extend, Bounds, Points, Pixels)) {
                 // not possible in UE 4.19:
                 //FVector2D BoundExtend = (Bounds.Max - Bounds.Min) / 2.0;
                 //Canvas->K2_DrawBox((Bounds.Min + BoundExtend), BoundExtend, LineThickness, color);
                 FVector2D TopRight(Bounds.Max.X, Bounds.Min.Y);
                 FVector2D BottomLeft(Bounds.Min.X, Bounds.Max.Y);
                 Canvas->K2_DrawLine(Bounds.Min, TopRight, LineThickness, color);
                 Canvas->K2_DrawLine(Bounds.Min, BottomLeft, LineThickness, color);
                 Canvas->K2_DrawLine(Bounds.Max, TopRight, LineThickness, color);
                 Canvas->K2_DrawLine(Bounds.Max, BottomLeft, LineThickness, color);
             }
         }
     }
     else {
         UE_LOG(LogTemp, Warning, TEXT("No Canvas could be created from TextureTarget"));
     }
     UKismetRenderingLibrary::EndDrawCanvasToRenderTarget(WorldContext, Context);
 }

If you want to know whats in the calcBoundsFromViewInfo method, you can take a look in this post

more ▼

answered Dec 20 '18 at 08:21 PM

avatar image

DaKenpachi
79 4 6 9

(comments are locked)
10|2000 characters needed characters left
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