Files
UnrealEngine/Engine/Source/Runtime/Renderer/Private/VisualizeTexturePresent.cpp
2025-05-18 13:04:45 +08:00

184 lines
6.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "VisualizeTexturePresent.h"
#include "VisualizeTexture.h"
#include "ScreenPass.h"
#include "UnrealEngine.h"
#include "Engine/Canvas.h"
#include "Engine/Engine.h"
#include "RenderTargetPool.h"
#include "SceneRendering.h"
void FVisualizeTexturePresent::PresentContent(FRDGBuilder& GraphBuilder, const FViewInfo& View, FScreenPassRenderTarget Output)
{
check(Output.IsValid());
#if SUPPORTS_VISUALIZE_TEXTURE
FVisualizeTexture::FCaptured& Captured = GVisualizeTexture.Captured;
if (!Captured.PooledRenderTarget && !Captured.Texture)
{
// visualize feature is deactivated
return;
}
// Reset bitmap flags now that we know we've saved out the bitmap we're seeing on screen.
{
using EFlags = FVisualizeTexture::EFlags;
EnumRemoveFlags(GVisualizeTexture.Config.Flags, EFlags::SaveBitmap | EFlags::SaveBitmapAsStencil);
}
const FPooledRenderTargetDesc& Desc = Captured.Desc;
FRDGTextureRef VisualizeTexture2D = Captured.Texture;
// The RDG version may be stale. The IPooledRenderTarget overrides it.
if (Captured.PooledRenderTarget)
{
Captured.Texture = nullptr;
VisualizeTexture2D = GraphBuilder.RegisterExternalTexture(Captured.PooledRenderTarget, Desc.DebugName);
}
RDG_EVENT_SCOPE(GraphBuilder, "VisualizeTexture");
using EInputUVMapping = FVisualizeTexture::EInputUVMapping;
const EInputUVMapping InputUVMapping = VisualizeTexture2D->Desc.IsTexture2D() ? GVisualizeTexture.Config.InputUVMapping : EInputUVMapping::Whole;
using EInputValueMapping = FVisualizeTexture::EInputValueMapping;
const EInputValueMapping InputValueMapping = Captured.InputValueMapping;
{
FScreenPassTexture CopyInput(VisualizeTexture2D);
FScreenPassRenderTarget CopyOutput = Output;
switch (InputUVMapping)
{
case EInputUVMapping::LeftTop:
CopyOutput.ViewRect = View.UnconstrainedViewRect;
break;
case EInputUVMapping::PixelPerfectCenter:
{
FIntPoint SrcSize = CopyInput.ViewRect.Size();
FIntPoint Center = View.UnconstrainedViewRect.Size() / 2;
FIntPoint HalfMin = SrcSize / 2;
FIntPoint HalfMax = SrcSize - HalfMin;
CopyOutput.ViewRect = FIntRect(Center - HalfMin, Center + HalfMax);
}
break;
case EInputUVMapping::PictureInPicture:
{
const FIntPoint CopyInputExtent = CopyInput.Texture->Desc.Extent;
const float CopyInputAspectRatio = float(CopyInputExtent.X) / float(CopyInputExtent.Y);
int32 TargetedHeight = 0.3f * View.UnconstrainedViewRect.Height();
int32 TargetedWidth = CopyInputAspectRatio * TargetedHeight;
int32 OffsetFromBorder = 100;
CopyOutput.ViewRect.Min.X = View.UnconstrainedViewRect.Min.X + OffsetFromBorder;
CopyOutput.ViewRect.Max.X = CopyOutput.ViewRect.Min.X + TargetedWidth;
CopyOutput.ViewRect.Max.Y = View.UnconstrainedViewRect.Max.Y - OffsetFromBorder;
CopyOutput.ViewRect.Min.Y = CopyOutput.ViewRect.Max.Y - TargetedHeight;
}
break;
}
AddDrawTexturePass(GraphBuilder, View, CopyInput, CopyOutput);
}
Output.LoadAction = ERenderTargetLoadAction::ELoad;
const FIntPoint ViewportSizeXY = Captured.OutputExtent;
FString ViewDescription = GVisualizeTexture.ViewDescriptionMap[Captured.ViewUniqueId];
AddDrawCanvasPass(GraphBuilder, {}, View, Output,
[VisualizeTexture2D, ViewportSizeXY, Desc, &View, InputUVMapping, InputValueMapping, ViewUniqueId = Captured.ViewUniqueId, ViewDescription, ViewRects = CopyTemp(Captured.ViewRects)](FCanvas& Canvas)
{
float X = 100 + View.UnconstrainedViewRect.Min.X;
float Y = 160 + View.UnconstrainedViewRect.Min.Y;
float YStep = 14;
{
const uint32 VersionCount = GVisualizeTexture.GetVersionCount(VisualizeTexture2D->Name);
FString ExtendedName;
if (VersionCount > 0)
{
const uint32 Version = FMath::Min(GVisualizeTexture.Requested.Version.Get(VersionCount), VersionCount - 1);
// was reused this frame
ExtendedName = FString::Printf(TEXT("%s@%d @0..%d"), VisualizeTexture2D->Name, Version, VersionCount - 1);
}
else
{
// was not reused this frame but can be referenced
ExtendedName = FString::Printf(TEXT("%s"), VisualizeTexture2D->Name);
}
const FVisualizeTexture::FConfig& Config = GVisualizeTexture.Config;
FString Channels = TEXT("RGB");
switch (Config.SingleChannel)
{
case 0: Channels = TEXT("R"); break;
case 1: Channels = TEXT("G"); break;
case 2: Channels = TEXT("B"); break;
case 3: Channels = TEXT("A"); break;
}
float Multiplier = (Config.SingleChannel == -1) ? Config.RGBMul : Config.SingleChannelMul;
FString Line = FString::Printf(TEXT("VisualizeTexture: \"%s\" %s*%g UV%d"),
*ExtendedName,
*Channels,
Multiplier,
InputUVMapping);
Canvas.DrawShadowedString(X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1));
}
{
FString Line = FString::Printf(TEXT("View ID %d: \"%s\""), ViewUniqueId, *ViewDescription);
Canvas.DrawShadowedString(X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1));
}
{
FString Line = FString::Printf(TEXT(" TextureInfo: %s"), *(Desc.GenerateInfoString()));
Canvas.DrawShadowedString(X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1));
}
{
FString Line = FString::Printf(TEXT(" ViewportSize:(%d,%d)"), ViewportSizeXY.X, ViewportSizeXY.Y);
Canvas.DrawShadowedString(X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1));
}
const FSceneViewFamily& ViewFamily = *View.Family;
for (int32 ViewId = 0; ViewId < ViewRects.Num(); ++ViewId)
{
const FIntRect& ViewRect = ViewRects[ViewId];
FString Line = FString::Printf(TEXT(" View #%d: (%d,%d)-(%d,%d)"), ViewId + 1, ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Max.X, ViewRect.Max.Y);
Canvas.DrawShadowedString(X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1));
}
X += 40;
if (EnumHasAnyFlags(Desc.Flags, TexCreate_CPUReadback))
{
Canvas.DrawShadowedString(X, Y += YStep, TEXT("Content cannot be visualized on the GPU (TexCreate_CPUReadback)"), GetStatsFont(), FLinearColor(1, 1, 0));
}
else
{
Canvas.DrawShadowedString(X, Y += YStep, TEXT("Blinking Red: <0"), GetStatsFont(), FLinearColor(1, 0, 0));
Canvas.DrawShadowedString(X, Y += YStep, TEXT("Blinking Blue: NAN or Inf"), GetStatsFont(), FLinearColor(0, 0, 1));
if (InputValueMapping == EInputValueMapping::Shadow)
{
Canvas.DrawShadowedString(X, Y += YStep, TEXT("Color Key: Linear with white near and teal distant"), GetStatsFont(), FLinearColor(54.f / 255.f, 117.f / 255.f, 136.f / 255.f));
}
else if (InputValueMapping == EInputValueMapping::Depth)
{
Canvas.DrawShadowedString(X, Y += YStep, TEXT("Color Key: Nonlinear with white distant"), GetStatsFont(), FLinearColor(0.5, 0, 0));
}
}
});
#endif
}