Hi Devs,
I’m trying to make a thumbnail for my save system based on latest screenshot like many games do.
To do that, I created my own APawn (see below). I created both methods:
- captureScene() which use USceneCaptureComponent2D to fill my UTextureRenderTarget2D
- dumpCapture() which read UTextureRenderTarget2D (GPU data) to write a CPU buffer
I connect the both methods to a GUI button
Currently, if I look my ingame pawn inside editor, all looks good and texture target has a good picture.
But when I press my button, I read a black image which is not my clearColor of this buffer and no error return by API.
In this code, I make a full capture every time to fill this cursed UTextureRenderTarget2D (not optimized I know but is not my issue for now).
Please help me to find my bug !!
Thanks !!!
I’m on UnrealEngine 5.2.0 official package.
Code:
APaysanPawn::APaysanPawn()
{
// Don t rotate character to camera direction
bUseControllerRotationPitch = false;
bUseControllerRotationYaw = false;
bUseControllerRotationRoll = false;
const float radius = 80.0f;
SphereCapsule = CreateDefaultSubobject<USphereComponent>(TEXT("SphereCapsule"));
SphereCapsule->SetSphereRadius(radius);
SphereCapsule->SetRelativeLocation(FVector(0.0f, 0.0f, radius));
SetRootComponent(SphereCapsule);
NavMovement = CreateDefaultSubobject<UFloatingPawnMovement>(TEXT("NavMovement"));
NavMovement->bConstrainToPlane = true;
NavMovement->bSnapToPlaneAtStart = true;
NavMovement->SetUpdatedComponent(SphereCapsule);
// Create a camera boom...
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(SphereCapsule);
CameraBoom->SetUsingAbsoluteRotation(true); // Dont want arm to rotate when character does
CameraBoom->TargetArmLength = 3000.f;
CameraBoom->SetRelativeRotation(FRotator(-60.f, 0.f, 0.f));
CameraBoom->bDoCollisionTest = false; // Dont want to pull camera in when it collides with level
// Create a camera...
TopDownCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("TopDownCamera"));
TopDownCameraComponent->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
TopDownCameraComponent->bUsePawnControlRotation = false; // Camera does not rotate relative to arm
// Create capture component + texture
_textureRender = NewObject<UTextureRenderTarget2D>(this, TEXT("ScreenShot"));
_textureRender->InitAutoFormat(512, 512);
_textureRender->ClearColor = FColor::Magenta;
_textureRender->bGPUSharedFlag = true;
_textureRender->TargetGamma = 1.0f;
_textureRender->UpdateResourceImmediate();
Capture = CreateDefaultSubobject<USceneCaptureComponent2D>(TEXT("SceneCapture"));
Capture->TextureTarget = _textureRender;
Capture->CaptureSource = SCS_FinalColorLDR;
Capture->SetupAttachment(CameraBoom);
// Activate ticking in order to update the cursor every frame.
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = true;
}
void APaysanPawn::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
}
void APaysanPawn::captureScene() const
{
check(Capture != nullptr && _textureRender != nullptr);
Capture->CaptureScene();
}
TArray64<uint8> APaysanPawn::dumpCapture() const
{
check(Capture != nullptr && _textureRender != nullptr);
TArray64<uint8> CompressedBitmap;
FImage image;
if (FImageUtils::GetRenderTargetImage(_textureRender, image))
{
if (!FImageUtils::CompressImage(CompressedBitmap, TEXT("jpg"), image))
{
verifyf(false, TEXT("Can't compress render target image to jpg"))
}
}
else
{
verifyf(false, TEXT("Can't read render target image"));
}
return CompressedBitmap;
}
with this .h
UCLASS(Blueprintable)
class APaysanPawn : public APawn
{
GENERATED_BODY()
public:
APaysanPawn();
// Called every frame.
virtual void Tick(float DeltaSeconds) override;
/** Returns TopDownCameraComponent subobject **/
FORCEINLINE class UCameraComponent* GetTopDownCameraComponent() const { return TopDownCameraComponent; }
/** Returns CameraBoom subobject **/
FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
void captureScene() const;
TArray64<uint8> dumpCapture() const;
private:
/** Top down camera */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
class UCameraComponent* TopDownCameraComponent = nullptr;
/** Camera boom positioning the camera above the character */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
class USpringArmComponent* CameraBoom = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
class USphereComponent* SphereCapsule = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
class UNavMovementComponent* NavMovement = nullptr;
UPROPERTY()
UTextureRenderTarget2D* _textureRender = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
USceneCaptureComponent2D* Capture = nullptr;
};