Added style interpolation

This commit is contained in:
Manuel Wagner 2022-09-15 16:56:08 +02:00
parent 6afe2e5736
commit 2230451d77
25 changed files with 254 additions and 82 deletions

View File

@ -36,7 +36,7 @@ ScriptStackOnWarnings=true
GlobalDefaultGameMode=/Game/B_LyraGameMode.B_LyraGameMode_C
GameInstanceClass=/Game/B_LyraGameInstance.B_LyraGameInstance_C
GameDefaultMap=/Game/System/FrontEnd/Maps/L_LyraFrontEnd.L_LyraFrontEnd
EditorStartupMap=/Game/System/DefaultEditorMap/L_DefaultEditorOverview.L_DefaultEditorOverview
EditorStartupMap=/ShooterMaps/Maps/L_Expanse.L_Expanse
[/Script/Hotfix.OnlineHotfixManager]
HotfixManagerClassName=/Script/LyraGame.LyraHotfixManager

View File

@ -221,3 +221,10 @@ VoiceChatVolumeControlBus=/Game/Audio/Modulation/ControlBuses/CB_VoiceChat.CB_Vo
+LDRAudioSubmixEffectChain=(Submix="/Game/Audio/Submixes/MainSubmix.MainSubmix",SubmixEffectChain=("/Game/Audio/DYN_LowMultibandDynamics.DYN_LowMultibandDynamics","/Game/Audio/Effects/SubmixEffects/DYN_LowDynamics.DYN_LowDynamics"))
LoadingScreenControlBusMix=/Game/Audio/Modulation/ControlBusMixes/CBM_LoadingScreenMix.CBM_LoadingScreenMix
[/Script/StyleTransfer.StyleTransferSettings]
StyleTransferNetwork=/StyleTransfer/NN_TransferVGG.NN_TransferVGG
StylePredictionNetwork=/StyleTransfer/NN_PredictorVGG.NN_PredictorVGG
+StyleTextures=/StyleTransfer/T_StyleImage.T_StyleImage
+StyleTextures=/StyleTransfer/T_StyleImage3.T_StyleImage3
InterpolationCurve=(EditorCurveData=(Keys=((InterpMode=RCIM_Cubic,TangentMode=RCTM_User),(InterpMode=RCIM_Cubic,TangentMode=RCTM_User,Time=2.241476,Value=1.000000),(InterpMode=RCIM_Cubic,TangentMode=RCTM_User,Time=3.908512,Value=1.000000),(InterpMode=RCIM_Cubic,TangentMode=RCTM_User,Time=5.831762),(Time=7.971708)),DefaultValue=340282346638528859811704183484516925440.000000,PreInfinityExtrap=RCCE_Constant,PostInfinityExtrap=RCCE_Constant),ExternalCurve=None)

