RealtimeStyleTransferRuntime/Plugins/PocketWorlds/Source/Private/PocketCapture.cpp

357 lines
10 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "PocketCapture.h"
#include "Components/SceneCaptureComponent2D.h"
#include "Engine/TextureRenderTarget2D.h"
#include "PocketCaptureSubsystem.h"
#include "Camera/CameraComponent.h"
#include "Components/PrimitiveComponent.h"
// UPocketCapture
//---------------------------------------------------------------------------------
UPocketCapture::UPocketCapture()
{
}
void UPocketCapture::Initialize(UWorld* InWorld, int32 InRendererIndex)
{
PrivateWorld = InWorld;
RendererIndex = InRendererIndex;
CaptureComponent = NewObject<USceneCaptureComponent2D>(this, "Thumbnail_Capture_Component");
CaptureComponent->RegisterComponentWithWorld(InWorld);
CaptureComponent->bConsiderUnrenderedOpaquePixelAsFullyTranslucent = true;
CaptureComponent->PrimitiveRenderMode = ESceneCapturePrimitiveRenderMode::PRM_UseShowOnlyList;
CaptureComponent->bCaptureEveryFrame = false;
CaptureComponent->bCaptureOnMovement = false;
CaptureComponent->bAlwaysPersistRenderingState = true;
//UE_LOG(LogPocketLevels, Log, TEXT("ThumbnailRenderer: Initialize:%s"), *GetName());
}
void UPocketCapture::Deinitialize()
{
CaptureComponent->UnregisterComponent();
//UE_LOG(LogPocketLevels, Log, TEXT("ThumbnailRenderer: Deinitialize:%s"), *GetName());
}
void UPocketCapture::BeginDestroy()
{
Super::BeginDestroy();
if (CaptureComponent)
{
CaptureComponent->UnregisterComponent();
CaptureComponent = nullptr;
}
}
void UPocketCapture::SetRenderTargetSize(int32 Width, int32 Height)
{
if (SurfaceWidth != Width || SurfaceHeight != Height)
{
SurfaceWidth = Width;
SurfaceHeight = Height;
if (DiffuseRT)
{
DiffuseRT->ResizeTarget(SurfaceWidth, SurfaceHeight);
}
if (AlphaMaskRT)
{
AlphaMaskRT->ResizeTarget(SurfaceWidth, SurfaceHeight);
}
if (EffectsRT)
{
EffectsRT->ResizeTarget(SurfaceWidth, SurfaceHeight);
}
}
//UE_LOG(LogPocketLevels, Log, TEXT("ThumbnailRenderer: SetRenderTargetSize:%dx%d"), Width, Height);
}
UTextureRenderTarget2D* UPocketCapture::GetOrCreateDiffuseRenderTarget()
{
if (DiffuseRT == nullptr)
{
DiffuseRT = NewObject<UTextureRenderTarget2D>(this, TEXT("ThumbnailRenderer_Diffuse"));
DiffuseRT->RenderTargetFormat = RTF_RGBA8;
DiffuseRT->InitAutoFormat(SurfaceWidth, SurfaceHeight);
DiffuseRT->UpdateResourceImmediate(true);
}
return DiffuseRT;
}
UTextureRenderTarget2D* UPocketCapture::GetOrCreateAlphaMaskRenderTarget()
{
if (AlphaMaskRT == nullptr)
{
AlphaMaskRT = NewObject<UTextureRenderTarget2D>(this, TEXT("ThumbnailRenderer_AlphaMask"));
AlphaMaskRT->RenderTargetFormat = RTF_R8;
AlphaMaskRT->InitAutoFormat(SurfaceWidth, SurfaceHeight);
AlphaMaskRT->UpdateResourceImmediate(true);
}
return AlphaMaskRT;
}
UTextureRenderTarget2D* UPocketCapture::GetOrCreateEffectsRenderTarget()
{
if (EffectsRT == nullptr)
{
EffectsRT = NewObject<UTextureRenderTarget2D>(this, TEXT("ThumbnailRenderer_Fx"));
EffectsRT->RenderTargetFormat = RTF_R8;
EffectsRT->InitAutoFormat(SurfaceWidth, SurfaceHeight);
EffectsRT->UpdateResourceImmediate(true);
}
return EffectsRT;
}
void UPocketCapture::SetCaptureTarget(AActor* InCaptureTarget)
{
CaptureTargetPtr = InCaptureTarget;
OnCaptureTargetChanged(InCaptureTarget);
}
void UPocketCapture::SetAlphaMaskedActors(const TArray<AActor*>& InCaptureTargets)
{
AlphaMaskActorPtrs.Reset();
for (AActor* CaptureTarget : InCaptureTargets)
{
AlphaMaskActorPtrs.Add(CaptureTarget);
}
}
UPocketCaptureSubsystem* UPocketCapture::GetThumbnailSystem() const
{
return CastChecked<UPocketCaptureSubsystem>(GetOuter());
}
TArray<UPrimitiveComponent*> UPocketCapture::GatherPrimitivesForCapture(const TArray<AActor*>& InCaptureActors) const
{
const bool bIncludeFromChildActors = true;
TArray<UPrimitiveComponent*> PrimitiveComponents;
for (AActor* CaptureActor : InCaptureActors)
{
TArray<UPrimitiveComponent*> ChildPrimitiveComponents;
CaptureActor->GetComponents(ChildPrimitiveComponents, bIncludeFromChildActors);
for (UPrimitiveComponent* ChildPrimitiveComponent : ChildPrimitiveComponents)
{
if (!ChildPrimitiveComponent->bHiddenInGame)
{
PrimitiveComponents.Add(ChildPrimitiveComponent);
}
}
}
return PrimitiveComponents;
}
bool UPocketCapture::CaptureScene(UTextureRenderTarget2D* InRenderTarget, const TArray<AActor*>& InCaptureActors, ESceneCaptureSource InCaptureSource, UMaterialInterface* OverrideMaterial)
{
if (InRenderTarget == nullptr)
{
//UE_LOG(LogPocketLevels, Error, TEXT(""));
return false;
}
if (AActor* CaptureTarget = CaptureTargetPtr.Get())
{
if (InCaptureActors.Num() > 0)
{
TArray<UPrimitiveComponent*> PrimitiveComponents = GatherPrimitivesForCapture(InCaptureActors);
GetThumbnailSystem()->StreamThisFrame(PrimitiveComponents);
TArray<UMaterialInterface*> OriginalMaterials;
if (OverrideMaterial)
{
for (UPrimitiveComponent* PrimitiveComponent : PrimitiveComponents)
{
const int32 MaterialCount = PrimitiveComponent->GetNumMaterials();
for (int32 MaterialIndex = 0; MaterialIndex < MaterialCount; MaterialIndex++)
{
OriginalMaterials.Add(PrimitiveComponent->GetMaterial(MaterialIndex));
PrimitiveComponent->SetMaterial(MaterialIndex, OverrideMaterial);
}
}
}
UCameraComponent* Camera = CaptureTarget->FindComponentByClass<UCameraComponent>();
if (ensure(Camera))
{
CaptureComponent->ShowOnlyActors = InCaptureActors;
FMinimalViewInfo CaptureView;
Camera->GetCameraView(0, CaptureView);
// We need to make sure the texture streamer takes into account this new location,
// this request only lasts for one tick, so we call it every time we need to draw,
// so that they stay resident.
//IStreamingManager::Get().AddViewSlaveLocation(CaptureView.Location);
CaptureComponent->TextureTarget = InRenderTarget;
CaptureComponent->PostProcessSettings = Camera->PostProcessSettings;
CaptureComponent->SetCameraView(CaptureView);
CaptureComponent->ShowFlags.SetDepthOfField(false);
CaptureComponent->ShowFlags.SetMotionBlur(false);
CaptureComponent->ShowFlags.SetScreenPercentage(false);
CaptureComponent->ShowFlags.SetScreenSpaceReflections(false);
CaptureComponent->ShowFlags.SetDistanceFieldAO(false);
CaptureComponent->ShowFlags.SetLensFlares(false);
CaptureComponent->ShowFlags.SetOnScreenDebug(false);
//CaptureComponent->ShowFlags.SetEyeAdaptation(false);
CaptureComponent->ShowFlags.SetColorGrading(false);
CaptureComponent->ShowFlags.SetCameraImperfections(false);
CaptureComponent->ShowFlags.SetVignette(false);
CaptureComponent->ShowFlags.SetGrain(false);
CaptureComponent->ShowFlags.SetSeparateTranslucency(false);
CaptureComponent->ShowFlags.SetScreenPercentage(false);
CaptureComponent->ShowFlags.SetScreenSpaceReflections(false);
CaptureComponent->ShowFlags.SetTemporalAA(false);
// might cause reallocation if we render rarely to it - for now off
CaptureComponent->ShowFlags.SetAmbientOcclusion(false);
// Requires resources in the FScene, which get reallocated for every temporary scene if enabled
CaptureComponent->ShowFlags.SetIndirectLightingCache(false);
CaptureComponent->ShowFlags.SetLightShafts(false);
CaptureComponent->ShowFlags.SetPostProcessMaterial(false);
CaptureComponent->ShowFlags.SetHighResScreenshotMask(false);
CaptureComponent->ShowFlags.SetHMDDistortion(false);
CaptureComponent->ShowFlags.SetStereoRendering(false);
CaptureComponent->ShowFlags.SetVolumetricFog(false);
CaptureComponent->ShowFlags.SetVolumetricLightmap(false);
CaptureComponent->ShowFlags.SetSkyLighting(false);
CaptureComponent->CaptureSource = InCaptureSource;
CaptureComponent->ProfilingEventName = TEXT("Pocket Capture");
CaptureComponent->CaptureScene();
if (OriginalMaterials.Num() > 0)
{
int32 TotalMaterialIndex = 0;
for (UPrimitiveComponent* PrimitiveComponent : PrimitiveComponents)
{
const int32 MaterialCount = PrimitiveComponent->GetNumMaterials();
for (int32 MaterialIndex = 0; MaterialIndex < MaterialCount; MaterialIndex++)
{
PrimitiveComponent->SetMaterial(MaterialIndex, OriginalMaterials[TotalMaterialIndex]);
TotalMaterialIndex++;
}
}
}
return true;
}
}
else
{
//UE_LOG(LogPocketLevels, Warning, TEXT("UPocketCapture: %s CaptureScene Failed: No Capture Actors"), *GetName());
}
}
else
{
//UE_LOG(LogPocketLevels, Warning, TEXT("UPocketCapture: %s CaptureScene Failed: No Capture Target"), *GetName());
}
return false;
}
void UPocketCapture::CaptureDiffuse()
{
if (UTextureRenderTarget2D* RenderTarget = GetOrCreateDiffuseRenderTarget())
{
TArray<AActor*> CaptureActors;
if (AActor* CaptureTarget = CaptureTargetPtr.Get())
{
CaptureTarget->GetAttachedActors(CaptureActors);
CaptureActors.Add(CaptureTarget);
}
CaptureScene(RenderTarget, CaptureActors, ESceneCaptureSource::SCS_FinalColorLDR, nullptr);
}
}
void UPocketCapture::CaptureAlphaMask()
{
if (UTextureRenderTarget2D* RenderTarget = GetOrCreateAlphaMaskRenderTarget())
{
TArray<AActor*> CaptureActors;
for (const TWeakObjectPtr<AActor>& AlphaMaskTargetPtr : AlphaMaskActorPtrs)
{
if (AActor* AlphaMaskTarget = AlphaMaskTargetPtr.Get())
{
CaptureActors.Add(AlphaMaskTarget);
}
}
CaptureScene(RenderTarget, CaptureActors, ESceneCaptureSource::SCS_SceneColorHDR, AlphaMaskMaterial);
}
}
void UPocketCapture::CaptureEffects()
{
if (UTextureRenderTarget2D* RenderTarget = GetOrCreateEffectsRenderTarget())
{
ensure(false);//TODO
TArray<AActor*> CaptureActors;
CaptureScene(RenderTarget, CaptureActors, ESceneCaptureSource::SCS_SceneColorHDR, EffectMaskMaterial);
}
}
void UPocketCapture::ReleaseResources()
{
if (DiffuseRT)
{
DiffuseRT->ReleaseResource();
}
if (AlphaMaskRT)
{
AlphaMaskRT->ReleaseResource();
}
if (EffectsRT)
{
EffectsRT->ReleaseResource();
}
//OnReleaseResources();
}
void UPocketCapture::ReclaimResources()
{
if (DiffuseRT)
{
DiffuseRT->UpdateResource();
}
if (AlphaMaskRT)
{
AlphaMaskRT->UpdateResource();
}
if (EffectsRT)
{
EffectsRT->UpdateResource();
}
//OnReclaimResources();
}
int32 UPocketCapture::GetRendererIndex() const
{
return RendererIndex;
}