UE5 - Alpha inverted- USceneCaptureComponent2D capture transparent background scene

UE v5.3.2

I have the following Actor to capture scene into a PNG image. I want it renders a person with transparent background but I got something inverted.

Here is my project setting

Why Alpha is inverted? Am I doing something wrong? I can only invert it back pixel by pixel? that is low-efficient because I am trying to stream the scene.

UCLASS()
class MYPROJECT2_API ASceneStreamProducer : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ASceneStreamProducer();


	UPROPERTY(EditAnywhere, Category = "Output Information", meta = (ClampMin = "32", ClampMax = "4096", UIMin = "32", UIMax = "4096"))
	uint32 ResolutionX;

	UPROPERTY(EditAnywhere, Category = "Output Information", meta = (ClampMin = "32", ClampMax = "4096", UIMin = "32", UIMax = "4096"))
	uint32 ResolutionY;

	UPROPERTY(EditAnywhere, Category = "Output Information", meta = (ClampMin = "20.0", ClampMax = "170.0", UIMin = "20.0", UIMax = "179.9"))
	float FieldOfView;

	UPROPERTY(EditAnywhere, Category = "Stereo Setup")
	FVector OurCameraTranslation;

	UPROPERTY(EditAnywhere, Category = "Stereo Setup")
	FQuat OurCameraRotation;


protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UTextureRenderTarget2D* RenderTarget;
	USceneCaptureComponent2D* SceneCapture;
	UCameraComponent* OurCamera;
};



// Sets default values
ASceneStreamProducer::ASceneStreamProducer()
	: RenderTarget(0)
	, SceneCapture(0)
	, ResolutionX(1920)
	, ResolutionY(1080)
	, FieldOfView(90.0f)
	, OurCameraTranslation(0.0f, 0.0f, 0.0f)
	, OurCameraRotation(0., 0., 0., 1.)
{
	PrimaryActorTick.bCanEverTick = true;

	// Only tick once all updates regarding movement and physics have happened
	PrimaryActorTick.TickGroup = TG_PostUpdateWork;

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

	// Initialize Render Target
	RenderTarget = CreateDefaultSubobject<UTextureRenderTarget2D>(TEXT("RenderTarget"));
	RenderTarget->RenderTargetFormat = ETextureRenderTargetFormat::RTF_RGBA8; // Adjust format as needed
	RenderTarget->InitAutoFormat(ResolutionX, ResolutionY); // Set desired width and height

	OurCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("ViewportCamera"));
	OurCamera->SetupAttachment(RootComponent);

	SceneCapture = CreateDefaultSubobject<USceneCaptureComponent2D>(TEXT("SceneCapture"));
	SceneCapture->SetupAttachment(OurCamera);


	UE_LOG(LogTemp, Warning, TEXT("ASceneStreamProducer has been created!"));

}

// Called when the game starts or when spawned
void ASceneStreamProducer::BeginPlay()
{
	Super::BeginPlay();
	
	UE_LOG(LogTemp, Warning, TEXT("ASceneStreamProducer BeginPlay!"));


	OurCamera->FieldOfView = FieldOfView;
	SceneCapture->FOVAngle = FieldOfView;

	OurCamera->SetRelativeLocation(OurCameraTranslation);
	OurCamera->SetRelativeRotation(OurCameraRotation);


	RenderTarget = NewObject<UTextureRenderTarget2D>();
	RenderTarget->InitCustomFormat(ResolutionX, ResolutionY, EPixelFormat::PF_B8G8R8A8, true);
	RenderTarget->ClearColor = FLinearColor::Transparent;
	RenderTarget->UpdateResourceImmediate();

	
	SceneCapture->CaptureSource = SCS_FinalColorHDR;
	SceneCapture->TextureTarget = RenderTarget;
	SceneCapture->bCaptureEveryFrame = true;
}

// Called every frame
void ASceneStreamProducer::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	auto RenderTargetResource = RenderTarget->GameThread_GetRenderTargetResource();

	if (RenderTargetResource)
	{
		TArray<FColor> PixelBuffer;
		RenderTargetResource->ReadPixels(PixelBuffer);

		const int32 Width = RenderTargetResource->GetSizeX();
		const int32 Height = RenderTargetResource->GetSizeY();

		// Create an FHdrImageWrapper object
		IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
		TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);

		if (ImageWrapper.IsValid())
		{
			// Set the raw pixel data from buffer8
			ImageWrapper->SetRaw(PixelBuffer.GetData(), Width * Height * 4, Width, Height, ERGBFormat::BGRA, 8);

			// Compress the image data
			TArray64<uint8> ImageData = ImageWrapper->GetCompressed();
			// Specify a desired file path
			FString FilePath = "F:\\projects\\ar_muxer\\output\\FrameCapture.png";
			FFileHelper::SaveArrayToFile(ImageData, *FilePath);
			UE_LOG(LogTemp, Warning, TEXT("Frame saved to: %s"), *FilePath);
		}
		else
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to create image wrapper!"));
		}
	}
}

Take the alpha and inside of the RT Texture sample of the Render to texture node add a one minus node before connecting to the alpha channel (inside of the material containing the final render target)

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.