BIN
Plugins/StyleTransfer/Content/NN_PredictorVGG.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Plugins/StyleTransfer/Content/NN_TransferVGG.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Plugins/StyleTransfer/Content/T_StyleImage1.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Plugins/StyleTransfer/Content/T_StyleImage2.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Plugins/StyleTransfer/Content/T_StyleImage3.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Plugins/StyleTransfer/Content/T_StyleImage4.uasset (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,21 @@
// Copyright 2022 Manuel Wagner - All rights reserved
RWBuffer<float> OutputUAV;
Buffer<float> InputSrvA;
Buffer<float> InputSrvB;
uint TensorVolume;
float Alpha;
[numthreads(THREADGROUP_SIZE_X, THREADGROUP_SIZE_Y, THREADGROUP_SIZE_Z)]
void InterpolateTensorsCS(in const uint3 DispatchThreadID : SV_DispatchThreadID)
{
const uint Index = DispatchThreadID.x;
if (Index >= TensorVolume)
{
return;
}
OutputUAV[Index] = lerp(InputSrvA[Index], InputSrvB[Index], Alpha);
}
#include "/Engine/Public/Platform.ush"

View File

@ -1,4 +1,4 @@
// Copyright Epic Games, Inc. All Rights Reserved.
// Copyright Manuel Wagner All Rights Reserved.
#include "StyleTransferModule.h"

View File

@ -12,6 +12,7 @@
#include "SceneView.h"
#include "ScreenPass.h"
#include "CommonRenderResources.h"
#include "InterpolateTensorsCS.h"
#include "IPixWinPlugin.h"
#include "IPixWinPlugin.h"
#include "IRenderCaptureProvider.h"
@ -215,6 +216,39 @@ void FStyleTransferSceneViewExtension::TextureToTensor(FRDGBuilder& GraphBuilder
);
}
void FStyleTransferSceneViewExtension::InterpolateTensors(FRDGBuilder& GraphBuilder, const FNeuralTensor& DestinationTensor, const FNeuralTensor& InputTensorA, const FNeuralTensor& InputTensorB, float Alpha)
{
RDG_EVENT_SCOPE(GraphBuilder, "InterpolateTensors");
const FRDGBufferRef DestinationBuffer = GraphBuilder.RegisterExternalBuffer(DestinationTensor.GetPooledBuffer());
const FRDGBufferRef InputBufferA = GraphBuilder.RegisterExternalBuffer(InputTensorA.GetPooledBuffer());
const FRDGBufferRef InputBufferB = GraphBuilder.RegisterExternalBuffer(InputTensorB.GetPooledBuffer());
auto InterpolateTensorsParameters = GraphBuilder.AllocParameters<FInterpolateTensorsCS::FParameters>();
InterpolateTensorsParameters->InputSrvA = GraphBuilder.CreateSRV(InputBufferA, EPixelFormat::PF_R32_FLOAT);
InterpolateTensorsParameters->InputSrvB = GraphBuilder.CreateSRV(InputBufferB, EPixelFormat::PF_R32_FLOAT);
InterpolateTensorsParameters->OutputUAV = GraphBuilder.CreateUAV(DestinationBuffer);
InterpolateTensorsParameters->Alpha = Alpha;
InterpolateTensorsParameters->TensorVolume = DestinationTensor.Num();
FIntVector InterpolateTensorsThreadGroupCount = FComputeShaderUtils::GetGroupCount(
{CastNarrowingSafe<int32>(DestinationTensor.Num()), 1, 1},
FInterpolateTensorsCS::ThreadGroupSize
);
TShaderMapRef<FInterpolateTensorsCS> InterpolateTensorsCS(GetGlobalShaderMap(GMaxRHIFeatureLevel));
GraphBuilder.AddPass(
RDG_EVENT_NAME("InterpolateTensors"),
InterpolateTensorsParameters,
ERDGPassFlags::Compute,
[InterpolateTensorsCS, InterpolateTensorsParameters, InterpolateTensorsThreadGroupCount](FRHICommandList& RHICommandList)
{
FComputeShaderUtils::Dispatch(RHICommandList, InterpolateTensorsCS,
*InterpolateTensorsParameters, InterpolateTensorsThreadGroupCount);
}
);
}
FScreenPassTexture FStyleTransferSceneViewExtension::PostProcessPassAfterTonemap_RenderThread(FRDGBuilder& GraphBuilder, const FSceneView& View, const FPostProcessMaterialInputs& InOutInputs)
{
const FScreenPassTexture& SceneColor = InOutInputs.Textures[(uint32)EPostProcessMaterialInput::SceneColor];

View File

@ -24,5 +24,8 @@ public:
TSoftObjectPtr<UNeuralNetwork> StylePredictionNetwork = nullptr;
UPROPERTY(EditAnywhere, Config)
TSoftObjectPtr<UTexture2D> StyleTexture = nullptr;
TArray<TSoftObjectPtr<UTexture2D>> StyleTextures;
UPROPERTY(EditAnywhere, Config)
FRuntimeFloatCurve InterpolationCurve;
};

View File

