Files
FunnyGirl/Plugins/VRM4U/Source/VRM4URender/Private/VrmSceneCaptureComponent.cpp
T
2026-05-19 13:42:41 +07:00

168 lines
5.3 KiB
C++

// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
#include "VrmSceneCaptureComponent.h"
#include "SceneViewExtension.h"
#include "Runtime/Engine/Public/SceneView.h"
#include "Engine/TextureRenderTarget2D.h"
#include "ScreenPass.h"
#include "Kismet/GameplayStatics.h"
#include "VRM4URender.h"
#include "VrmBPFunctionLibrary.h"
#include "Misc/EngineVersionComparison.h"
#if UE_VERSION_OLDER_THAN(5,3,0)
#include "PostProcess/PostProcessing.h"
#include "PostProcess/PostProcessMaterial.h"
#else
#include "PostProcess/PostProcessMaterialInputs.h"
#endif
class FVrmSceneCaptureSceneViewExtension : public ISceneViewExtension, public TSharedFromThis<FVrmSceneCaptureSceneViewExtension, ESPMode::ThreadSafe>
{
public:
FVrmSceneCaptureSceneViewExtension(const FAutoRegister& AutoRegister)
{ }
virtual ~FVrmSceneCaptureSceneViewExtension() = default;
virtual void BeginRenderViewFamily(FSceneViewFamily& InViewFamily) override {};
virtual void SetupViewFamily(FSceneViewFamily& InViewFamily) override {};
virtual void SetupView(FSceneViewFamily& InViewFamily, FSceneView& InView) override
{
}
virtual void PostRenderBasePassDeferred_RenderThread(FRDGBuilder& GraphBuilder, FSceneView& InView, const FRenderTargetBindingSlots& RenderTargets, TRDGUniformBufferRef<FSceneTextureUniformParameters> SceneTextures)
{
if (InView.bIsSceneCapture == false) return;
FRDGTextureRef DstRDGTex = nullptr;
FRDGTextureRef SrcRDGTex = nullptr;
if (CaptureComponentWeak.IsValid() == false) return;
if (CaptureComponentWeak->RenderTargetA == nullptr) return;
if (CaptureComponentWeak->RenderTargetB == nullptr) return;
//DstRDGTex = RegisterExternalTexture(GraphBuilder, CaptureComponentWeak->RenderTargetA->GetRenderTargetResource()->GetTexture2DRHI(), TEXT("VRM4U_CopyDst"));
for (auto &a : RenderTargets.Output) {
if (a.GetTexture() == nullptr) continue;
FString s = a.GetTexture()->Name;
if (s.Contains("BufferC")) {
SrcRDGTex = a.GetTexture();
}
}
if (SrcRDGTex) {
FVRM4URenderModule::AddCopyPass(GraphBuilder, FIntPoint(InView.UnscaledViewRect.Width(), InView.UnscaledViewRect.Height()), SrcRDGTex, CaptureComponentWeak->RenderTargetA);
}
SrcRDGTex = nullptr;
//DstRDGTex = RegisterExternalTexture(GraphBuilder, CaptureComponentWeak->RenderTargetA->GetRenderTargetResource()->GetTexture2DRHI(), TEXT("VRM4U_CopyDst"));
for (auto& a : RenderTargets.Output) {
if (a.GetTexture() == nullptr) continue;
FString s = a.GetTexture()->Name;
if (s.Contains("BufferA")) {
SrcRDGTex = a.GetTexture();
}
}
if (SrcRDGTex) {
FVRM4URenderModule::AddCopyPass(GraphBuilder, FIntPoint(InView.UnscaledViewRect.Width(), InView.UnscaledViewRect.Height()), SrcRDGTex, CaptureComponentWeak->RenderTargetB);
}
}
virtual void SubscribeToPostProcessingPass(EPostProcessingPass PassId, const FSceneView& View, FAfterPassCallbackDelegateArray& InOutPassCallbacks, bool bIsPassEnabled)
{
if (PassId == EPostProcessingPass::Tonemap)
{
//InOutPassCallbacks.Add(FAfterPassCallbackDelegate::CreateRaw(this, &FVrmSceneCaptureSceneViewExtension::PostProcessPassAfterTonemap_RenderThread));
}
}
FScreenPassTexture PostProcessPassAfterTonemap_RenderThread(FRDGBuilder& GraphBuilder, const FSceneView& InView, const FPostProcessMaterialInputs& InOutInputs)
{
#if UE_VERSION_OLDER_THAN(5,4,0)
FScreenPassTexture SceneTexture = const_cast<FScreenPassTexture&>(InOutInputs.Textures[(uint32)EPostProcessMaterialInput::SceneColor]);
return SceneTexture;
#else
return InOutInputs.ReturnUntouchedSceneColorForPostProcessing(GraphBuilder);
#endif
}
public:
TWeakObjectPtr<UVrmSceneCaptureComponent2D> CaptureComponentWeak;
};
UVrmSceneCaptureComponent2D::UVrmSceneCaptureComponent2D(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void UVrmSceneCaptureComponent2D::OnRegister()
{
Super::OnRegister();
#if WITH_EDITORONLY_DATA
if (ProxyMeshComponent)
{
ProxyMeshComponent->DestroyComponent();
ProxyMeshComponent = nullptr;
}
#endif
if (!SceneViewExtension.IsValid())
{
SceneViewExtension = FSceneViewExtensions::NewExtension<FVrmSceneCaptureSceneViewExtension>();
SceneViewExtension->CaptureComponentWeak = this;
}
}
void UVrmSceneCaptureComponent2D::OnUnregister()
{
Super::OnUnregister();
if (SceneViewExtension.IsValid())
{
SceneViewExtensions.Remove(SceneViewExtension);
SceneViewExtension.Reset();
}
//CineCameraComponent = nullptr;
}
void UVrmSceneCaptureComponent2D::OnAttachmentChanged()
{
}
void UVrmSceneCaptureComponent2D::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
FTransform transform;
float fovDegree;
UVrmBPFunctionLibrary::VRMGetCameraTransform(this, 0, false, transform, fovDegree);
float fov = fovDegree;
{
bool b1, b2, b3;
UVrmBPFunctionLibrary::VRMGetPlayMode(b1, b2, b3);
if (b1 == true && b2 == false) {
auto* c = UGameplayStatics::GetPlayerCameraManager(this, 0);
float ar_current = (float)RenderTargetA->SizeX / RenderTargetA->SizeY;
float HalfX_game = FMath::DegreesToRadians(fovDegree / 2);
float HalfY = FMath::Atan(FMath::Tan(HalfX_game) / c->ViewTarget.POV.AspectRatio);
float HalfX_new = FMath::Atan(ar_current * FMath::Tan(HalfY));
fov = 2.f * FMath::RadiansToDegrees(HalfX_new);
}
}
this->FOVAngle = fov;
}