You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Add VT tile size bias to texture level of detail settings. This allows us to set up tile size bias per platform to use smaller tile sizes on platforms with less processing power. [FYI] Mickael.Gilabert #ROBOMERGE-SOURCE: CL 13143577 via CL 13143578 via CL 13143580 via CL 13143583 #ROBOMERGE-BOT: RELEASE (Release-Engine-Staging -> Main) (v687-13115495) [CL 13143585 by jeremy moore in Main branch]
137 lines
5.4 KiB
C++
137 lines
5.4 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "VT/RuntimeVirtualTextureSceneProxy.h"
|
|
|
|
#include "Components/RuntimeVirtualTextureComponent.h"
|
|
#include "VirtualTextureSystem.h"
|
|
#include "VT/RuntimeVirtualTexture.h"
|
|
#include "VT/RuntimeVirtualTextureProducer.h"
|
|
#include "VT/VirtualTexture.h"
|
|
#include "VT/VirtualTextureBuilder.h"
|
|
|
|
int32 FRuntimeVirtualTextureSceneProxy::ProducerIdGenerator = 1;
|
|
|
|
FRuntimeVirtualTextureSceneProxy::FRuntimeVirtualTextureSceneProxy(URuntimeVirtualTextureComponent* InComponent)
|
|
: SceneIndex(0)
|
|
, ProducerId(0)
|
|
, VirtualTexture(nullptr)
|
|
, CombinedDirtyRect(0, 0, 0, 0)
|
|
{
|
|
if (InComponent->GetVirtualTexture() != nullptr && InComponent->GetVirtualTexture()->GetEnabled())
|
|
{
|
|
// We store a ProducerId here so that we will be able to find our SceneIndex from the Producer during rendering.
|
|
// We will need the SceneIndex to determine which primitives should render to this Producer.
|
|
ProducerId = ProducerIdGenerator++;
|
|
|
|
VirtualTexture = InComponent->GetVirtualTexture();
|
|
Transform = InComponent->GetVirtualTextureTransform();
|
|
const FBox Bounds = InComponent->Bounds.GetBox();
|
|
|
|
// The producer description is calculated using the transform to determine the aspect ratio
|
|
FVTProducerDescription Desc;
|
|
VirtualTexture->GetProducerDescription(Desc, Transform);
|
|
VirtualTextureSize = FIntPoint(Desc.BlockWidthInTiles * Desc.TileSize, Desc.BlockHeightInTiles * Desc.TileSize);
|
|
// We only need to dirty flush up to the producer description MaxLevel which accounts for the RemoveLowMips
|
|
MaxDirtyLevel = Desc.MaxLevel;
|
|
|
|
const ERuntimeVirtualTextureMaterialType MaterialType = VirtualTexture->GetMaterialType();
|
|
const bool bClearTextures = VirtualTexture->GetClearTextures();
|
|
|
|
// The Producer object created here will be passed into the virtual texture system which will take ownership.
|
|
IVirtualTexture* Producer = new FRuntimeVirtualTextureProducer(Desc, ProducerId, MaterialType, bClearTextures, InComponent->GetScene(), Transform, Bounds);
|
|
|
|
if (InComponent->IsStreamingLowMips())
|
|
{
|
|
UVirtualTexture2D* StreamingTexture = InComponent->GetStreamingTexture()->Texture;
|
|
// Streaming mips start from the MaxLevel before taking into account the RemoveLowMips
|
|
const int32 MaxLevel = FMath::CeilLogTwo(FMath::Max(Desc.BlockWidthInTiles, Desc.BlockHeightInTiles));
|
|
// Wrap our producer to use a streaming producer for low mips
|
|
int32 StreamingTransitionLevel;
|
|
Producer = RuntimeVirtualTexture::CreateStreamingTextureProducer(Producer, Desc, StreamingTexture, MaxLevel, StreamingTransitionLevel);
|
|
// Any dirty flushes don't need to flush the streaming mips (they only change with a build step).
|
|
MaxDirtyLevel = FMath::Clamp(StreamingTransitionLevel, 0, MaxDirtyLevel);
|
|
}
|
|
|
|
// The Initialize() call will allocate the virtual texture by spawning work on the render thread.
|
|
VirtualTexture->Initialize(Producer, Transform, Bounds);
|
|
}
|
|
}
|
|
|
|
FRuntimeVirtualTextureSceneProxy::~FRuntimeVirtualTextureSceneProxy()
|
|
{
|
|
checkSlow(IsInRenderingThread());
|
|
}
|
|
|
|
void FRuntimeVirtualTextureSceneProxy::Release()
|
|
{
|
|
if (VirtualTexture != nullptr)
|
|
{
|
|
VirtualTexture->Release();
|
|
VirtualTexture = nullptr;
|
|
}
|
|
}
|
|
|
|
void FRuntimeVirtualTextureSceneProxy::Dirty(FBoxSphereBounds const& Bounds)
|
|
{
|
|
// Transform world bounds into Virtual Texture UV space
|
|
const FVector O = Transform.GetTranslation();
|
|
const FVector U = Transform.GetUnitAxis(EAxis::X) * 1.f / Transform.GetScale3D().X;
|
|
const FVector V = Transform.GetUnitAxis(EAxis::Y) * 1.f / Transform.GetScale3D().Y;
|
|
const FVector P = Bounds.GetSphere().Center - O;
|
|
const FVector2D UVCenter = FVector2D(FVector::DotProduct(P, U), FVector::DotProduct(P, V));
|
|
const float Scale = FMath::Max(1.f / Transform.GetScale3D().X, 1.f / Transform.GetScale3D().Y);
|
|
const float UVRadius = Bounds.GetSphere().W * Scale;
|
|
const FVector2D UVExtent(UVRadius, UVRadius);
|
|
const FBox2D UVRect = FBox2D(UVCenter - UVExtent, UVCenter + UVExtent);
|
|
|
|
// Convert to Texel coordinate space
|
|
const FIntRect TextureRect(0, 0, VirtualTextureSize.X, VirtualTextureSize.Y);
|
|
FIntRect TexelRect(
|
|
FMath::FloorToInt(UVRect.Min.X * VirtualTextureSize.X),
|
|
FMath::FloorToInt(UVRect.Min.Y * VirtualTextureSize.Y),
|
|
FMath::CeilToInt(UVRect.Max.X * VirtualTextureSize.X),
|
|
FMath::CeilToInt(UVRect.Max.Y * VirtualTextureSize.Y));
|
|
TexelRect.Clip(TextureRect);
|
|
|
|
// Only add rect if it has some area
|
|
if (TexelRect.Min != TexelRect.Max)
|
|
{
|
|
const bool bFirst = DirtyRects.Add(TexelRect) == 0;
|
|
if (bFirst)
|
|
{
|
|
CombinedDirtyRect = TexelRect;
|
|
}
|
|
else
|
|
{
|
|
CombinedDirtyRect.Union(TexelRect);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FRuntimeVirtualTextureSceneProxy::FlushDirtyPages()
|
|
{
|
|
// If Producer handle is not initialized yet it's safe to do nothing because we won't have rendered anything to the VT that needs flushing.
|
|
if (ProducerHandle.PackedValue != 0)
|
|
{
|
|
//todo[vt]:
|
|
// Profile to work out best heuristic for when we should use the CombinedDirtyRect
|
|
// Also consider using some other structure to represent dirty area such as a course 2D bitfield
|
|
const bool bCombinedFlush = (DirtyRects.Num() > 2 || CombinedDirtyRect == FIntRect(0, 0, VirtualTextureSize.X, VirtualTextureSize.Y));
|
|
|
|
if (bCombinedFlush)
|
|
{
|
|
FVirtualTextureSystem::Get().FlushCache(ProducerHandle, CombinedDirtyRect, MaxDirtyLevel);
|
|
}
|
|
else
|
|
{
|
|
for (FIntRect Rect : DirtyRects)
|
|
{
|
|
FVirtualTextureSystem::Get().FlushCache(ProducerHandle, Rect, MaxDirtyLevel);
|
|
}
|
|
}
|
|
}
|
|
|
|
DirtyRects.Reset();
|
|
CombinedDirtyRect = FIntRect(0, 0, 0, 0);
|
|
}
|