Modifying pixels in RenderTarget to draw bounding box

Hi,

I have a SceneCapture2D pointing to a staticmesh (the small metallic thing on the table)

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][2] 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!

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.

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