diff --git a/03-UnrealEngine/Rendering/RenderFeature/ShaderWorldPlugin/ShaderWorld.md b/03-UnrealEngine/Rendering/RenderFeature/ShaderWorldPlugin/ShaderWorld.md index 6e219df..446f8ce 100644 --- a/03-UnrealEngine/Rendering/RenderFeature/ShaderWorldPlugin/ShaderWorld.md +++ b/03-UnrealEngine/Rendering/RenderFeature/ShaderWorldPlugin/ShaderWorld.md @@ -16,9 +16,6 @@ rating: ⭐ - ShaderWorldActor.h:[[#AShaderWorldActor]] - SWorld.h:[[#ASWorld]] -## FRenderCommandFence - - # USWorldSubsystem 主要管理: - TArray SW_Contexts @@ -168,8 +165,10 @@ void AShaderWorldActor::ReadbacksManagement() - bool - RedbuildCollisionContext - Array - - CollisionWorkQueue:类型为FCollisionProcessingWork。 - - CollisionReadToProcess + - CollisionReadToProcess: + - CollisionWorkQueue:类型为FCollisionProcessingWork,碰撞处理任务队列,将回读的 +- FCollisionMeshElement + - ReadBackCompletion:碰撞数据GPU回读是否完成。 ```c++ @@ -230,6 +229,7 @@ void AShaderWorldActor::CollisionManagement(float& DeltaT) ``` #### SetupCollisions() +设置相关变量。 ```c++ bool AShaderWorldActor::SetupCollisions() { @@ -356,7 +356,7 @@ bool AShaderWorldActor::CollisionFinalizeWork() void UShaderWorldCollisionComponent::UpdateSectionTriMesh(TSharedPtr& Positions) { - //UBodySetup + //当UBodySetup更新队列还有任务时,执行改函数会将FSWShareableVerticePositionBuffer加入到UpdatesReceivedDuringCompute数组中并且退出。 if (AsyncBodySetupQueue.Num() > 0) { #if SWDEBUG @@ -370,7 +370,7 @@ void UShaderWorldCollisionComponent::UpdateSectionTriMesh(TSharedPtr 0 && ProcMeshSections[0].PositionBuffer.IsValid() && (ProcMeshSections[0].PositionBuffer->Positions3f.Num() == 0 || ProcMeshSections[0].PositionBuffer->Positions3f.Num() == Positions->Positions.Num()); if(!EnsureSameBuffers) { @@ -398,6 +398,7 @@ void UShaderWorldCollisionComponent::UpdateSectionTriMesh(TSharedPtr(WeakThis.Get())) { + //塞入Normal if(IsValid(Comp)) Comp->ReceiveComputedNormals(PBuffer, Normals); } @@ -408,8 +409,8 @@ void UShaderWorldCollisionComponent::UpdateSectionTriMesh(TSharedPtrCreatePhysicsMeshesAsync(),使用UBodySetup异步创建新的碰撞网格。 + UpdateLocalBounds();//更新UShaderWorldCollisionComponent的LocalBoundingBox UpdateNavigation(); if (ProcMeshSections.Num() > 0 && (ProcMeshSections[0].bSectionVisible || (GetWorld() && !GetWorld()->IsGameWorld()))) @@ -423,6 +424,7 @@ void UShaderWorldCollisionComponent::UpdateSectionTriMesh(TSharedPtrTargetSection = 0; SectionData->NewPositionBuffer = ProcMeshSections[0].PositionBuffer; + //更新SceneProxy FShaderWProceduralMeshSceneProxy的NewPositionBuffer,也就是UpdateSection if(AShaderWorldActor* owner = Cast(GetOwner())) { { @@ -450,6 +452,192 @@ void UShaderWorldCollisionComponent::UpdateSectionTriMesh(TSharedPtr= 0; CollID--) + { + const FName& ElID = CollisionReadToProcess[CollID]; + + + if (!CollisionMesh.Find(ElID)) + { + CollisionWorkQueue.Empty(); + CollisionReadToProcess.RemoveAt(CollID); + continue; + } + + //判断FCollisionMeshElement是否有效,以及是否将碰撞数据回读完成,如果完成,则将数据添加到碰撞处理队列CollisionWorkQueue,并且从碰撞回读队列CollisionReadToProcess + FCollisionMeshElement& Mesh = *CollisionMesh.Find(ElID); + if ((*Mesh.ReadBackCompletion.Get())) + { + ensure(Mesh.Mesh); + + if(FGeoCProcMeshSection* Section = Mesh.Mesh->GetProcMeshSection(0)) + { + if(CollisionMesh.Contains(CollisionBufferHolder)) + { + CollisionWorkQueue.Emplace( + ElID + , Mesh.HeightData + , (*CollisionMesh.Find(CollisionBufferHolder)).Mesh->VerticesTemplate + , (*CollisionMesh.Find(CollisionBufferHolder)).Mesh->TrianglesTemplate); + } + else + { + SW_LOG("!CollisionMesh.Contains(CollisionBufferHolder)") + } + + } + else + { + SW_LOG("CollisionPreprocessGPU :: Mesh.Mesh->GetProcMeshSection(0) = nullptr") + } + + + CollisionReadToProcess.RemoveAt(CollID); + } + } + + if (!CollisionReadToProcess.IsEmpty()) + { + return false; + } + + + CollisionReadToProcess.Empty(); + + if (CollisionWorkQueue.Num() > 0) + { + (*bProcessingGroundCollision.Get()) = true; + + AShaderWorldActor* SWContext = this; + + Async(EAsyncExecution::TaskGraph, [Completion = bProcessingGroundCollision, RenderAPI = RendererAPI, VerticesPerPatch = CollisionVerticesPerPatch, Work = CollisionWorkQueue] + { + + ParallelFor(Work.Num(), [&](int32 WorkIndex) + { + + const FCollisionProcessingWork& WorkEl = Work[WorkIndex]; + + + if (!WorkEl.Read.IsValid() || !WorkEl.SourceB.IsValid() || !WorkEl.DestB.IsValid()) + return; + + const int NumOfVertex = WorkEl.SourceB->Positions.Num(); + + WorkEl.DestB->Positions.SetNum(NumOfVertex); + WorkEl.DestB->Positions3f.SetNum(NumOfVertex); + WorkEl.DestB->MaterialIndices.SetNum(NumOfVertex); + WorkEl.DestB->Bound = FBox(EForceInit::ForceInit); + + FVector LocationfVertice_WS(0); + uint16 MaterialIndice = 0; + + uint8* ReadData8 = (uint8*)WorkEl.Read->ReadData.GetData(); + + TSet& TrianglesAffectedByHoles = WorkEl.DestB->TrianglesAffectedByHoles; + TrianglesAffectedByHoles.Empty(); + + //#TODO ISPC slower ? +#if 0 // INTEL_ISPC + if (RenderAPI == EGeoRenderingAPI::OpenGL) + { + ispc::ShaderWorld_HeightFromGPUReadOpenGL(NumOfVertex, VerticesPerPatch, ReadData8,(ispc::FVector*)WorkEl.SourceB->Positions.GetData(), (ispc::FVector*)WorkEl.DestB->Positions.GetData(), (ispc::FVector3f*)WorkEl.DestB->Positions3f.GetData(), WorkEl.DestB->MaterialIndices.GetData()); + + } + else + { + ispc::ShaderWorld_HeightFromGPURead(NumOfVertex, VerticesPerPatch, ReadData8, (ispc::FVector3f*)WorkEl.SourceB->Positions3f.GetData(), (ispc::FVector*)WorkEl.DestB->Positions.GetData(), (ispc::FVector3f*)WorkEl.DestB->Positions3f.GetData(), WorkEl.DestB->MaterialIndices.GetData()); + } +#else + + + for (int32 k = 0; k < NumOfVertex; k++) + { + + if (RenderAPI == EGeoRenderingAPI::OpenGL) + { + const int index = k % VerticesPerPatch + (VerticesPerPatch - 1 - (k / VerticesPerPatch)) * VerticesPerPatch; + + LocationfVertice_WS = FVector(WorkEl.SourceB->Positions[k].X, WorkEl.SourceB->Positions[k].Y, GetHeightFromGPURead(&ReadData8[4 * index], MaterialIndice)); + } + else + LocationfVertice_WS = FVector(WorkEl.SourceB->Positions[k].X, WorkEl.SourceB->Positions[k].Y, GetHeightFromGPURead(&ReadData8[4 * k], MaterialIndice)); + + WorkEl.DestB->Positions[k] = LocationfVertice_WS; + WorkEl.DestB->Positions3f[k] = FVector3f(LocationfVertice_WS); + WorkEl.DestB->MaterialIndices[k] = MaterialIndice; + + + /* + * Height below -7km means terrain hole + */ + if(WorkEl.DestB->Positions[k].Z < -700000.0) + { + /* + * Find triangles including this vertex and add them to removed triangles + */ + + if(WorkEl.SourceB->PositionToTriangle.Contains(k)) + { + TrianglesAffectedByHoles.Append(*WorkEl.SourceB->PositionToTriangle.Find(k)); + } + } + else + { + WorkEl.DestB->Bound += WorkEl.DestB->Positions[k]; + } + } + +#endif + /* + * If the terrain has holes, create a custom index buffer with the related triangles removed + */ + if(TrianglesAffectedByHoles.Num() > 0) + { + WorkEl.DestB->FilteredTriangles = MakeShared(); + + for(int32 Triangle = 0; Triangle < WorkEl.TriangleTemplate->Indices.Num()/3; Triangle++) + { + if(!TrianglesAffectedByHoles.Contains(Triangle)) + { + WorkEl.DestB->FilteredTriangles->Indices.Add(WorkEl.TriangleTemplate->Indices[Triangle * 3]); + WorkEl.DestB->FilteredTriangles->Indices.Add(WorkEl.TriangleTemplate->Indices[Triangle * 3 + 1]); + WorkEl.DestB->FilteredTriangles->Indices.Add(WorkEl.TriangleTemplate->Indices[Triangle * 3 + 2]); + + WorkEl.DestB->FilteredTriangles->Triangles_CollisionOnly.Add(WorkEl.TriangleTemplate->Triangles_CollisionOnly[Triangle]); + } + } + } + else + { + WorkEl.DestB->FilteredTriangles.Reset(); + } + + + //WorkEl.DestB->Bound = FBox(WorkEl.DestB->Positions); + } + ); + + if (Completion.IsValid()) + Completion->AtomicSet(false); + + }); + } + + return true; +} +``` + + ### SpawnablesManagement() ### TerrainAndSpawnablesManagement()