@ -19,6 +19,12 @@ TAutoConsoleVariable<bool> CVarStyleTransferEnabled(
TEXT("Set to true to enable style transfer")
);
TAutoConsoleVariable<bool> CVarAutoCaptureStylePrediction(
TEXT("r.StyleTransfer.AutoCapturePrediction"),
false,
TEXT("Set to true to enable style transfer auto capture for profiling in PIX etc.")
);
void UStyleTransferSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
@ -34,6 +40,26 @@ void UStyleTransferSubsystem::Deinitialize()
Super::Deinitialize();
}
bool UStyleTransferSubsystem::Tick(float DeltaTime)
{
if (!GetWorld())
return true;
if (StylePredictionInferenceContexts.Num() > 1)
{
const UStyleTransferSettings* StyleTransferSettings = GetDefault<UStyleTransferSettings>();
const FRichCurve* InterpCurve = StyleTransferSettings->InterpolationCurve.GetRichCurveConst();
float MinTime, MaxTime;
InterpCurve->GetTimeRange(MinTime, MaxTime);
const double Time = MinTime + FMath::Fmod(GetWorld()->GetTimeSeconds(), static_cast<double>(MaxTime - MinTime));
const float Alpha = InterpCurve->Eval(Time);
UE_LOG(LogStyleTransfer, VeryVerbose, TEXT("Alpha is %0.4f"), Alpha);
InterpolateStyles(StylePredictionInferenceContexts[0], StylePredictionInferenceContexts[1], Alpha);
}
return true;
}
void UStyleTransferSubsystem::StartStylizingViewport(FViewportClient* ViewportClient)
{
if (!StylePredictionNetwork->IsLoaded() || !StyleTransferNetwork->IsLoaded())
@ -45,20 +71,27 @@ void UStyleTransferSubsystem::StartStylizingViewport(FViewportClient* ViewportCl
if (!StyleTransferSceneViewExtension)
{
const UStyleTransferSettings* StyleTransferSettings = GetDefault<UStyleTransferSettings>();
StylePredictionInferenceContext = StylePredictionNetwork->CreateInferenceContext();
checkf(StylePredictionInferenceContext != INDEX_NONE, TEXT("Could not create inference context for StylePredictionNetwork"));
if (!StyleTransferInferenceContext || *StyleTransferInferenceContext == INDEX_NONE)
{
StyleTransferInferenceContext = MakeShared<int32>(StyleTransferNetwork->CreateInferenceContext());
checkf(*StyleTransferInferenceContext != INDEX_NONE, TEXT("Could not create inference context for StyleTransferNetwork"));
}
UTexture2D* StyleTexture = StyleTransferSettings->StyleTexture.LoadSynchronous();
for (int32 i = 0; i < FMath::Min(2, StyleTransferSettings->StyleTextures.Num()); ++i)
{
const int32& StylePredictionInferenceContext = StylePredictionInferenceContexts.Emplace_GetRef(StylePredictionNetwork->CreateInferenceContext());
checkf(StylePredictionInferenceContext != INDEX_NONE, TEXT("Could not create inference context for StylePredictionNetwork"));
UTexture2D* StyleTexture = StyleTransferSettings->StyleTextures[i].LoadSynchronous();
//UTexture2D* StyleTexture = LoadObject<UTexture2D>(this, TEXT("/Script/Engine.Texture2D'/StyleTransfer/T_StyleImage.T_StyleImage'"));
#if WITH_EDITOR
FTextureCompilingManager::Get().FinishCompilation({StyleTexture});
#endif
UpdateStyle(StyleTexture);
UpdateStyle(StyleTexture, StylePredictionInferenceContext);
}
//UpdateStyle(FPaths::GetPath("C:\\projects\\realtime-style-transfer\\temp\\style_params_tensor.bin"));
StyleTransferSceneViewExtension = FSceneViewExtensions::NewExtension<FStyleTransferSceneViewExtension>(ViewportClient->GetWorld(), ViewportClient, StyleTransferNetwork, StyleTransferInferenceContext.ToSharedRef());
}
StyleTransferSceneViewExtension->SetEnabled(true);
}
@ -67,10 +100,13 @@ void UStyleTransferSubsystem::StopStylizingViewport()
{
FlushRenderingCommands();
StyleTransferSceneViewExtension.Reset();
if (StylePredictionInferenceContext != INDEX_NONE)
if (StylePredictionInferenceContexts.Num())
{
StylePredictionNetwork->DestroyInferenceContext(StylePredictionInferenceContext);
StylePredictionInferenceContext = INDEX_NONE;
for (auto It = StylePredictionInferenceContexts.CreateIterator(); It; ++It)
{
StylePredictionNetwork->DestroyInferenceContext(*It);
It.RemoveCurrent();
}
}
if (StyleTransferInferenceContext && *StyleTransferInferenceContext != INDEX_NONE)
{
@ -80,20 +116,14 @@ void UStyleTransferSubsystem::StopStylizingViewport()
}
}
void UStyleTransferSubsystem::UpdateStyle(UTexture2D* StyleTexture)
void UStyleTransferSubsystem::UpdateStyle(UTexture2D* StyleTexture, int32 StylePredictionInferenceContext)
{
checkf(StyleTransferInferenceContext.IsValid() && (*StyleTransferInferenceContext) != INDEX_NONE, TEXT("Can not infer style without inference context"));
checkf(StylePredictionInferenceContext != INDEX_NONE, TEXT("Can not update style without inference context"));
FlushRenderingCommands();
ENQUEUE_RENDER_COMMAND(StylePrediction)([this, StyleTexture](FRHICommandListImmediate& RHICommandList)
ENQUEUE_RENDER_COMMAND(StylePrediction)([this, StyleTexture, StylePredictionInferenceContext](FRHICommandListImmediate& RHICommandList)
{
IRenderCaptureProvider* RenderCaptureProvider = nullptr;
const FName RenderCaptureProviderType = IRenderCaptureProvider::GetModularFeatureName();
if(IModularFeatures::Get().IsModularFeatureAvailable(RenderCaptureProviderType))
{
RenderCaptureProvider = &IModularFeatures::Get().GetModularFeature<IRenderCaptureProvider>(RenderCaptureProviderType);
RenderCaptureProvider->BeginCapture(&RHICommandList);
}
IRenderCaptureProvider* RenderCaptureProvider = ConditionalBeginRenderCapture(RHICommandList);
FRDGBuilder GraphBuilder(RHICommandList);
{
@ -120,7 +150,7 @@ void UStyleTransferSubsystem::UpdateStyle(UTexture2D* StyleTexture)
}
GraphBuilder.Execute();
if(RenderCaptureProvider)
if (RenderCaptureProvider)
{
RenderCaptureProvider->EndCapture(&RHICommandList);
}
@ -161,7 +191,7 @@ void UStyleTransferSubsystem::HandleConsoleVariableChanged(IConsoleVariable* Con
if (CVarStyleTransferEnabled->GetBool())
{
if(!(StyleTransferNetwork || StylePredictionNetwork))
if (!(StyleTransferNetwork || StylePredictionNetwork))
{
LoadNetworks();
}
@ -203,3 +233,40 @@ void UStyleTransferSubsystem::LoadNetworks()
UE_LOG(LogStyleTransfer, Error, TEXT("StylePredictionNetwork could not be loaded."));
}
}
void UStyleTransferSubsystem::InterpolateStyles(int32 StylePredictionInferenceContextA, int32 StylePredictionInferenceContextB, float Alpha)
{
checkf(StyleTransferInferenceContext.IsValid() && (*StyleTransferInferenceContext) != INDEX_NONE, TEXT("Can not transfer style without inference context"));
checkf(StylePredictionInferenceContexts.Contains(StylePredictionInferenceContextA), TEXT("Can not update style without inference context A"));
checkf(StylePredictionInferenceContexts.Contains(StylePredictionInferenceContextB), TEXT("Can not update style without inference context B"));
ENQUEUE_RENDER_COMMAND(StylePrediction)([this, StylePredictionInferenceContextA, StylePredictionInferenceContextB, Alpha](FRHICommandListImmediate& RHICommandList)
{
IRenderCaptureProvider* RenderCaptureProvider = ConditionalBeginRenderCapture(RHICommandList);
FRDGBuilder GraphBuilder(RHICommandList);
{
RDG_EVENT_SCOPE(GraphBuilder, "StylePrediction");
const FNeuralTensor& InputStyleImageTensorA = StylePredictionNetwork->GetOutputTensorForContext(StylePredictionInferenceContextA, 0);
const FNeuralTensor& InputStyleImageTensorB = StylePredictionNetwork->GetOutputTensorForContext(StylePredictionInferenceContextB, 0);
const FNeuralTensor& OutputStyleParamsTensor = StyleTransferNetwork->GetInputTensorForContext(*StyleTransferInferenceContext, StyleTransferStyleParamsInputIndex);
FStyleTransferSceneViewExtension::InterpolateTensors(GraphBuilder, OutputStyleParamsTensor, InputStyleImageTensorA, InputStyleImageTensorB, Alpha);
}
GraphBuilder.Execute();
if(RenderCaptureProvider) RenderCaptureProvider->EndCapture(&RHICommandList);
});
}
IRenderCaptureProvider* UStyleTransferSubsystem::ConditionalBeginRenderCapture(FRHICommandListImmediate& RHICommandList)
{
IRenderCaptureProvider* RenderCaptureProvider = nullptr;
if (CVarAutoCaptureStylePrediction.GetValueOnRenderThread())
{
const FName RenderCaptureProviderType = IRenderCaptureProvider::GetModularFeatureName();
if (IModularFeatures::Get().IsModularFeatureAvailable(RenderCaptureProviderType))
{
RenderCaptureProvider = &IModularFeatures::Get().GetModularFeature<IRenderCaptureProvider>(RenderCaptureProviderType);
RenderCaptureProvider->BeginCapture(&RHICommandList);
}
}
return RenderCaptureProvider;
}

View File

@ -1,4 +1,4 @@
// Copyright Epic Games, Inc. All Rights Reserved.
// Copyright Manuel Wagner All Rights Reserved.
#pragma once

View File

@ -43,6 +43,7 @@ public:
static void AddRescalingTextureCopy(FRDGBuilder& GraphBuilder, FRDGTexture& RDGSourceTexture, FScreenPassRenderTarget& DestinationRenderTarget);
static FRDGTexture* TensorToTexture(FRDGBuilder& GraphBuilder, const FRDGTextureDesc& BaseDestinationDesc, const FNeuralTensor& SourceTensor);
static void TextureToTensor(FRDGBuilder& GraphBuilder, FRDGTextureRef SourceTexture, const FNeuralTensor& DestinationTensor);
static void InterpolateTensors(FRDGBuilder& GraphBuilder, const FNeuralTensor& DestinationTensor, const FNeuralTensor& InputTensorA, const FNeuralTensor& InputTensorB, float Alpha);
private:
/** The actual Network pointer is not tracked so we need a WeakPtr too so we can check its validity on the game thread. */

View File

@ -3,6 +3,7 @@
#pragma once
#include "CoreMinimal.h"
#include "IRenderCaptureProvider.h"
#include "StyleTransferSceneViewExtension.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "UObject/Object.h"
@ -12,7 +13,7 @@
*
*/
UCLASS()
class STYLETRANSFER_API UStyleTransferSubsystem : public UGameInstanceSubsystem
class STYLETRANSFER_API UStyleTransferSubsystem : public UGameInstanceSubsystem, public FTSTickerObjectBase
{
GENERATED_BODY()
@ -22,11 +23,16 @@ public:
virtual void Deinitialize() override;
// --
// - FTSTickerObjectBase
virtual bool Tick(float DeltaTime) override final;
// --
void StartStylizingViewport(FViewportClient* ViewportClient);
void StopStylizingViewport();
void UpdateStyle(UTexture2D* StyleTexture);
void UpdateStyle(UTexture2D* StyleTexture, int32 StylePredictionInferenceContext);
void UpdateStyle(FString StyleTensorDataPath);
void InterpolateStyles(int32 StylePredictionInferenceContextA, int32 StylePredictionInferenceContextB, float Alpha);
private:
FStyleTransferSceneViewExtension::Ptr StyleTransferSceneViewExtension;
@ -37,7 +43,7 @@ private:
UPROPERTY()
TObjectPtr<UNeuralNetwork> StylePredictionNetwork;
int32 StylePredictionInferenceContext = INDEX_NONE;
TArray<int32> StylePredictionInferenceContexts;
TSharedPtr<int32, ESPMode::ThreadSafe> StyleTransferInferenceContext;
@ -46,4 +52,6 @@ private:
void HandleConsoleVariableChanged(IConsoleVariable*);
void LoadNetworks();
IRenderCaptureProvider* ConditionalBeginRenderCapture(FRHICommandListImmediate& RHICommandList);
};

View File

@ -1,4 +1,4 @@
// Copyright Epic Games, Inc. All Rights Reserved.
// Copyright Manuel Wagner All Rights Reserved.
using System.IO;
using UnrealBuildTool;

View File

@ -0,0 +1,19 @@
// Copyright Manuel Wagner All Rights Reserved.
#include "InterpolateTensorsCS.h"
const FIntVector FInterpolateTensorsCS::ThreadGroupSize{64, 1, 1};
void FInterpolateTensorsCS::ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_X"), ThreadGroupSize.X);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_Y"), ThreadGroupSize.Y);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_Z"), ThreadGroupSize.Z);
}
IMPLEMENT_GLOBAL_SHADER(FInterpolateTensorsCS,
"/Plugins/StyleTransfer/Shaders/Private/InterpolateTensors.usf",
"InterpolateTensorsCS", SF_Compute); // Path defined in StyleTransferModule.cpp

View File

@ -1,4 +1,4 @@
// Copyright Epic Games, Inc. All Rights Reserved.
// Copyright Manuel Wagner All Rights Reserved.
#include "OutputTensorToSceneColorCS.h"

View File

@ -1,4 +1,4 @@
// Copyright Epic Games, Inc. All Rights Reserved.
// Copyright Manuel Wagner All Rights Reserved.
#include "SceneColorToInputTensorCS.h"

View File

@ -0,0 +1,41 @@
// Copyright Manuel Wagner All Rights Reserved.
#pragma once
// GPU/RHI/shaders
#include "GlobalShader.h"
#include "RHI.h"
#include "ProfilingDebugging/RealtimeGPUProfiler.h"
#include "RenderGraphUtils.h"
#include "ShaderParameterUtils.h"
class STYLETRANSFERSHADERS_API FInterpolateTensorsCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FInterpolateTensorsCS);
SHADER_USE_PARAMETER_STRUCT(FInterpolateTensorsCS, FGlobalShader)
static const FIntVector ThreadGroupSize;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<float>, OutputUAV)
// Unreal sadly does not support arrays of Buffers in shader compiler
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float>, InputSrvA)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float>, InputSrvB)
SHADER_PARAMETER(float, Alpha)
SHADER_PARAMETER(uint32, TensorVolume)
END_SHADER_PARAMETER_STRUCT()
// - FShader
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) {
return GetMaxSupportedFeatureLevel(Parameters.Platform) >= ERHIFeatureLevel::SM5;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment);
// --
private:
};

