You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb jack.porter #ROBOMERGE-OWNER: dmitriy.dyomin #ROBOMERGE-AUTHOR: dmitriy.dyomin #ROBOMERGE-SOURCE: CL 19528072 via CL 19528235 via CL 19528695 via CL 19528703 #ROBOMERGE-BOT: UE5 (Release-Engine-Staging -> Main) (v937-19513599) [CL 19532768 by dmitriy dyomin in ue5-main branch]
520 lines
19 KiB
C++
520 lines
19 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
LandscapeRenderMobile.cpp: Landscape Rendering without using vertex texture fetch
|
|
=============================================================================*/
|
|
|
|
#include "LandscapeRenderMobile.h"
|
|
#include "ShaderParameterUtils.h"
|
|
#include "Serialization/BufferArchive.h"
|
|
#include "Serialization/MemoryReader.h"
|
|
#include "PrimitiveSceneInfo.h"
|
|
#include "LandscapeLayerInfoObject.h"
|
|
#include "HAL/LowLevelMemTracker.h"
|
|
#include "MeshMaterialShader.h"
|
|
|
|
// Debug CVar for disabling the loading of landscape hole meshes
|
|
static TAutoConsoleVariable<int32> CVarMobileLandscapeHoleMesh(
|
|
TEXT("r.Mobile.LandscapeHoleMesh"),
|
|
1,
|
|
TEXT("Set to 0 to skip loading of landscape hole meshes on mobile."),
|
|
ECVF_Default);
|
|
|
|
static TAutoConsoleVariable<int32> CVarUseMobileLandscapeMesh(
|
|
TEXT("r.Mobile.LandscapeMesh"),
|
|
1,
|
|
TEXT("Whether to use baked landscape mesh for a mobile"),
|
|
ECVF_ReadOnly);
|
|
|
|
bool FLandscapeVertexFactoryMobile::ShouldCompilePermutation(const FVertexFactoryShaderPermutationParameters& Parameters)
|
|
{
|
|
return UseMobileLandscapeMesh(Parameters.Platform) &&
|
|
(Parameters.MaterialParameters.bIsUsedWithLandscape || Parameters.MaterialParameters.bIsSpecialEngineMaterial);
|
|
}
|
|
|
|
void FLandscapeVertexFactoryMobile::InitRHI()
|
|
{
|
|
// list of declaration items
|
|
FVertexDeclarationElementList Elements;
|
|
|
|
// position decls
|
|
Elements.Add(AccessStreamComponent(MobileData.PositionComponent,0));
|
|
|
|
if (MobileData.LODHeightsComponent.Num())
|
|
{
|
|
const int32 BaseAttribute = 1;
|
|
for(int32 Index = 0;Index < MobileData.LODHeightsComponent.Num();Index++)
|
|
{
|
|
Elements.Add(AccessStreamComponent(MobileData.LODHeightsComponent[Index], BaseAttribute + Index));
|
|
}
|
|
}
|
|
|
|
// create the actual device decls
|
|
InitDeclaration(Elements);
|
|
}
|
|
|
|
/** Shader parameters for use with FLandscapeVertexFactory */
|
|
class FLandscapeVertexFactoryMobileVertexShaderParameters : public FVertexFactoryShaderParameters
|
|
{
|
|
DECLARE_TYPE_LAYOUT(FLandscapeVertexFactoryMobileVertexShaderParameters, NonVirtual);
|
|
public:
|
|
/**
|
|
* Bind shader constants by name
|
|
* @param ParameterMap - mapping of named shader constants to indices
|
|
*/
|
|
void Bind(const FShaderParameterMap& ParameterMap)
|
|
{
|
|
TexCoordOffsetParameter.Bind(ParameterMap,TEXT("TexCoordOffset"));
|
|
}
|
|
|
|
void GetElementShaderBindings(
|
|
const class FSceneInterface* Scene,
|
|
const FSceneView* InView,
|
|
const class FMeshMaterialShader* Shader,
|
|
const EVertexInputStreamType InputStreamType,
|
|
ERHIFeatureLevel::Type FeatureLevel,
|
|
const FVertexFactory* VertexFactory,
|
|
const FMeshBatchElement& BatchElement,
|
|
class FMeshDrawSingleShaderBindings& ShaderBindings,
|
|
FVertexInputStreamArray& VertexStreams
|
|
) const
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_LandscapeVFDrawTimeVS);
|
|
|
|
const FLandscapeBatchElementParams* BatchElementParams = (const FLandscapeBatchElementParams*)BatchElement.UserData;
|
|
check(BatchElementParams);
|
|
|
|
const FLandscapeComponentSceneProxyMobile* SceneProxy = (const FLandscapeComponentSceneProxyMobile*)BatchElementParams->SceneProxy;
|
|
ShaderBindings.Add(Shader->GetUniformBufferParameter<FLandscapeUniformShaderParameters>(),*BatchElementParams->LandscapeUniformShaderParametersResource);
|
|
ShaderBindings.Add(Shader->GetUniformBufferParameter<FLandscapeSectionLODUniformParameters>(), BatchElementParams->LandscapeSectionLODUniformParameters);
|
|
|
|
if (TexCoordOffsetParameter.IsBound())
|
|
{
|
|
FVector CameraLocalPos3D = SceneProxy->WorldToLocal.TransformPosition(InView->ViewMatrices.GetViewOrigin());
|
|
|
|
FVector2D TexCoordOffset(
|
|
CameraLocalPos3D.X + SceneProxy->SectionBase.X,
|
|
CameraLocalPos3D.Y + SceneProxy->SectionBase.Y
|
|
);
|
|
ShaderBindings.Add(TexCoordOffsetParameter, FVector2f(TexCoordOffset));
|
|
}
|
|
}
|
|
|
|
protected:
|
|
LAYOUT_FIELD(FShaderParameter, TexCoordOffsetParameter);
|
|
};
|
|
|
|
IMPLEMENT_TYPE_LAYOUT(FLandscapeVertexFactoryMobileVertexShaderParameters);
|
|
|
|
/** Shader parameters for use with FLandscapeVertexFactory */
|
|
class FLandscapeVertexFactoryMobilePixelShaderParameters : public FLandscapeVertexFactoryPixelShaderParameters
|
|
{
|
|
DECLARE_TYPE_LAYOUT(FLandscapeVertexFactoryMobilePixelShaderParameters, NonVirtual);
|
|
public:
|
|
/**
|
|
* Bind shader constants by name
|
|
* @param ParameterMap - mapping of named shader constants to indices
|
|
*/
|
|
void Bind(const FShaderParameterMap& ParameterMap)
|
|
{
|
|
FLandscapeVertexFactoryPixelShaderParameters::Bind(ParameterMap);
|
|
}
|
|
|
|
void GetElementShaderBindings(
|
|
const class FSceneInterface* Scene,
|
|
const FSceneView* InView,
|
|
const class FMeshMaterialShader* Shader,
|
|
const EVertexInputStreamType InputStreamType,
|
|
ERHIFeatureLevel::Type FeatureLevel,
|
|
const FVertexFactory* VertexFactory,
|
|
const FMeshBatchElement& BatchElement,
|
|
class FMeshDrawSingleShaderBindings& ShaderBindings,
|
|
FVertexInputStreamArray& VertexStreams
|
|
) const
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_LandscapeVFDrawTimePS);
|
|
|
|
FLandscapeVertexFactoryPixelShaderParameters::GetElementShaderBindings(Scene, InView, Shader, InputStreamType, FeatureLevel, VertexFactory, BatchElement, ShaderBindings, VertexStreams);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_TYPE_LAYOUT(FLandscapeVertexFactoryMobilePixelShaderParameters);
|
|
|
|
/**
|
|
* Shader parameters for use with FLandscapeFixedGridVertexFactory
|
|
* Simple grid rendering (without dynamic lod blend) needs a simpler fixed setup.
|
|
*/
|
|
class FLandscapeFixedGridVertexFactoryMobileVertexShaderParameters : public FLandscapeVertexFactoryMobileVertexShaderParameters
|
|
{
|
|
DECLARE_TYPE_LAYOUT(FLandscapeFixedGridVertexFactoryMobileVertexShaderParameters, NonVirtual);
|
|
public:
|
|
void GetElementShaderBindings(
|
|
const class FSceneInterface* Scene,
|
|
const FSceneView* InView,
|
|
const class FMeshMaterialShader* Shader,
|
|
const EVertexInputStreamType InputStreamType,
|
|
ERHIFeatureLevel::Type FeatureLevel,
|
|
const FVertexFactory* VertexFactory,
|
|
const FMeshBatchElement& BatchElement,
|
|
class FMeshDrawSingleShaderBindings& ShaderBindings,
|
|
FVertexInputStreamArray& VertexStreams
|
|
) const
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_LandscapeVFDrawTimeVS);
|
|
|
|
const FLandscapeBatchElementParams* BatchElementParams = (const FLandscapeBatchElementParams*)BatchElement.UserData;
|
|
check(BatchElementParams);
|
|
ShaderBindings.Add(Shader->GetUniformBufferParameter<FLandscapeUniformShaderParameters>(), *BatchElementParams->LandscapeUniformShaderParametersResource);
|
|
ShaderBindings.Add(Shader->GetUniformBufferParameter<FLandscapeFixedGridUniformShaderParameters>(), (*BatchElementParams->FixedGridUniformShaderParameters)[BatchElementParams->CurrentLOD]);
|
|
|
|
if (TexCoordOffsetParameter.IsBound())
|
|
{
|
|
ShaderBindings.Add(TexCoordOffsetParameter, FVector4f(ForceInitToZero));
|
|
}
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_TYPE_LAYOUT(FLandscapeFixedGridVertexFactoryMobileVertexShaderParameters);
|
|
|
|
IMPLEMENT_VERTEX_FACTORY_PARAMETER_TYPE(FLandscapeVertexFactoryMobile, SF_Vertex, FLandscapeVertexFactoryMobileVertexShaderParameters);
|
|
IMPLEMENT_VERTEX_FACTORY_PARAMETER_TYPE(FLandscapeVertexFactoryMobile, SF_Pixel, FLandscapeVertexFactoryMobilePixelShaderParameters);
|
|
|
|
IMPLEMENT_VERTEX_FACTORY_PARAMETER_TYPE(FLandscapeFixedGridVertexFactoryMobile, SF_Vertex, FLandscapeFixedGridVertexFactoryMobileVertexShaderParameters);
|
|
IMPLEMENT_VERTEX_FACTORY_PARAMETER_TYPE(FLandscapeFixedGridVertexFactoryMobile, SF_Pixel, FLandscapeVertexFactoryMobilePixelShaderParameters);
|
|
|
|
IMPLEMENT_VERTEX_FACTORY_TYPE(FLandscapeVertexFactoryMobile, "/Engine/Private/LandscapeVertexFactory.ush",
|
|
EVertexFactoryFlags::UsedWithMaterials
|
|
| EVertexFactoryFlags::SupportsStaticLighting
|
|
| EVertexFactoryFlags::SupportsDynamicLighting
|
|
);
|
|
IMPLEMENT_VERTEX_FACTORY_TYPE(FLandscapeFixedGridVertexFactoryMobile, "/Engine/Private/LandscapeVertexFactory.ush",
|
|
EVertexFactoryFlags::UsedWithMaterials
|
|
| EVertexFactoryFlags::SupportsStaticLighting
|
|
| EVertexFactoryFlags::SupportsDynamicLighting
|
|
| EVertexFactoryFlags::SupportsCachingMeshDrawCommands
|
|
);
|
|
|
|
void FLandscapeFixedGridVertexFactoryMobile::ModifyCompilationEnvironment(const FVertexFactoryShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FLandscapeVertexFactoryMobile::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("FIXED_GRID"), TEXT("1"));
|
|
}
|
|
|
|
bool FLandscapeFixedGridVertexFactoryMobile::ShouldCompilePermutation(const FVertexFactoryShaderPermutationParameters& Parameters)
|
|
{
|
|
return UseMobileLandscapeMesh(Parameters.Platform) &&
|
|
(Parameters.MaterialParameters.bIsUsedWithLandscape || Parameters.MaterialParameters.bIsSpecialEngineMaterial);
|
|
}
|
|
|
|
void FLandscapeVertexBufferMobile::UpdateMemoryStat(int32 Delta)
|
|
{
|
|
INC_DWORD_STAT_BY(STAT_LandscapeVertexMem, Delta);
|
|
}
|
|
|
|
/**
|
|
* Initialize the RHI for this rendering resource
|
|
*/
|
|
void FLandscapeVertexBufferMobile::InitRHI()
|
|
{
|
|
// create a static vertex buffer
|
|
FRHIResourceCreateInfo CreateInfo(TEXT("FLandscapeVertexBufferMobile"));
|
|
VertexBufferRHI = RHICreateBuffer(VertexData.Num(), BUF_Static | BUF_VertexBuffer, 0, ERHIAccess::VertexOrIndexBuffer, CreateInfo);
|
|
|
|
// Copy stored platform data and free CPU copy
|
|
void* VertexDataPtr = RHILockBuffer(VertexBufferRHI, 0, VertexData.Num(), RLM_WriteOnly);
|
|
FMemory::Memcpy(VertexDataPtr, VertexData.GetData(), VertexData.Num());
|
|
VertexData.Empty();
|
|
|
|
RHIUnlockBuffer(VertexBufferRHI);
|
|
}
|
|
|
|
struct FLandscapeMobileHoleData
|
|
{
|
|
FRawStaticIndexBuffer16or32Interface* IndexBuffer = nullptr;
|
|
int32 NumHoleLods;
|
|
int32 IndexBufferSize;
|
|
int32 MinHoleIndex;
|
|
int32 MaxHoleIndex;
|
|
|
|
~FLandscapeMobileHoleData()
|
|
{
|
|
if (IndexBuffer != nullptr)
|
|
{
|
|
DEC_DWORD_STAT_BY(STAT_LandscapeHoleMem, IndexBuffer->GetResourceDataSize());
|
|
IndexBuffer->ReleaseResource();
|
|
delete IndexBuffer;
|
|
}
|
|
}
|
|
};
|
|
|
|
template <typename INDEX_TYPE>
|
|
void SerializeLandscapeMobileHoleData(FMemoryArchive& Ar, FLandscapeMobileHoleData& HoleData)
|
|
{
|
|
Ar << HoleData.MinHoleIndex;
|
|
Ar << HoleData.MaxHoleIndex;
|
|
|
|
TArray<INDEX_TYPE> IndexData;
|
|
Ar << HoleData.IndexBufferSize;
|
|
IndexData.SetNumUninitialized(HoleData.IndexBufferSize);
|
|
Ar.Serialize(IndexData.GetData(), HoleData.IndexBufferSize * sizeof(INDEX_TYPE));
|
|
|
|
const bool bLoadHoleMeshData = HoleData.IndexBufferSize > 0 && CVarMobileLandscapeHoleMesh.GetValueOnGameThread();
|
|
if (bLoadHoleMeshData)
|
|
{
|
|
FRawStaticIndexBuffer16or32<INDEX_TYPE>* IndexBuffer = new FRawStaticIndexBuffer16or32<INDEX_TYPE>(false);
|
|
IndexBuffer->AssignNewBuffer(IndexData);
|
|
HoleData.IndexBuffer = IndexBuffer;
|
|
BeginInitResource(HoleData.IndexBuffer);
|
|
INC_DWORD_STAT_BY(STAT_LandscapeHoleMem, HoleData.IndexBuffer->GetResourceDataSize());
|
|
}
|
|
}
|
|
|
|
FLandscapeMobileRenderData::FLandscapeMobileRenderData(const TArray<uint8>& InPlatformData, uint8 InCurFirstLODIdx)
|
|
: CurrentFirstLODIdx(InCurFirstLODIdx)
|
|
{
|
|
FMemoryReader MemAr(InPlatformData);
|
|
|
|
int32 NumHoleLods = 0;
|
|
MemAr << NumHoleLods;
|
|
if (NumHoleLods > 0)
|
|
{
|
|
HoleData = new FLandscapeMobileHoleData;
|
|
HoleData->NumHoleLods = NumHoleLods;
|
|
|
|
bool b16BitIndices = false;
|
|
MemAr << b16BitIndices;
|
|
if (b16BitIndices)
|
|
{
|
|
SerializeLandscapeMobileHoleData<uint16>(MemAr, *HoleData);
|
|
}
|
|
else
|
|
{
|
|
SerializeLandscapeMobileHoleData<uint32>(MemAr, *HoleData);
|
|
}
|
|
}
|
|
|
|
{
|
|
int32 VertexCount = 0;
|
|
MemAr << VertexCount;
|
|
TArray<uint8> VertexData;
|
|
VertexData.SetNumUninitialized(VertexCount * sizeof(FLandscapeMobileVertex));
|
|
MemAr.Serialize(VertexData.GetData(), VertexData.Num());
|
|
VertexBuffer = new FLandscapeVertexBufferMobile(MoveTemp(VertexData));
|
|
}
|
|
}
|
|
|
|
FLandscapeMobileRenderData::~FLandscapeMobileRenderData()
|
|
{
|
|
// Make sure the vertex buffer is always destroyed from the render thread
|
|
if (VertexBuffer != nullptr)
|
|
{
|
|
if (IsInRenderingThread())
|
|
{
|
|
delete VertexBuffer;
|
|
delete HoleData;
|
|
}
|
|
else
|
|
{
|
|
FLandscapeVertexBufferMobile* InVertexBuffer = VertexBuffer;
|
|
FLandscapeMobileHoleData* InHoleData = HoleData;
|
|
ENQUEUE_RENDER_COMMAND(InitCommand)(
|
|
[InVertexBuffer, InHoleData](FRHICommandListImmediate& RHICmdList)
|
|
{
|
|
delete InVertexBuffer;
|
|
delete InHoleData;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
FLandscapeComponentSceneProxyMobile::FLandscapeComponentSceneProxyMobile(ULandscapeComponent* InComponent)
|
|
: FLandscapeComponentSceneProxy(InComponent)
|
|
, MobileRenderData(InComponent->PlatformData.GetRenderData())
|
|
{
|
|
check(InComponent);
|
|
|
|
check(InComponent->MobileMaterialInterfaces.Num() > 0);
|
|
check(InComponent->MobileWeightmapTextures.Num() > 0);
|
|
|
|
WeightmapTextures = InComponent->MobileWeightmapTextures;
|
|
NormalmapTexture = InComponent->MobileWeightmapTextures[0];
|
|
|
|
#if WITH_EDITOR
|
|
const TArray<FWeightmapLayerAllocationInfo>& LayerAllocations = InComponent->MobileWeightmapLayerAllocations.Num() ? InComponent->MobileWeightmapLayerAllocations : InComponent->GetWeightmapLayerAllocations();
|
|
LayerColors.Empty();
|
|
for (const FWeightmapLayerAllocationInfo& Allocation : LayerAllocations)
|
|
{
|
|
if (Allocation.LayerInfo != nullptr)
|
|
{
|
|
LayerColors.Add(Allocation.LayerInfo->LayerUsageDebugColor);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
FLandscapeComponentSceneProxyMobile::~FLandscapeComponentSceneProxyMobile()
|
|
{
|
|
if (VertexFactory)
|
|
{
|
|
delete VertexFactory;
|
|
VertexFactory = NULL;
|
|
}
|
|
}
|
|
|
|
SIZE_T FLandscapeComponentSceneProxyMobile::GetTypeHash() const
|
|
{
|
|
static size_t UniquePointer;
|
|
return reinterpret_cast<size_t>(&UniquePointer);
|
|
}
|
|
|
|
void FLandscapeComponentSceneProxyMobile::CreateRenderThreadResources()
|
|
{
|
|
LLM_SCOPE(ELLMTag::Landscape);
|
|
|
|
FLandscapeRenderSystem::CreateResources(this);
|
|
|
|
if (VisibilityHelper.ShouldBeVisible())
|
|
{
|
|
RegisterSection();
|
|
}
|
|
|
|
auto FeatureLevel = GetScene().GetFeatureLevel();
|
|
|
|
// Use only index buffers from the shared buffers since the vertex buffers are unique per proxy on mobile
|
|
SharedBuffers = FLandscapeComponentSceneProxy::SharedBuffersMap.FindRef(SharedBuffersKey);
|
|
if (SharedBuffers == nullptr)
|
|
{
|
|
SharedBuffers = new FLandscapeSharedBuffers(
|
|
SharedBuffersKey, SubsectionSizeQuads, NumSubsections,
|
|
FeatureLevel, true);
|
|
|
|
FLandscapeComponentSceneProxy::SharedBuffersMap.Add(SharedBuffersKey, SharedBuffers);
|
|
}
|
|
SharedBuffers->AddRef();
|
|
|
|
// Init vertex buffer
|
|
{
|
|
check(MobileRenderData->VertexBuffer);
|
|
MobileRenderData->VertexBuffer->InitResource();
|
|
|
|
FLandscapeVertexFactoryMobile* LandscapeVertexFactory = new FLandscapeVertexFactoryMobile(FeatureLevel);
|
|
LandscapeVertexFactory->MobileData.PositionComponent = FVertexStreamComponent(MobileRenderData->VertexBuffer, STRUCT_OFFSET(FLandscapeMobileVertex, Position), sizeof(FLandscapeMobileVertex), VET_UByte4N);
|
|
for (uint32 Index = 0; Index < LANDSCAPE_MAX_ES_LOD_COMP; ++Index)
|
|
{
|
|
LandscapeVertexFactory->MobileData.LODHeightsComponent.Add
|
|
(FVertexStreamComponent(MobileRenderData->VertexBuffer, STRUCT_OFFSET(FLandscapeMobileVertex, LODHeights) + sizeof(uint8) * 4 * Index, sizeof(FLandscapeMobileVertex), VET_UByte4N));
|
|
}
|
|
|
|
LandscapeVertexFactory->InitResource();
|
|
VertexFactory = LandscapeVertexFactory;
|
|
}
|
|
|
|
// Init vertex buffer for rendering to virtual texture
|
|
if (UseVirtualTexturing(FeatureLevel))
|
|
{
|
|
FLandscapeFixedGridVertexFactoryMobile* LandscapeVertexFactory = new FLandscapeFixedGridVertexFactoryMobile(FeatureLevel);
|
|
LandscapeVertexFactory->MobileData.PositionComponent = FVertexStreamComponent(MobileRenderData->VertexBuffer, STRUCT_OFFSET(FLandscapeMobileVertex, Position), sizeof(FLandscapeMobileVertex), VET_UByte4N);
|
|
|
|
for (uint32 Index = 0; Index < LANDSCAPE_MAX_ES_LOD_COMP; ++Index)
|
|
{
|
|
LandscapeVertexFactory->MobileData.LODHeightsComponent.Add
|
|
(FVertexStreamComponent(MobileRenderData->VertexBuffer, STRUCT_OFFSET(FLandscapeMobileVertex, LODHeights) + sizeof(uint8) * 4 * Index, sizeof(FLandscapeMobileVertex), VET_UByte4N));
|
|
}
|
|
|
|
LandscapeVertexFactory->InitResource();
|
|
FixedGridVertexFactory = LandscapeVertexFactory;
|
|
}
|
|
|
|
// Assign LandscapeUniformShaderParameters
|
|
LandscapeUniformShaderParameters.InitResource();
|
|
|
|
// Create per Lod uniform buffers
|
|
LandscapeFixedGridUniformShaderParameters.AddDefaulted(MaxLOD + 1);
|
|
for (int32 LodIndex = 0; LodIndex <= MaxLOD; ++LodIndex)
|
|
{
|
|
LandscapeFixedGridUniformShaderParameters[LodIndex].InitResource();
|
|
FLandscapeFixedGridUniformShaderParameters Parameters;
|
|
Parameters.LodValues = FVector4f(
|
|
LodIndex,
|
|
0.f,
|
|
(float)((SubsectionSizeVerts >> LodIndex) - 1),
|
|
1.f / (float)((SubsectionSizeVerts >> LodIndex) - 1));
|
|
LandscapeFixedGridUniformShaderParameters[LodIndex].SetContents(Parameters);
|
|
}
|
|
|
|
MobileRenderData->bReadyForStreaming = true;
|
|
}
|
|
|
|
TSharedPtr<FLandscapeMobileRenderData, ESPMode::ThreadSafe> FLandscapeComponentDerivedData::GetRenderData()
|
|
{
|
|
// This function is expected to be called from either the GameThread or via ParallelFor from the GameThread
|
|
check(!IsInActualRenderingThread());
|
|
|
|
if (FPlatformProperties::RequiresCookedData() && CachedRenderData.IsValid())
|
|
{
|
|
// on device we can re-use the cached data if we are re-registering our component.
|
|
return CachedRenderData;
|
|
}
|
|
else
|
|
{
|
|
check(CompressedLandscapeData.Num() > 0);
|
|
CachedRenderData.Reset();
|
|
|
|
FMemoryReader Ar(CompressedLandscapeData);
|
|
|
|
// Note: change LANDSCAPE_FULL_DERIVEDDATA_VER when modifying the serialization layout
|
|
int32 UncompressedSize;
|
|
Ar << UncompressedSize;
|
|
|
|
int32 CompressedSize;
|
|
Ar << CompressedSize;
|
|
|
|
TArray<uint8> CompressedData;
|
|
CompressedData.Empty(CompressedSize);
|
|
CompressedData.AddUninitialized(CompressedSize);
|
|
Ar.Serialize(CompressedData.GetData(), CompressedSize);
|
|
|
|
TArray<uint8> UncompressedData;
|
|
UncompressedData.Empty(UncompressedSize);
|
|
UncompressedData.AddUninitialized(UncompressedSize);
|
|
|
|
verify(FCompression::UncompressMemory(NAME_Zlib, UncompressedData.GetData(), UncompressedSize, CompressedData.GetData(), CompressedSize));
|
|
|
|
TSharedPtr<FLandscapeMobileRenderData, ESPMode::ThreadSafe> RenderData = MakeShareable(new FLandscapeMobileRenderData(MoveTemp(UncompressedData), (uint8)StreamingLODDataArray.Num()));
|
|
|
|
// if running on device
|
|
if (FPlatformProperties::RequiresCookedData())
|
|
{
|
|
// free the compressed data now that we have used it to create the render data.
|
|
CompressedLandscapeData.Empty();
|
|
}
|
|
|
|
// store a reference to the render data so we can use it again should the component be reregistered.
|
|
CachedRenderData = RenderData;
|
|
|
|
return RenderData;
|
|
}
|
|
}
|
|
|
|
void FLandscapeComponentSceneProxyMobile::ApplyMeshElementModifier(FMeshBatchElement& InOutMeshElement, int32 InLodIndex) const
|
|
{
|
|
const bool bHoleDataExists = MobileRenderData->HoleData != nullptr && MobileRenderData->HoleData->IndexBuffer != nullptr && InLodIndex < MobileRenderData->HoleData->NumHoleLods;
|
|
if (bHoleDataExists)
|
|
{
|
|
FLandscapeMobileHoleData const& HoleData = *MobileRenderData->HoleData;
|
|
InOutMeshElement.IndexBuffer = HoleData.IndexBuffer;
|
|
InOutMeshElement.NumPrimitives = HoleData.IndexBufferSize / 3;
|
|
InOutMeshElement.FirstIndex = 0;
|
|
InOutMeshElement.MinVertexIndex = HoleData.MinHoleIndex;
|
|
InOutMeshElement.MaxVertexIndex = HoleData.MaxHoleIndex;
|
|
}
|
|
}
|
|
|
|
#if PLATFORM_SUPPORTS_LANDSCAPE_VISUAL_MESH_LOD_STREAMING
|
|
uint8 FLandscapeComponentSceneProxyMobile::GetCurrentFirstLODIdx_RenderThread() const
|
|
{
|
|
check(MobileRenderData.IsValid());
|
|
return MobileRenderData->CurrentFirstLODIdx;
|
|
}
|
|
#endif
|