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/Content/FBX/line_subdivided.fbx b/Content/FBX/line_subdivided.fbx new file mode 100644 index 0000000000000000000000000000000000000000..9156f9d2ede9144f866ab16aaab74415ee8bc573 Binary files /dev/null and b/Content/FBX/line_subdivided.fbx differ diff --git a/Content/FBX/line_subdivided.obj b/Content/FBX/line_subdivided.obj new file mode 100644 index 0000000000000000000000000000000000000000..2b22144549bd75808b6242f91d77ba9507a3cb03 --- /dev/null +++ b/Content/FBX/line_subdivided.obj @@ -0,0 +1,61 @@ +# Blender v2.81 (sub 16) OBJ File: '' +# www.blender.org +mtllib untitled.mtl +o Plane.001 +v -0.000001 0.000000 1.000000 +v -0.000000 1.000000 1.000000 +v -0.000001 0.000000 -1.000000 +v -0.000001 1.000000 -1.000000 +v -0.000001 0.109067 1.000000 +v -0.000001 0.209067 1.000000 +v -0.000000 0.309067 1.000000 +v -0.000000 0.409067 1.000000 +v -0.000000 0.509067 1.000000 +v -0.000000 0.609067 1.000000 +v -0.000000 0.709067 1.000000 +v -0.000000 0.809067 1.000000 +v -0.000000 0.909067 1.000000 +v -0.000001 0.909067 -1.000000 +v -0.000001 0.809067 -1.000000 +v -0.000001 0.709067 -1.000000 +v -0.000001 0.609067 -1.000000 +v -0.000001 0.509067 -1.000000 +v -0.000001 0.409067 -1.000000 +v -0.000001 0.309067 -1.000000 +v -0.000001 0.209067 -1.000000 +v -0.000001 0.109067 -1.000000 +vt 0.909067 0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.909067 1.000000 +vt 0.000000 0.000000 +vt 0.109067 0.000000 +vt 0.109067 1.000000 +vt 0.000000 1.000000 +vt 0.209067 0.000000 +vt 0.209067 1.000000 +vt 0.309067 0.000000 +vt 0.309067 1.000000 +vt 0.409067 0.000000 +vt 0.409067 1.000000 +vt 0.509067 0.000000 +vt 0.509067 1.000000 +vt 0.609067 0.000000 +vt 0.609067 1.000000 +vt 0.709067 0.000000 +vt 0.709067 1.000000 +vt 0.809067 0.000000 +vt 0.809067 1.000000 +vn -1.0000 0.0000 0.0000 +usemtl None +s 1 +f 13/1/1 2/2/1 4/3/1 14/4/1 +f 1/5/1 5/6/1 22/7/1 3/8/1 +f 5/6/1 6/9/1 21/10/1 22/7/1 +f 6/9/1 7/11/1 20/12/1 21/10/1 +f 7/11/1 8/13/1 19/14/1 20/12/1 +f 8/13/1 9/15/1 18/16/1 19/14/1 +f 9/15/1 10/17/1 17/18/1 18/16/1 +f 10/17/1 11/19/1 16/20/1 17/18/1 +f 11/19/1 12/21/1 15/22/1 16/20/1 +f 12/21/1 13/1/1 14/4/1 15/22/1 diff --git a/Content/FBX/line_subdivided2.fbx b/Content/FBX/line_subdivided2.fbx new file mode 100644 index 0000000000000000000000000000000000000000..00a204d0d00d17bf8aaf2afe6076a426aed09417 Binary files /dev/null and b/Content/FBX/line_subdivided2.fbx differ diff --git a/Content/FBX/line_subdivided3.fbx b/Content/FBX/line_subdivided3.fbx new file mode 100644 index 0000000000000000000000000000000000000000..38f6ffd70c71b4a3b32ebb9e1b21f0d87f1e0540 Binary files /dev/null and b/Content/FBX/line_subdivided3.fbx differ diff --git a/Content/FBX/line_subdivided5.fbx b/Content/FBX/line_subdivided5.fbx new file mode 100644 index 0000000000000000000000000000000000000000..e68dc9a802d6f4617c541d196f958d057cb5b21e Binary files /dev/null and b/Content/FBX/line_subdivided5.fbx differ diff --git a/Content/FBX/optimized_line-2.fbx b/Content/FBX/optimized_line-2.fbx new file mode 100644 index 0000000000000000000000000000000000000000..f536baa3a444a69cf7037cb14341aea3ca1bd247 Binary files /dev/null and b/Content/FBX/optimized_line-2.fbx differ diff --git a/Content/FBX/optimized_line.fbx b/Content/FBX/optimized_line.fbx new file mode 100644 index 0000000000000000000000000000000000000000..f536baa3a444a69cf7037cb14341aea3ca1bd247 Binary files /dev/null and b/Content/FBX/optimized_line.fbx differ diff --git a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp index c9bb355e58c833783fb1e6fddea5edb786d21d31..1de264785753e54b00d83595458cc49be38bb2eb 100644 --- a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp +++ b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp @@ -26,7 +26,8 @@ UGPUInstancedLineComponent::UGPUInstancedLineComponent(const FObjectInitializer& SetGenerateOverlapEvents(false); SetCanEverAffectNavigation(false); - + + // 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; @@ -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,20 @@ 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); + + int32 InstanceCounter = 0; + for (int32 LineIndex = 0; LineIndex < NumberOfLines; ++LineIndex) { const FLinearColor Color = UniformColor ? Colors[0] : Colors[LineIndex]; @@ -560,23 +552,49 @@ 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); + InitializeCreatedSegmentInstance(InstanceCounter, Color, Width, CurrentTextureIndex); + NewLineArray.IndexArray.Add({ InstanceCounter, LineIndex * (NumberOfSegmentsPerLine + 1) + PointIndex }); CurrentTextureIndex++; - + InstanceCounter++; 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 +641,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;