View File

@ -1,4 +1,4 @@
// Copyright Epic Games, Inc. All Rights Reserved.
// Copyright Manuel Wagner All Rights Reserved.
#pragma once

View File

@ -1,4 +1,4 @@
// Copyright Epic Games, Inc. All Rights Reserved.
// Copyright Manuel Wagner All Rights Reserved.
#pragma once

View File

@ -1,25 +0,0 @@
#include "GameFeatureAction_StyleTransfer.h"
#include "StyleTransferSubsystem.h"
void UGameFeatureAction_StyleTransfer::OnGameFeatureActivating(FGameFeatureActivatingContext& Context)
{
Super::OnGameFeatureActivating(Context);
}
void UGameFeatureAction_StyleTransfer::OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context)
{
Super::OnGameFeatureDeactivating(Context);
// @todo shutdown cleanly
}
void UGameFeatureAction_StyleTransfer::AddToWorld(const FWorldContext& WorldContext, const FGameFeatureStateChangeContext& ChangeContext)
{
auto* StyleTransferSubsystem = WorldContext.OwningGameInstance->GetSubsystem<UStyleTransferSubsystem>();
UGameViewportClient* GameViewportClient = WorldContext.GameViewport;
StyleTransferSubsystem->StartStylizingViewport(GameViewportClient);
}

View File

@ -1,22 +0,0 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFeatureAction_WorldActionBase.h"
#include "UObject/Object.h"
#include "GameFeatureAction_StyleTransfer.generated.h"
/**
*
*/
UCLASS()
class LYRAGAME_API UGameFeatureAction_StyleTransfer : public UGameFeatureAction_WorldActionBase
{
GENERATED_BODY()
public:
virtual void OnGameFeatureActivating(FGameFeatureActivatingContext& Context) override;
virtual void OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context) override;
private:
virtual void AddToWorld(const FWorldContext& WorldContext, const FGameFeatureStateChangeContext& ChangeContext) override;
};