184 lines
6.6 KiB
C++
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
|
|
} |