diff --git a/Content/DynamicLineMaterial.uasset b/Content/DynamicLineMaterial.uasset index 26f025290ed78a74a384cd2da2d1cabe3817a43b..3f918f4a1b441eda6db831988e4b81e311b91702 100644 Binary files a/Content/DynamicLineMaterial.uasset and b/Content/DynamicLineMaterial.uasset differ diff --git a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp index 240eb831057f349038068ac954b1ed48a70d23e9..fdf33513f09daa335e7d22fd087eb26304b226d2 100644 --- a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp +++ b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp @@ -26,8 +26,9 @@ UGPUInstancedLineComponent::UGPUInstancedLineComponent(const FObjectInitializer& SetGenerateOverlapEvents(false); SetCanEverAffectNavigation(false); - - static ConstructorHelpers::FObjectFinder<UStaticMesh>LineMeshAsset(TEXT("StaticMesh'/InstancedMeshLineRendering/line_subdivided5.line_subdivided5'")); + + // Use optimized line here for now. + static ConstructorHelpers::FObjectFinder<UStaticMesh>LineMeshAsset(TEXT("StaticMesh'/InstancedMeshLineRendering/optimized_line.optimized_line'")); static ConstructorHelpers::FObjectFinder<UMaterial>LineMaterialAsset(TEXT("Material'/InstancedMeshLineRendering/DynamicLineMaterial.DynamicLineMaterial'")); UStaticMesh* LineAsset = LineMeshAsset.Object; UMaterial* LineMaterial = LineMaterialAsset.Object; @@ -89,22 +90,26 @@ void UGPUInstancedLineComponent::UpdateWholeTexture() const FLinearColor UGPUInstancedLineComponent::GetLineColor(int32 LineId) { - const float R = PerInstanceSMCustomData[LineMap[LineId].IndexArray[0].InstanceIndex * NumCustomDataFloats]; - const float G = PerInstanceSMCustomData[LineMap[LineId].IndexArray[0].InstanceIndex * NumCustomDataFloats + 1]; - const float B = PerInstanceSMCustomData[LineMap[LineId].IndexArray[0].InstanceIndex * NumCustomDataFloats + 2]; - return { R, G, B }; + const float* CustomDataColorPointer = &PerInstanceSMCustomData[LineMap[LineId].IndexArray[0].InstanceIndex * NumCustomDataFloats]; + return { *CustomDataColorPointer, *(CustomDataColorPointer + 1), *(CustomDataColorPointer + 2) }; } int32 UGPUInstancedLineComponent::AddNewSegmentInstance(const FLinearColor& Color, float Width, int32 Index) { // Add with a dummy transform const int32 InstanceId = AddInstance(FTransform::Identity); + InitializeCreatedSegmentInstance(InstanceId, Color, Width, Index); + return InstanceId; +} + +void UGPUInstancedLineComponent::InitializeCreatedSegmentInstance(const int InstanceId, const FLinearColor& Color, + float Width, int32 Index) +{ SetCustomDataValue(InstanceId, 0, Color.R, false); SetCustomDataValue(InstanceId, 1, Color.G, false); - SetCustomDataValue(InstanceId, 2, Color.B, 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::UpdateTexture(const FIntPoint& StartIndex, int32 NumberOfPoints, uint8* SrcData, bool bMarkRenderStateDirty) @@ -122,8 +127,8 @@ void UGPUInstancedLineComponent::UpdateTexture(const FIntPoint& StartIndex, int3 }); // Probably not a good place to call this - if(bMarkRenderStateDirty) - MarkRenderStateDirty(); + //if(bMarkRenderStateDirty) + // MarkRenderStateDirty(); } void UGPUInstancedLineComponent::Init() @@ -526,33 +531,18 @@ bool UGPUInstancedLineComponent::ResizeTexture(int32 Width, int32 Height) return true; } -void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int32 NumberOfSegmentsPerLine, - TArray<FVector4>& Points, const TArray<FLinearColor>& Colors, const TArray<float>& Widths) +void UGPUInstancedLineComponent::AddBulkInternal(int32 NumberOfLines, int32 NumberOfSegmentsPerLine, + const TArray<FLinearColor>& Colors, const TArray<float>& Widths) { - if (LinearLineData.Num() != 0 || LineMap.Num() != 0 || GetInstanceCount() != 0) - { - LinearLineData.Empty(); // Reset - LineMap.Empty(); - - //NextFreeId = 0; - CurrentTextureIndex = 0; - CurrentTextureMarker = FIntPoint(0, 0); - ClearInstances(); - } - - if (Points.Num() != NumberOfLines * (NumberOfSegmentsPerLine + 1)) - { - UE_LOG(LogLineRendering, Fatal, TEXT("UGPUInstancedLineComponent::InitializeLinesInBulk : Inconsistent number of points and lines!")); - } - - LinearLineData = MoveTemp(Points); - - // Add the number of instances - sadly this requires the for loop const bool UniformColor = Colors.Num() == 1; const bool UniformWidth = Widths.Num() == 1; - + + TArray<FTransform> DummyTransforms; + DummyTransforms.SetNum(NumberOfLines * NumberOfSegmentsPerLine); + AddInstances(DummyTransforms, false); + for (int32 LineIndex = 0; LineIndex < NumberOfLines; ++LineIndex) { const FLinearColor Color = UniformColor ? Colors[0] : Colors[LineIndex]; @@ -560,23 +550,50 @@ void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int3 const int32 Idx = LineMap.Add(FGPULineArray()); FGPULineArray& NewLineArray = LineMap[Idx]; NewLineArray.IndexArray.Reserve(NumberOfSegmentsPerLine + 1); - + for (int32 PointIndex = 0; PointIndex < NumberOfSegmentsPerLine; ++PointIndex) { - const int32 InstanceId = AddNewSegmentInstance(Color, Width, CurrentTextureIndex); - NewLineArray.IndexArray.Add({InstanceId, LineIndex * (NumberOfSegmentsPerLine + 1) + PointIndex}); + //const int32 InstanceId = AddNewSegmentInstance(Color, Width, CurrentTextureIndex); + const int32 InstanceId = CurrentTextureIndex; + InitializeCreatedSegmentInstance(InstanceId, Color, Width, CurrentTextureIndex); + NewLineArray.IndexArray.Add({ InstanceId, LineIndex * (NumberOfSegmentsPerLine + 1) + PointIndex }); CurrentTextureIndex++; MoveTextureMarker(); } - NewLineArray.IndexArray.Add({-1, LineIndex * (NumberOfSegmentsPerLine + 1) + NumberOfSegmentsPerLine}); + NewLineArray.IndexArray.Add({ -1, LineIndex * (NumberOfSegmentsPerLine + 1) + NumberOfSegmentsPerLine }); MoveTextureMarker(); CurrentTextureIndex++; //NextFreeId++; } MarkRenderStateDirty(); - UpdateWholeTexture(); + UpdateWholeTexture(); +} + +void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int32 NumberOfSegmentsPerLine, + TArray<FVector4>& Points, const TArray<FLinearColor>& Colors, const TArray<float>& Widths) +{ + if (LinearLineData.Num() != 0 || LineMap.Num() != 0 || GetInstanceCount() != 0) + { + LinearLineData.Empty(); // Reset + LineMap.Empty(); + + //NextFreeId = 0; + CurrentTextureIndex = 0; + CurrentTextureMarker = FIntPoint(0, 0); + ClearInstances(); + } + + if (Points.Num() != NumberOfLines * (NumberOfSegmentsPerLine + 1)) + { + UE_LOG(LogLineRendering, Fatal, TEXT("UGPUInstancedLineComponent::InitializeLinesInBulk : Inconsistent number of points and lines!")); + } + + LinearLineData = MoveTemp(Points); + + AddBulkInternal(NumberOfLines, NumberOfSegmentsPerLine, Colors, Widths); + } void UGPUInstancedLineComponent::InitializeLinesInBulkTesselate(int32 NumberOfLines, int32 NumberOfSegmentsPerLine, @@ -623,36 +640,7 @@ void UGPUInstancedLineComponent::InitializeLinesInBulkTesselate(int32 NumberOfLi } - // Add the number of instances - sadly this requires the for loop - - const bool UniformColor = Colors.Num() == 1; - const bool UniformWidth = Widths.Num() == 1; - - for (int32 LineIndex = 0; LineIndex < NumberOfLines; ++LineIndex) - { - const FLinearColor Color = UniformColor ? Colors[0] : Colors[LineIndex]; - const float Width = UniformWidth ? Widths[0] : Widths[LineIndex]; - const int32 Idx = LineMap.Add(FGPULineArray()); - FGPULineArray& NewLineArray = LineMap[Idx]; - NewLineArray.IndexArray.Reserve(NumberOfSegmentsPerLine + 1); - - for (int32 PointIndex = 0; PointIndex < NumberOfSegmentsPerLine; ++PointIndex) - { - const int32 InstanceId = AddNewSegmentInstance(Color, Width, CurrentTextureIndex); - NewLineArray.IndexArray.Add({ InstanceId, LineIndex * (NumberOfSegmentsPerLine + 1) + PointIndex }); - CurrentTextureIndex++; - - MoveTextureMarker(); - } - NewLineArray.IndexArray.Add({ -1, LineIndex * (NumberOfSegmentsPerLine + 1) + NumberOfSegmentsPerLine }); - MoveTextureMarker(); - CurrentTextureIndex++; - //NextFreeId++; - } - - MarkRenderStateDirty(); - UpdateWholeTexture(); - + AddBulkInternal(NumberOfLines, NumberOfSegmentsPerLine, Colors, Widths); } diff --git a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h index ee7e845a51d82dae9d0c46e8409781b241838fd3..ddb24ac0df444ef61a677da82494568d3bfb54d6 100644 --- a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h +++ b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h @@ -132,9 +132,12 @@ private: int32 AddNewSegmentInstance(const FLinearColor& Color, float Width, int32 Index); - void UpdateTexture(const FIntPoint& StartIndex, int32 NumberOfPoints, uint8* SrcData, bool bMarkRenderStateDirty = true); + void InitializeCreatedSegmentInstance(const int InstanceId, const FLinearColor& Color, float Width, int32 Index); + void UpdateTexture(const FIntPoint& StartIndex, int32 NumberOfPoints, uint8* SrcData, bool bMarkRenderStateDirty = true); + void AddBulkInternal(int32 NumberOfLines, int32 NumberOfSegmentsPerLine, const TArray<FLinearColor>& Colors, const TArray<float>& Widths); + public: void UpdateWholeTexture() const;