| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- // Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
- #pragma once
- #include "Engine.h"
- #include "Components/MeshComponent.h"
- #include "RuntimeMeshProfiling.h"
- #include "RuntimeMeshVersion.h"
- #include "RuntimeMeshCore.h"
- #include "RuntimeMeshRendering.h"
- #include "RuntimeMeshUpdateCommands.h"
- /** Interface class for the RT proxy of a single mesh section */
- class FRuntimeMeshSectionProxyInterface : public FRuntimeMeshVisibilityInterface
- {
- public:
- FRuntimeMeshSectionProxyInterface() {}
- virtual ~FRuntimeMeshSectionProxyInterface() {}
- virtual bool ShouldRender() = 0;
- virtual bool WantsToRenderInStaticPath() const = 0;
- virtual bool ShouldUseAdjacencyIndexBuffer() const = 0;
- virtual FMaterialRelevance GetMaterialRelevance() const = 0;
- virtual void CreateMeshBatch(FMeshBatch& MeshBatch, FMaterialRenderProxy* WireframeMaterial, bool bIsSelected) = 0;
- virtual void FinishCreate_RenderThread(FRuntimeMeshSectionCreateDataInterface* UpdateData) = 0;
- virtual void FinishUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) = 0;
- virtual void FinishPositionUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) = 0;
- virtual void FinishPropertyUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) = 0;
- };
- /** Templated class for the RT proxy of a single mesh section */
- template <typename VertexType, bool NeedsPositionOnlyBuffer>
- class FRuntimeMeshSectionProxy : public FRuntimeMeshSectionProxyInterface
- {
- protected:
- /** Whether this section is currently visible */
- bool bIsVisible;
- /** Should this section cast a shadow */
- bool bCastsShadow;
- /** Whether this section should be using an adjacency index buffer */
- bool bShouldUseAdjacency;
- /** Whether this section is using a tessellation adjacency index buffer */
- bool bIsUsingAdjacency;
- /** Update frequency of this section */
- const EUpdateFrequency UpdateFrequency;
- /** Material applied to this section */
- UMaterialInterface* Material;
- FMaterialRelevance MaterialRelevance;
- FRuntimeMeshVertexBuffer<FVector>* PositionVertexBuffer;
- /** Vertex buffer for this section */
- FRuntimeMeshVertexBuffer<VertexType> VertexBuffer;
- /** Index buffer for this section */
- FRuntimeMeshIndexBuffer IndexBuffer;
- /** Vertex factory for this section */
- FRuntimeMeshVertexFactory VertexFactory;
- public:
- FRuntimeMeshSectionProxy(FSceneInterface* InScene, EUpdateFrequency InUpdateFrequency, bool bInIsVisible, bool bInCastsShadow, UMaterialInterface* InMaterial, FMaterialRelevance InMaterialRelevance) :
- bIsVisible(bInIsVisible), bCastsShadow(bInCastsShadow), UpdateFrequency(InUpdateFrequency), Material(InMaterial), MaterialRelevance(InMaterialRelevance),
- PositionVertexBuffer(nullptr), VertexBuffer(InUpdateFrequency), IndexBuffer(InUpdateFrequency), VertexFactory(this)
- {
- bShouldUseAdjacency = RequiresAdjacencyInformation(InMaterial, VertexFactory.GetType(), InScene->GetFeatureLevel());
- }
- virtual ~FRuntimeMeshSectionProxy() override
- {
- VertexBuffer.ReleaseResource();
- IndexBuffer.ReleaseResource();
- VertexFactory.ReleaseResource();
- if (PositionVertexBuffer)
- {
- PositionVertexBuffer->ReleaseResource();
- delete PositionVertexBuffer;
- }
- }
- virtual bool ShouldRender() override { return bIsVisible && VertexBuffer.Num() > 0 && IndexBuffer.Num() > 0; }
- virtual bool WantsToRenderInStaticPath() const override { return UpdateFrequency == EUpdateFrequency::Infrequent; }
-
- virtual bool ShouldUseAdjacencyIndexBuffer() const override { return bShouldUseAdjacency; }
- virtual FMaterialRelevance GetMaterialRelevance() const { return MaterialRelevance; }
-
- virtual void CreateMeshBatch(FMeshBatch& MeshBatch, FMaterialRenderProxy* WireframeMaterial, bool bIsSelected) override
- {
- MeshBatch.VertexFactory = &VertexFactory;
- MeshBatch.bWireframe = WireframeMaterial != nullptr;
- MeshBatch.MaterialRenderProxy = MeshBatch.bWireframe ? WireframeMaterial : Material->GetRenderProxy(bIsSelected);
-
- if (bIsUsingAdjacency && WireframeMaterial == nullptr)
- {
- MeshBatch.Type = PT_12_ControlPointPatchList;
- }
- else
- {
- MeshBatch.Type = PT_TriangleList;
- }
- MeshBatch.DepthPriorityGroup = SDPG_World;
- MeshBatch.CastShadow = bCastsShadow;
- FMeshBatchElement& BatchElement = MeshBatch.Elements[0];
- BatchElement.IndexBuffer = &IndexBuffer;
- BatchElement.FirstIndex = 0;
- BatchElement.NumPrimitives = bIsUsingAdjacency? IndexBuffer.Num() / 12 : IndexBuffer.Num() / 3;
- BatchElement.MinVertexIndex = 0;
- BatchElement.MaxVertexIndex = VertexBuffer.Num() - 1;
- }
- virtual void FinishCreate_RenderThread(FRuntimeMeshSectionCreateDataInterface* UpdateData) override
- {
- check(IsInRenderingThread());
- auto* SectionUpdateData = UpdateData->As<FRuntimeMeshSectionCreateData<VertexType>>();
- check(SectionUpdateData);
-
- if (NeedsPositionOnlyBuffer)
- {
- // Initialize the position buffer
- PositionVertexBuffer = new FRuntimeMeshVertexBuffer<FVector>(UpdateFrequency);
- // Get and adjust the vertex structure
- auto VertexStructure = VertexType::GetVertexStructure(VertexBuffer);
- VertexStructure.PositionComponent = FVertexStreamComponent(PositionVertexBuffer, 0, sizeof(FVector), VET_Float3);
- VertexFactory.Init(VertexStructure);
- }
- else
- {
- // Get and submit the vertex structure
- auto VertexStructure = VertexType::GetVertexStructure(VertexBuffer);
- VertexFactory.Init(VertexStructure);
- }
-
- // Initialize the vertex factory
- VertexFactory.InitResource();
- auto& Vertices = SectionUpdateData->VertexBuffer;
- VertexBuffer.SetNum(Vertices.Num());
- VertexBuffer.SetData(Vertices);
- if (NeedsPositionOnlyBuffer)
- {
- auto& PositionVertices = SectionUpdateData->PositionVertexBuffer;
- PositionVertexBuffer->SetNum(PositionVertices.Num());
- PositionVertexBuffer->SetData(PositionVertices);
- }
-
- auto& Indices = SectionUpdateData->IndexBuffer;
- IndexBuffer.SetNum(Indices.Num());
- IndexBuffer.SetData(Indices);
- bIsUsingAdjacency = SectionUpdateData->bIsAdjacencyIndexBuffer;
- }
-
- virtual void FinishUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) override
- {
- check(IsInRenderingThread());
- auto* SectionUpdateData = UpdateData->As<FRuntimeMeshSectionUpdateData<VertexType>>();
- check(SectionUpdateData);
- if (SectionUpdateData->bIncludeVertexBuffer)
- {
- auto& VertexBufferData = SectionUpdateData->VertexBuffer;
- VertexBuffer.SetNum(VertexBufferData.Num());
- VertexBuffer.SetData(VertexBufferData);
- }
- if (NeedsPositionOnlyBuffer && SectionUpdateData->bIncludePositionBuffer)
- {
- auto& PositionVertices = SectionUpdateData->PositionVertexBuffer;
- PositionVertexBuffer->SetNum(PositionVertices.Num());
- PositionVertexBuffer->SetData(PositionVertices);
- }
- if (SectionUpdateData->bIncludeIndices)
- {
- auto& IndexBufferData = SectionUpdateData->IndexBuffer;
- IndexBuffer.SetNum(IndexBufferData.Num());
- IndexBuffer.SetData(IndexBufferData);
- bIsUsingAdjacency = SectionUpdateData->bIsAdjacencyIndexBuffer;
- }
- }
- virtual void FinishPositionUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) override
- {
- check(IsInRenderingThread());
- // Get the Position Only update data
- auto* SectionUpdateData = UpdateData->As<FRuntimeMeshSectionPositionOnlyUpdateData<VertexType>>();
- check(SectionUpdateData);
-
- // Copy the new data to the gpu
- PositionVertexBuffer->SetData(SectionUpdateData->PositionVertexBuffer);
- }
- virtual void FinishPropertyUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) override
- {
- auto* SectionUpdateData = UpdateData->As<FRuntimeMeshSectionPropertyUpdateData>();
- check(SectionUpdateData);
- // Copy visibility/shadow
- bIsVisible = SectionUpdateData->bIsVisible;
- bCastsShadow = SectionUpdateData->bCastsShadow;
- }
- };
|