RuntimeMeshSectionProxy.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
  2. #pragma once
  3. #include "Engine.h"
  4. #include "Components/MeshComponent.h"
  5. #include "RuntimeMeshProfiling.h"
  6. #include "RuntimeMeshVersion.h"
  7. #include "RuntimeMeshCore.h"
  8. #include "RuntimeMeshRendering.h"
  9. #include "RuntimeMeshUpdateCommands.h"
  10. /** Interface class for the RT proxy of a single mesh section */
  11. class FRuntimeMeshSectionProxyInterface : public FRuntimeMeshVisibilityInterface
  12. {
  13. public:
  14. FRuntimeMeshSectionProxyInterface() {}
  15. virtual ~FRuntimeMeshSectionProxyInterface() {}
  16. virtual bool ShouldRender() = 0;
  17. virtual bool WantsToRenderInStaticPath() const = 0;
  18. virtual bool ShouldUseAdjacencyIndexBuffer() const = 0;
  19. virtual FMaterialRelevance GetMaterialRelevance() const = 0;
  20. virtual void CreateMeshBatch(FMeshBatch& MeshBatch, FMaterialRenderProxy* WireframeMaterial, bool bIsSelected) = 0;
  21. virtual void FinishCreate_RenderThread(FRuntimeMeshSectionCreateDataInterface* UpdateData) = 0;
  22. virtual void FinishUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) = 0;
  23. virtual void FinishPositionUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) = 0;
  24. virtual void FinishPropertyUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) = 0;
  25. };
  26. /** Templated class for the RT proxy of a single mesh section */
  27. template <typename VertexType, bool NeedsPositionOnlyBuffer>
  28. class FRuntimeMeshSectionProxy : public FRuntimeMeshSectionProxyInterface
  29. {
  30. protected:
  31. /** Whether this section is currently visible */
  32. bool bIsVisible;
  33. /** Should this section cast a shadow */
  34. bool bCastsShadow;
  35. /** Whether this section should be using an adjacency index buffer */
  36. bool bShouldUseAdjacency;
  37. /** Whether this section is using a tessellation adjacency index buffer */
  38. bool bIsUsingAdjacency;
  39. /** Update frequency of this section */
  40. const EUpdateFrequency UpdateFrequency;
  41. /** Material applied to this section */
  42. UMaterialInterface* Material;
  43. FMaterialRelevance MaterialRelevance;
  44. FRuntimeMeshVertexBuffer<FVector>* PositionVertexBuffer;
  45. /** Vertex buffer for this section */
  46. FRuntimeMeshVertexBuffer<VertexType> VertexBuffer;
  47. /** Index buffer for this section */
  48. FRuntimeMeshIndexBuffer IndexBuffer;
  49. /** Vertex factory for this section */
  50. FRuntimeMeshVertexFactory VertexFactory;
  51. public:
  52. FRuntimeMeshSectionProxy(FSceneInterface* InScene, EUpdateFrequency InUpdateFrequency, bool bInIsVisible, bool bInCastsShadow, UMaterialInterface* InMaterial, FMaterialRelevance InMaterialRelevance) :
  53. bIsVisible(bInIsVisible), bCastsShadow(bInCastsShadow), UpdateFrequency(InUpdateFrequency), Material(InMaterial), MaterialRelevance(InMaterialRelevance),
  54. PositionVertexBuffer(nullptr), VertexBuffer(InUpdateFrequency), IndexBuffer(InUpdateFrequency), VertexFactory(this)
  55. {
  56. bShouldUseAdjacency = RequiresAdjacencyInformation(InMaterial, VertexFactory.GetType(), InScene->GetFeatureLevel());
  57. }
  58. virtual ~FRuntimeMeshSectionProxy() override
  59. {
  60. VertexBuffer.ReleaseResource();
  61. IndexBuffer.ReleaseResource();
  62. VertexFactory.ReleaseResource();
  63. if (PositionVertexBuffer)
  64. {
  65. PositionVertexBuffer->ReleaseResource();
  66. delete PositionVertexBuffer;
  67. }
  68. }
  69. virtual bool ShouldRender() override { return bIsVisible && VertexBuffer.Num() > 0 && IndexBuffer.Num() > 0; }
  70. virtual bool WantsToRenderInStaticPath() const override { return UpdateFrequency == EUpdateFrequency::Infrequent; }
  71. virtual bool ShouldUseAdjacencyIndexBuffer() const override { return bShouldUseAdjacency; }
  72. virtual FMaterialRelevance GetMaterialRelevance() const { return MaterialRelevance; }
  73. virtual void CreateMeshBatch(FMeshBatch& MeshBatch, FMaterialRenderProxy* WireframeMaterial, bool bIsSelected) override
  74. {
  75. MeshBatch.VertexFactory = &VertexFactory;
  76. MeshBatch.bWireframe = WireframeMaterial != nullptr;
  77. MeshBatch.MaterialRenderProxy = MeshBatch.bWireframe ? WireframeMaterial : Material->GetRenderProxy(bIsSelected);
  78. if (bIsUsingAdjacency && WireframeMaterial == nullptr)
  79. {
  80. MeshBatch.Type = PT_12_ControlPointPatchList;
  81. }
  82. else
  83. {
  84. MeshBatch.Type = PT_TriangleList;
  85. }
  86. MeshBatch.DepthPriorityGroup = SDPG_World;
  87. MeshBatch.CastShadow = bCastsShadow;
  88. FMeshBatchElement& BatchElement = MeshBatch.Elements[0];
  89. BatchElement.IndexBuffer = &IndexBuffer;
  90. BatchElement.FirstIndex = 0;
  91. BatchElement.NumPrimitives = bIsUsingAdjacency? IndexBuffer.Num() / 12 : IndexBuffer.Num() / 3;
  92. BatchElement.MinVertexIndex = 0;
  93. BatchElement.MaxVertexIndex = VertexBuffer.Num() - 1;
  94. }
  95. virtual void FinishCreate_RenderThread(FRuntimeMeshSectionCreateDataInterface* UpdateData) override
  96. {
  97. check(IsInRenderingThread());
  98. auto* SectionUpdateData = UpdateData->As<FRuntimeMeshSectionCreateData<VertexType>>();
  99. check(SectionUpdateData);
  100. if (NeedsPositionOnlyBuffer)
  101. {
  102. // Initialize the position buffer
  103. PositionVertexBuffer = new FRuntimeMeshVertexBuffer<FVector>(UpdateFrequency);
  104. // Get and adjust the vertex structure
  105. auto VertexStructure = VertexType::GetVertexStructure(VertexBuffer);
  106. VertexStructure.PositionComponent = FVertexStreamComponent(PositionVertexBuffer, 0, sizeof(FVector), VET_Float3);
  107. VertexFactory.Init(VertexStructure);
  108. }
  109. else
  110. {
  111. // Get and submit the vertex structure
  112. auto VertexStructure = VertexType::GetVertexStructure(VertexBuffer);
  113. VertexFactory.Init(VertexStructure);
  114. }
  115. // Initialize the vertex factory
  116. VertexFactory.InitResource();
  117. auto& Vertices = SectionUpdateData->VertexBuffer;
  118. VertexBuffer.SetNum(Vertices.Num());
  119. VertexBuffer.SetData(Vertices);
  120. if (NeedsPositionOnlyBuffer)
  121. {
  122. auto& PositionVertices = SectionUpdateData->PositionVertexBuffer;
  123. PositionVertexBuffer->SetNum(PositionVertices.Num());
  124. PositionVertexBuffer->SetData(PositionVertices);
  125. }
  126. auto& Indices = SectionUpdateData->IndexBuffer;
  127. IndexBuffer.SetNum(Indices.Num());
  128. IndexBuffer.SetData(Indices);
  129. bIsUsingAdjacency = SectionUpdateData->bIsAdjacencyIndexBuffer;
  130. }
  131. virtual void FinishUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) override
  132. {
  133. check(IsInRenderingThread());
  134. auto* SectionUpdateData = UpdateData->As<FRuntimeMeshSectionUpdateData<VertexType>>();
  135. check(SectionUpdateData);
  136. if (SectionUpdateData->bIncludeVertexBuffer)
  137. {
  138. auto& VertexBufferData = SectionUpdateData->VertexBuffer;
  139. VertexBuffer.SetNum(VertexBufferData.Num());
  140. VertexBuffer.SetData(VertexBufferData);
  141. }
  142. if (NeedsPositionOnlyBuffer && SectionUpdateData->bIncludePositionBuffer)
  143. {
  144. auto& PositionVertices = SectionUpdateData->PositionVertexBuffer;
  145. PositionVertexBuffer->SetNum(PositionVertices.Num());
  146. PositionVertexBuffer->SetData(PositionVertices);
  147. }
  148. if (SectionUpdateData->bIncludeIndices)
  149. {
  150. auto& IndexBufferData = SectionUpdateData->IndexBuffer;
  151. IndexBuffer.SetNum(IndexBufferData.Num());
  152. IndexBuffer.SetData(IndexBufferData);
  153. bIsUsingAdjacency = SectionUpdateData->bIsAdjacencyIndexBuffer;
  154. }
  155. }
  156. virtual void FinishPositionUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) override
  157. {
  158. check(IsInRenderingThread());
  159. // Get the Position Only update data
  160. auto* SectionUpdateData = UpdateData->As<FRuntimeMeshSectionPositionOnlyUpdateData<VertexType>>();
  161. check(SectionUpdateData);
  162. // Copy the new data to the gpu
  163. PositionVertexBuffer->SetData(SectionUpdateData->PositionVertexBuffer);
  164. }
  165. virtual void FinishPropertyUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) override
  166. {
  167. auto* SectionUpdateData = UpdateData->As<FRuntimeMeshSectionPropertyUpdateData>();
  168. check(SectionUpdateData);
  169. // Copy visibility/shadow
  170. bIsVisible = SectionUpdateData->bIsVisible;
  171. bCastsShadow = SectionUpdateData->bCastsShadow;
  172. }
  173. };