How to take photos at the same time for multiple cameras in pure C++(without blueprint or sth)?

header


#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Engine/TextureRenderTarget2D.h" 
#include "ReplayCrowdSystem.generated.h"


UCLASS()
class CAPTURECAMS_API AReplayCrowdSystem : public AActor
{
	GENERATED_BODY()

public:
	// Sets default values for this actor's properties
	AReplayCrowdSystem();

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

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

	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	bool Debug = false;

	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	TArray<ACameraActor*> Cameras;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FString RelativeDirectory;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FString Prefix;

	UFUNCTION(BlueprintCallable)
	void TakeScreenshot(int CameraIndex);

	UFUNCTION(BlueprintCallable)
	void TakeScreenshots();
	
	UFUNCTION()
	void CompleteImage();

	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
	class USceneCaptureComponent2D* CamCapture;

	UPROPERTY()
	USceneComponent* Root;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	class UTextureRenderTarget2D* RT;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FVector2D RTSize = FVector2D(1024, 1024);
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TEnumAsByte<ETextureRenderTargetFormat> TargetFormat;
	


private:
	class UCameraComponent* Cam;
	
	void InitCapture();

	int32 NumberOfImagesSaved;

};

CPP


#include "ReplayCrowdSystem.h"
#include "Camera/CameraComponent.h"
#include "Components/SceneCaptureComponent2D.h" 
#include "Kismet/KismetRenderingLibrary.h"
#include "Camera/CameraActor.h" 
#include "Camera/CameraComponent.h" 
#include "ImageWriteBlueprintLibrary.h" 

// Sets default values
AReplayCrowdSystem::AReplayCrowdSystem()
{
    Root = CreateDefaultSubobject<USceneComponent>("Root");
    SetRootComponent(Root);
    // 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;

    Cam = CreateDefaultSubobject<UCameraComponent>("Cam");
    Cam->SetupAttachment(Root);
    CamCapture = CreateDefaultSubobject<USceneCaptureComponent2D>("Cam Capture");
    CamCapture->SetupAttachment(Root);
    CamCapture->bCaptureOnMovement = false;
    CamCapture->bCaptureEveryFrame = false;
}

// Called when the game starts or when spawned
void AReplayCrowdSystem::BeginPlay()
{
    Super::BeginPlay();
    InitCapture();


}

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


void AReplayCrowdSystem::InitCapture() {
    if (CamCapture == nullptr) {
        CamCapture = NewObject<USceneCaptureComponent2D>(this);
        CamCapture->RegisterComponent();
        CamCapture->bCaptureOnMovement = false;
        CamCapture->bCaptureEveryFrame = false;        
        CamCapture->DetailMode = EDetailMode::DM_Epic;
    }
    if (RT == nullptr) {
        RT = UKismetRenderingLibrary::CreateRenderTarget2D(GetWorld(), RTSize.X, RTSize.Y);        
    }
}


void AReplayCrowdSystem::TakeScreenshots() {
    NumberOfImagesSaved = 0;
    for (int i = 0; i < Cameras.Num(); i++) {
        if (Cameras[i])
            TakeScreenshot(i);
    }
}

void AReplayCrowdSystem::CompleteImage()
{
    NumberOfImagesSaved++;
    if (Debug == true) {
        if (GEngine) {
            GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Cyan, "Saved [" + FString::FromInt(NumberOfImagesSaved) + "]");
        }

        if (NumberOfImagesSaved == Cameras.Num()) {
            if (GEngine) {
                GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Green, "All Saved");
            }
        }
    }
}


void AReplayCrowdSystem::TakeScreenshot(int CameraIndex)
{
    if (Cameras[CameraIndex])
    {
        InitCapture();

        FString FilePath = FPaths::ProjectContentDir() + RelativeDirectory;
        FString FileName = Prefix + FString::FromInt(CameraIndex) + ".png";

        UE_LOG(LogTemp, Warning, TEXT("camera location:%s"), *Cameras[CameraIndex]->GetActorLocation().ToString());

        if (CamCapture)
        {            
            SetActorLocation(Cameras[CameraIndex]->GetActorLocation());
            SetActorRotation(Cameras[CameraIndex]->GetActorRotation());
            FMinimalViewInfo viewInfo;
            Cam->GetCameraView(0, viewInfo);
            CamCapture->SetCameraView(viewInfo);
            RT->RenderTargetFormat = TargetFormat;
            CamCapture->bAlwaysPersistRenderingState = true;
            CamCapture->CaptureSource = SCS_FinalColorLDR;
            CamCapture->TextureTarget = RT;
            CamCapture->SetCameraView(viewInfo);
            CamCapture->CaptureScene();
            RT->UpdateResourceImmediate(false);
            //UKismetRenderingLibrary::ExportRenderTarget(this, RT, FilePath, FileName);
                                    
            FImageWriteOptions Options;
            Options.bAsync = false;
            Options.bOverwriteFile = true;
            Options.Format = EDesiredImageFormat::PNG;            
            Options.OnComplete.BindUFunction(this, "CompleteImage");
            Options.CompressionQuality = 100;

            UImageWriteBlueprintLibrary::ExportToDisk(RT, FilePath +"/"+ FileName,Options);            
            RT->UpdateResourceImmediate(true);
        }
    }
}

Project
captureCams.zip (5.2 MB)