You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#ROBOMERGE-SOURCE: CL 8030248 via CL 8041686 #ROBOMERGE-BOT: (v400-8057353) [CL 8062582 by jeremy moore in Main branch]
120 lines
4.5 KiB
C++
120 lines
4.5 KiB
C++
// Copyright 1998-2019 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"
|
|
|
|
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())
|
|
{
|
|
VirtualTexture = InComponent->GetVirtualTexture();
|
|
|
|
// 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++;
|
|
|
|
const ERuntimeVirtualTextureMaterialType MaterialType = VirtualTexture->GetMaterialType();
|
|
|
|
// Transform is based on bottom left of the URuntimeVirtualTextureComponent unit box (which is centered on the origin)
|
|
Transform = FTransform(FVector(-0.5f, -0.5f, 0.f)) * InComponent->GetComponentTransform();
|
|
|
|
// The producer description is calculated using the transform to determine the aspect ratio
|
|
FVTProducerDescription Desc;
|
|
VirtualTexture->GetProducerDescription(Desc, Transform);
|
|
VirtualTextureSize = FIntPoint(Desc.WidthInBlocks * Desc.BlockWidthInTiles * Desc.TileSize, Desc.HeightInBlocks * Desc.BlockHeightInTiles * Desc.TileSize);
|
|
|
|
// The Producer object created here will be passed into the virtual texture system which will take ownership.
|
|
// The Initialize() call will allocate the virtual texture by spawning work on the render thread.
|
|
FRuntimeVirtualTextureProducer* Producer = new FRuntimeVirtualTextureProducer(Desc, ProducerId, MaterialType, InComponent->GetScene(), Transform);
|
|
VirtualTexture->Initialize(Producer, Transform);
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
else
|
|
{
|
|
for (FIntRect Rect : DirtyRects)
|
|
{
|
|
FVirtualTextureSystem::Get().FlushCache(ProducerHandle, Rect);
|
|
}
|
|
}
|
|
}
|
|
|
|
DirtyRects.Reset();
|
|
CombinedDirtyRect = FIntRect(0, 0, 0, 0);
|
|
}
|