diff --git a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp index 68cd46982506e6f4cc8ad1ecb10263f5bb1d92f3..291a0c2c28c4fa57a0c0dae04cef349ec6b2010a 100644 --- a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp +++ b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp @@ -68,7 +68,7 @@ void UGPUInstancedLineComponent::ReleaseData() //CurrentTextureMarker.Y = 0; } -void UGPUInstancedLineComponent::UpdateWholeTexture() +void UGPUInstancedLineComponent::UpdateWholeTexture() const { TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UGPUInstancedLineComponent::UpdateWholeTexture")) @@ -92,6 +92,18 @@ void UGPUInstancedLineComponent::UpdateWholeTexture() }); } +int32 UGPUInstancedLineComponent::AddNewSegmentInstance(const FLinearColor& Color, float Width, int32 Index) +{ + // Add with a dummy transform + int32 InstanceId = AddInstance(FTransform::Identity); + SetCustomDataValue(InstanceId, 0, Color.R, false); + SetCustomDataValue(InstanceId, 1, Color.G, false); + SetCustomDataValue(InstanceId, 2, Color.B, false); + SetCustomDataValue(InstanceId, 3, Width / 2.0f, false); + SetCustomDataValue(InstanceId, 4, static_cast<float>(Index), false); // Segment Start + return InstanceId; +} + void UGPUInstancedLineComponent::Init() { if (PositionTexture == nullptr) @@ -436,64 +448,16 @@ void UGPUInstancedLineComponent::TickComponent(float DeltaTime, ELevelTick TickT #endif -//TStructOnScope<FActorComponentInstanceData> UGPUInstancedLineComponent::GetComponentInstanceData() const -//{ -// TStructOnScope<FActorComponentInstanceData> InstanceData; -//#if WITH_EDITOR -// InstanceData.InitializeAs<FUGPUInstancedLineComponentInstanceData>(this); -// FUGPUInstancedLineComponentInstanceData* LineInstanceData = InstanceData.Cast<FUGPUInstancedLineComponentInstanceData>(); -// -// //LineInstanceData->PositionTexture = PositionTexture; -// //LineInstanceData->DynamicMaterial = DynamicLineMaterial; -// //LineInstanceData->LineMap = LineMap; -// -//#endif -// return InstanceData; -//} -//#endif -// -//void UGPUInstancedLineComponent::ApplyComponentInstanceData(FUGPUInstancedLineComponentInstanceData* ComponentInstanceData) -//{ -//#if WITH_EDITOR -// //check(ComponentInstanceData); -// //if(ComponentInstanceData->PositionTexture != nullptr) -// // PositionTexture = ComponentInstanceData->PositionTexture; -// //if (ComponentInstanceData->DynamicMaterial != nullptr) -// //{ -// // DynamicLineMaterial = ComponentInstanceData->DynamicMaterial; -// // DynamicLineMaterial->SetTextureParameterValue("PositionTexture", PositionTexture); -// // DynamicLineMaterial->SetScalarParameterValue("TextureWidth", TextureWidth); -// // SetMaterial(0, DynamicLineMaterial); -// //} -// //if (ComponentInstanceData->LineMap.Num() > 0) -// // LineMap = ComponentInstanceData->LineMap; -// -// -//#endif -//} - // Doesn't do anything yet, just as a testing function to see execution order on Unreal startup. void UGPUInstancedLineComponent::PostLoad() { Super::PostLoad(); - //UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::PostLoad")); - //if (FApp::CanEverRender() && !IsTemplate()) - //{ - //DynamicLineMaterial = UMaterialInstanceDynamic::Create(LineMaterialInterface, this); - //SetMaterial(0, DynamicLineMaterial); - //} } // Doesn't do anything yet, just as a testing function to see execution order on Unreal startup. void UGPUInstancedLineComponent::OnComponentCreated() { Super::OnComponentCreated(); - //UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::OnComponentCreated")); - //if (FApp::CanEverRender() && !IsTemplate()) - //{ - // DynamicLineMaterial = UMaterialInstanceDynamic::Create(LineMaterialInterface, this); - // SetMaterial(0, DynamicLineMaterial); - //} } void UGPUInstancedLineComponent::BeginDestroy() @@ -605,13 +569,7 @@ void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int3 for (int32 PointIndex = 0; PointIndex < NumberOfSegmentsPerLine; ++PointIndex) { - // Add with a dummy transform - int32 InstanceId = AddInstance(FTransform::Identity); - SetCustomDataValue(InstanceId, 0, Color.R, false); - SetCustomDataValue(InstanceId, 1, Color.G, false); - SetCustomDataValue(InstanceId, 2, Color.B, false); - SetCustomDataValue(InstanceId, 3, Width / 2.0f, false); - SetCustomDataValue(InstanceId, 4, static_cast<float>(CurrentTextureIndex), false); // Segment Start + const int32 InstanceId = AddNewSegmentInstance(Color, Width, CurrentTextureIndex); NewLineArray.IndexArray.Add({InstanceId, LineIndex * (NumberOfSegmentsPerLine + 1) + PointIndex}); CurrentTextureIndex++; @@ -652,12 +610,7 @@ int32 UGPUInstancedLineComponent::AddLine(const TArray<FVector>& Line, FLinearCo for (int32 PointIndex = 0; PointIndex < NumberSegments; ++PointIndex) { // Add with a dummy transform - int32 InstanceId = AddInstance(FTransform::Identity); - SetCustomDataValue(InstanceId, 0, Color.R, false); - SetCustomDataValue(InstanceId, 1, Color.G, false); - SetCustomDataValue(InstanceId, 2, Color.B, false); - SetCustomDataValue(InstanceId, 3, Width / 2.0f, false); - SetCustomDataValue(InstanceId, 4, static_cast<float>(CurrentTextureIndex), false); // Segment Start + const int32 InstanceId = AddNewSegmentInstance(Color, Width, CurrentTextureIndex); NewLineArray.IndexArray.Add({InstanceId, LinearLineData.Num() + PointIndex}); CurrentTextureIndex++; @@ -716,12 +669,7 @@ int32 UGPUInstancedLineComponent::AddLine(TArray<FVector4>& Line, FLinearColor C for (int32 PointIndex = 0; PointIndex < NumberSegments; ++PointIndex) { // Add with a dummy transform - int32 InstanceId = AddInstance(FTransform::Identity); - SetCustomDataValue(InstanceId, 0, Color.R, false); - SetCustomDataValue(InstanceId, 1, Color.G, false); - SetCustomDataValue(InstanceId, 2, Color.B, false); - SetCustomDataValue(InstanceId, 3, Width / 2.0f, false); - SetCustomDataValue(InstanceId, 4, static_cast<float>(CurrentTextureIndex), false); // Segment Start + const int32 InstanceId = AddNewSegmentInstance(Color, Width, CurrentTextureIndex); NewLineArray.IndexArray.Add({ InstanceId, LinearLineData.Num() + PointIndex }); CurrentTextureIndex++; @@ -791,16 +739,10 @@ bool UGPUInstancedLineComponent::AddPoint(int32 LineId, const FVector& Point) // Check if it's the last line: FGPULineIndices& Indices = Line.IndexArray.Last(); - const int32 InstanceId = AddInstanceWorldSpace(FTransform::Identity); - SetCustomDataValue(InstanceId, 0, R, false); - SetCustomDataValue(InstanceId, 1, G, false); - SetCustomDataValue(InstanceId, 2, B, false); - SetCustomDataValue(InstanceId, 3, Width / 2.0f, false); - - // Update the latest dummy entry to point to the actual segment. + const int32 InstanceId = AddNewSegmentInstance({R, G, B}, Width, Indices.TextureIndex); Line.IndexArray.Last().InstanceIndex = InstanceId; - // Set remaining custom data for the newly created segment: - SetCustomDataValue(InstanceId, 4, static_cast<float>(Indices.TextureIndex), false); // Segment Start + + FVector4& PreviousLastPoint = LinearLineData[Indices.TextureIndex]; PreviousLastPoint.W = 1.0; // This isn't the line end anymore. @@ -910,26 +852,18 @@ bool UGPUInstancedLineComponent::InsertPoint(int32 LineId, int32 SegmentId, cons const float Width = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 3]; const int32 LinearDataIndex = Line.IndexArray[SegmentId].TextureIndex; - - // Add a new segment BEFORE the current one. - const int32 InstanceId = AddInstanceWorldSpace(FTransform::Identity); - SetCustomDataValue(InstanceId, 0, Color.R, false); - SetCustomDataValue(InstanceId, 1, Color.G, false); - SetCustomDataValue(InstanceId, 2, Color.B, false); - SetCustomDataValue(InstanceId, 3, Width / 2.0f, false); - LinearLineData.Insert(FVector4(Point), LinearDataIndex); - - - if(SegmentId == 0) + if (SegmentId == 0) { // This is now the new start point LinearLineData[LinearDataIndex].W = 0; // This was the old start point LinearLineData[LinearDataIndex + 1].W = 1; - } + } + // Add a new segment BEFORE the current one. + const int32 InstanceId = AddNewSegmentInstance(Color, Width, LinearDataIndex); + Line.IndexArray.Insert(FGPULineIndices{ InstanceId, LinearDataIndex }, SegmentId); - SetCustomDataValue(InstanceId, 4, LinearDataIndex, false); // Update the rest of the line for(int32 i = SegmentId + 1; i < Line.IndexArray.Num(); ++i) @@ -1004,13 +938,7 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>& { for (int32 PointIndex = 0; PointIndex < Points.Num(); ++PointIndex) { - const int32 InstanceId = AddInstanceWorldSpace(FTransform::Identity); - - SetCustomDataValue(InstanceId, 0, R, false); - SetCustomDataValue(InstanceId, 1, G, false); - SetCustomDataValue(InstanceId, 2, B, false); - SetCustomDataValue(InstanceId, 3, Width / 2.0f, false); - SetCustomDataValue(InstanceId, 4, static_cast<float>(PointTextureIndex + PointIndex), false); + const int32 InstanceId = AddNewSegmentInstance({ R, G, B }, Width, PointTextureIndex + PointIndex); // Update the latest dummy entry to point to the actual segment. if (PointIndex == 0) @@ -1030,9 +958,6 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>& CurrentTextureIndex++; MoveTextureMarker(); - // The line is longer than the remaining space on the row of the texture, so we need to update more than just one row. - const bool bMultiRow = InitialTextureMarker.Y != CurrentTextureMarker.Y; - // Recreate the data on the heap to allow asynchronous texture update. TArray<FVector4>* TextureData = new TArray<FVector4>(Points); int32 NumberOfRegions = 0; @@ -1075,14 +1000,8 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>& for (int32 PointIndex = 0; PointIndex < Points.Num(); ++PointIndex) { - const int32 InstanceId = AddInstanceWorldSpace(FTransform::Identity); - - SetCustomDataValue(InstanceId, 0, R, false); - SetCustomDataValue(InstanceId, 1, G, false); - SetCustomDataValue(InstanceId, 2, B, false); - SetCustomDataValue(InstanceId, 3, Width / 2.0f, false); - SetCustomDataValue(InstanceId, 4, static_cast<float>(NewPointTextureIndex - 1 + PointIndex), false); - + const int32 InstanceId = AddNewSegmentInstance({ R, G, B }, Width, NewPointTextureIndex - 1 + PointIndex); + // Update the latest dummy entry to point to the actual segment. if (PointIndex == 0) Line.IndexArray.Last().InstanceIndex = InstanceId; @@ -1141,14 +1060,9 @@ bool UGPUInstancedLineComponent::InsertPoints(int32 LineId, int32 SegmentId, con for (int32 PointIndex = 0; PointIndex < Points.Num(); ++PointIndex) { - const int32 InstanceId = AddInstanceWorldSpace(FTransform::Identity); - SetCustomDataValue(InstanceId, 0, R, false); - SetCustomDataValue(InstanceId, 1, G, false); - SetCustomDataValue(InstanceId, 2, B, false); - SetCustomDataValue(InstanceId, 3, Width / 2.0f, false); + const int32 InstanceId = AddNewSegmentInstance({ R, G, B }, Width, LinearDataIndex + PointIndex); Line.IndexArray.Insert({ InstanceId, LinearDataIndex + PointIndex }, SegmentId + PointIndex); - SetCustomDataValue(InstanceId, 4, LinearDataIndex + PointIndex, false); CurrentTextureIndex++; MoveTextureMarker(); } diff --git a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h index 9bcf844f09b2390429be44a5e09b0f7275ee3dbd..87a7b78957ff8acdebb60b6a4ccc86f0e1268872 100644 --- a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h +++ b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h @@ -144,8 +144,9 @@ public: // todo void ReleaseData(); - void UpdateWholeTexture(); + void UpdateWholeTexture() const; + int32 AddNewSegmentInstance(const FLinearColor& Color, float Width, int32 Index); /** * Reserves internal memory for a given amount of Lines and Segments per Line.