diff --git a/Content/DynamicLineMaterial.uasset b/Content/DynamicLineMaterial.uasset
index edbb6625eeb1a6e53b2cc00d07ffb9c7a1ca2aa3..26f025290ed78a74a384cd2da2d1cabe3817a43b 100644
Binary files a/Content/DynamicLineMaterial.uasset and b/Content/DynamicLineMaterial.uasset differ
diff --git a/Content/line_subdivided.uasset b/Content/line_subdivided.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..9176a669bab265b7ae855bd320b742438e2563d5
Binary files /dev/null and b/Content/line_subdivided.uasset differ
diff --git a/Content/line_subdivided2.uasset b/Content/line_subdivided2.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..f13825e8639ccaf1ffa02ac8a8a0aed1d28acac0
Binary files /dev/null and b/Content/line_subdivided2.uasset differ
diff --git a/Content/line_subdivided3.uasset b/Content/line_subdivided3.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..86d57bbf6c0d259ba0cf08e557cc86e8667c115d
Binary files /dev/null and b/Content/line_subdivided3.uasset differ
diff --git a/Content/line_subdivided5.uasset b/Content/line_subdivided5.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..6739970c818bfdb7bc0ac6f3a237dd496ee07f6d
Binary files /dev/null and b/Content/line_subdivided5.uasset differ
diff --git a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
index 291a0c2c28c4fa57a0c0dae04cef349ec6b2010a..c9bb355e58c833783fb1e6fddea5edb786d21d31 100644
--- a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
+++ b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
@@ -61,11 +61,6 @@ UGPUInstancedLineComponent::~UGPUInstancedLineComponent()
 // Not implemented yet because the data structure isn't clear yet.
 void UGPUInstancedLineComponent::ReleaseData()
 {
-	//LineMap.Empty();
-	//LinearLineData.Empty();
-	//NextFreeId = 0;
-	//CurrentTextureMarker.X = 0;
-	//CurrentTextureMarker.Y = 0;
 }
 
 void UGPUInstancedLineComponent::UpdateWholeTexture() const
@@ -92,10 +87,18 @@ 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 };
+}
+
 int32 UGPUInstancedLineComponent::AddNewSegmentInstance(const FLinearColor& Color, float Width, int32 Index)
 {
 	// Add with a dummy transform
-	int32 InstanceId = AddInstance(FTransform::Identity);
+	const int32 InstanceId = AddInstance(FTransform::Identity);
 	SetCustomDataValue(InstanceId, 0, Color.R, false);
 	SetCustomDataValue(InstanceId, 1, Color.G, false);
 	SetCustomDataValue(InstanceId, 2, Color.B, false);
@@ -104,6 +107,25 @@ int32 UGPUInstancedLineComponent::AddNewSegmentInstance(const FLinearColor& Colo
 	return InstanceId;
 }
 
+void UGPUInstancedLineComponent::UpdateTexture(const FIntPoint& StartIndex, int32 NumberOfPoints, uint8* SrcData, bool bMarkRenderStateDirty)
+{
+	int32 NumRegions = 0;
+	FUpdateTextureRegion2D* Regions = CalculateTextureRegions(StartIndex, NumberOfPoints, NumRegions);
+
+	const uint32 Pitch = TextureWidth;
+	PositionTexture->UpdateTextureRegions(0, NumRegions, Regions, Pitch * sizeof(FVector4), sizeof(FVector4), SrcData,
+		[](auto InTextureData, auto InRegions)
+	{
+		// Clean up the copied data
+		delete InTextureData;
+		delete InRegions;
+	});
+
+	// Probably not a good place to call this
+	if(bMarkRenderStateDirty)
+		MarkRenderStateDirty();
+}
+
 void UGPUInstancedLineComponent::Init()
 {	
 	if (PositionTexture == nullptr)
@@ -119,11 +141,6 @@ void UGPUInstancedLineComponent::Init()
 		//UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::Init MID was nullptr!"));
 		DynamicLineMaterial = UMaterialInstanceDynamic::Create(LineMaterialInterface, GetTransientPackage());
 		SetMaterial(0, DynamicLineMaterial);
-		//check(DynamicLineMaterial);
-
-		//DynamicLineMaterial = CreateAndSetMaterialInstanceDynamic(0);
-		//DynamicLineMaterial->SetTextureParameterValue("PositionTexture", PositionTexture);
-		//DynamicLineMaterial->SetScalarParameterValue("TextureWidth", TextureWidth);
 	}
 
 	DynamicLineMaterial->SetTextureParameterValue("PositionTexture", PositionTexture);
@@ -154,6 +171,7 @@ FUpdateTextureRegion2D* UGPUInstancedLineComponent::CalculateTextureRegions(cons
 {	
 	// Calculate the first consecutive region:
 	int32 RemainingPoints = NumberOfPoints;
+	const uint32 TextureWidthU = static_cast<uint32>(TextureWidth);
 	
 	TArray<FUpdateTextureRegion2D>* Regions = new TArray<FUpdateTextureRegion2D>();
 	Regions->AddZeroed(1);
@@ -165,7 +183,7 @@ FUpdateTextureRegion2D* UGPUInstancedLineComponent::CalculateTextureRegions(cons
 	(*Regions)[0].Width = FMath::Min(NumberOfPoints, TextureWidth - static_cast<int32>((*Regions)[0].DestX));
 	(*Regions)[0].Height = StartIndex.X == 0 ? (NumberOfPoints / TextureWidth) : 1;
 
-	checkf((*Regions)[0].DestX + (*Regions)[0].Width <= (uint32)TextureWidth, TEXT("Region[0] out of bounds on X. Texture: %i, %i, %i"), (*Regions)[0].DestX, (*Regions)[0].Width, PositionTexture->GetSizeX());
+	checkf((*Regions)[0].DestX + (*Regions)[0].Width <= TextureWidthU, TEXT("Region[0] out of bounds on X. Texture: %i, %i, %i"), (*Regions)[0].DestX, (*Regions)[0].Width, PositionTexture->GetSizeX());
 	
 	RemainingPoints -= (*Regions)[0].Height == 1 ? (*Regions)[0].Width : (*Regions)[0].Width * (*Regions)[0].Height;
 	if(RemainingPoints == 0)
@@ -184,7 +202,7 @@ FUpdateTextureRegion2D* UGPUInstancedLineComponent::CalculateTextureRegions(cons
 	(*Regions)[1].Height = RemainingPoints == 0 ? 1 : (RemainingPoints / TextureWidth);
 	RemainingPoints -= (*Regions)[1].Width * ((*Regions)[1].Height - 1);
 
-	checkf((*Regions)[1].DestX + (*Regions)[1].Width <= (uint32)TextureWidth, TEXT("Region[1] out of bounds on X. Texture: %i, %i, %i"), (*Regions)[1].DestX, (*Regions)[1].Width, PositionTexture->GetSizeX());
+	checkf((*Regions)[1].DestX + (*Regions)[1].Width <= TextureWidthU, TEXT("Region[1] out of bounds on X. Texture: %i, %i, %i"), (*Regions)[1].DestX, (*Regions)[1].Width, PositionTexture->GetSizeX());
 
 	if (RemainingPoints == 0)
 	{
@@ -205,7 +223,7 @@ FUpdateTextureRegion2D* UGPUInstancedLineComponent::CalculateTextureRegions(cons
 	(*Regions)[2].Height = RemainingPoints == 0 ? 1 : (RemainingPoints / TextureWidth);
 	RemainingPoints -= (*Regions)[2].Width * ((*Regions)[1].Height - 1);
 
-	checkf((*Regions)[2].DestX + (*Regions)[2].Width <= (uint32)TextureWidth, TEXT("Region[2] out of bounds on X. Texture: %i, %i, %i"), (*Regions)[2].DestX, (*Regions)[2].Width, PositionTexture->GetSizeX());
+	checkf((*Regions)[2].DestX + (*Regions)[2].Width <= TextureWidthU, TEXT("Region[2] out of bounds on X. Texture: %i, %i, %i"), (*Regions)[2].DestX, (*Regions)[2].Width, PositionTexture->GetSizeX());
 
 	
 	if (RemainingPoints > 0)
@@ -226,20 +244,13 @@ void UGPUInstancedLineComponent::BeginPlay()
 	}
 }
 
-// Doesn't do anything yet, just as a testing function to see execution order on Unreal startup.
-void UGPUInstancedLineComponent::PostInitProperties()
-{
-	Super::PostInitProperties();
-	//if (FApp::CanEverRender() && !HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
-		//UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::PostInitProperties IF"));
-}
 
 #if WITH_EDITOR
 void UGPUInstancedLineComponent::PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent)
 {
 	Init();
 	
-	if (PropertyChangedEvent.Property != NULL)
+	if (PropertyChangedEvent.Property != nullptr)
 	{
 		if (PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(UGPUInstancedLineComponent, EditorLines))
 		{
@@ -403,7 +414,7 @@ void UGPUInstancedLineComponent::PostEditChangeProperty(FPropertyChangedEvent& P
 	Init();
 	const FName PropertyName = PropertyChangedEvent.GetPropertyName();
 
-	if (PropertyChangedEvent.Property != NULL)
+	if (PropertyChangedEvent.Property != nullptr)
 	{
 		if (PropertyName == GET_MEMBER_NAME_CHECKED(FEditorPoint, Point))
 		{
@@ -447,29 +458,12 @@ void UGPUInstancedLineComponent::TickComponent(float DeltaTime, ELevelTick TickT
 
 #endif
 
-
-// Doesn't do anything yet, just as a testing function to see execution order on Unreal startup.
-void UGPUInstancedLineComponent::PostLoad()
-{
-	Super::PostLoad();
-}
-
-// Doesn't do anything yet, just as a testing function to see execution order on Unreal startup.
-void UGPUInstancedLineComponent::OnComponentCreated()
-{
-	Super::OnComponentCreated();
-}
-
 void UGPUInstancedLineComponent::BeginDestroy()
 {
 	Super::BeginDestroy();
 	ReleaseData();
 }
 
-void UGPUInstancedLineComponent::Serialize(FArchive& Ar)
-{
-	Super::Serialize(Ar);
-}
 
 void UGPUInstancedLineComponent::ReserveMemory(int32 NumberOfSegments, int32 NumberOfLines)
 {
@@ -563,7 +557,7 @@ void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int3
 	{
 		const FLinearColor Color = UniformColor ? Colors[0] : Colors[LineIndex];
 		const float Width = UniformWidth ? Widths[0] : Widths[LineIndex];
-		int32 Idx = LineMap.Add(FGPULineArray());
+		const int32 Idx = LineMap.Add(FGPULineArray());
 		FGPULineArray& NewLineArray = LineMap[Idx];
 		NewLineArray.IndexArray.Reserve(NumberOfSegmentsPerLine + 1);
 		
@@ -585,6 +579,82 @@ void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int3
 	UpdateWholeTexture();	
 }
 
+void UGPUInstancedLineComponent::InitializeLinesInBulkTesselate(int32 NumberOfLines, int32 NumberOfSegmentsPerLine,
+	TArray<FVector4>& Points, const TArray<FLinearColor>& Colors, const TArray<float>& Widths)
+{
+	// Just as a test
+	const int32 NumOriginalSegments = NumberOfSegmentsPerLine;
+	NumberOfSegmentsPerLine += 9;
+	LinearLineData.Reserve(NumberOfLines * (NumberOfSegmentsPerLine + 1));
+
+	
+	if (LinearLineData.Num() != 0 || LineMap.Num() != 0 || GetInstanceCount() != 0)
+	{
+		LinearLineData.Empty(); // Reset
+		LineMap.Empty();
+
+		//NextFreeId = 0;
+		CurrentTextureIndex = 0;
+		CurrentTextureMarker = FIntPoint(0, 0);
+		ClearInstances();
+	}
+
+	LinearLineData = MoveTemp(Points);
+	
+	// Add tesselated points from back to front	
+	for (int LineIdx = NumberOfLines - 1; LineIdx >= 0; --LineIdx)
+	{
+		// Get start and end of line
+		const FVector4 Start = LinearLineData[LineIdx * (NumOriginalSegments + 1)];
+		const FVector4 End = LinearLineData[LineIdx * (NumOriginalSegments + 1) + 1];
+		const FVector4 Dist = End - Start;
+		// Tesselate
+		const FVector4 First = Start + 0.1 * Dist;
+		const FVector4 Second = Start + 0.2 * Dist;
+		const FVector4 Third = Start + 0.3 * Dist;
+		const FVector4 Fourth = Start + 0.4 * Dist;
+		const FVector4 Fith = Start + 0.5 * Dist;
+		const FVector4 Sixth = Start + 0.6 * Dist;
+		const FVector4 Seventh = Start + 0.7 * Dist;
+		const FVector4 Eigth = Start + 0.8 * Dist;
+		const FVector4 Nineth = Start + 0.9 * Dist;
+
+		LinearLineData.Insert({ First, Second, Third, Fourth, Fith, Sixth, Seventh, Eigth, Nineth }, LineIdx * (NumOriginalSegments + 1) + 1);
+		
+	}
+
+	// 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();
+	
+}
+
 
 int32 UGPUInstancedLineComponent::AddLine(const TArray<FVector>& Line, FLinearColor Color, float Width)
 {
@@ -630,25 +700,12 @@ int32 UGPUInstancedLineComponent::AddLine(const TArray<FVector>& Line, FLinearCo
 	// Store the points in a linear array here
 	LinearLineData.Append(*TextureData);
 
-	int32 NumRegions = 0;
-	FUpdateTextureRegion2D* Regions = CalculateTextureRegions(InitialTextureMarker, Line.Num(), NumRegions);
-	
-	const uint32 Pitch = TextureWidth;
-	PositionTexture->UpdateTextureRegions(0, NumRegions, Regions, Pitch * sizeof(FVector4), sizeof(FVector4), (uint8*)TextureData->GetData(),
-		[](auto InTextureData, auto InRegions)
-	{
-		// Clean up the copied data
-		delete InTextureData;
-		delete InRegions;
-	});
-
-	//UE_LOG(LogLineRendering, Display, TEXT("Added Line #%d"), LineId); // Actually we can!
-
+	UpdateTexture(InitialTextureMarker, Line.Num(), (uint8*)TextureData->GetData());
 
 	return LineId;	
 }
 
-int32 UGPUInstancedLineComponent::AddLine(TArray<FVector4>& Line, FLinearColor Color, float Width)
+int32 UGPUInstancedLineComponent::AddLine(TArray<FVector4>& Line, FLinearColor Color, float Width, bool bMarkRenderStateDirty)
 {
 	if (Line.Num() < 2)
 	{
@@ -687,21 +744,7 @@ int32 UGPUInstancedLineComponent::AddLine(TArray<FVector4>& Line, FLinearColor C
 	// Store the points in a linear array here
 	LinearLineData.Append(*TextureData);
 
-	int32 NumRegions = 0;
-	FUpdateTextureRegion2D* Regions = CalculateTextureRegions(InitialTextureMarker, TextureData->Num(), NumRegions);
-
-	const uint32 Pitch = TextureWidth;
-	PositionTexture->UpdateTextureRegions(0, NumRegions, Regions, Pitch * sizeof(FVector4), sizeof(FVector4), (uint8*)TextureData->GetData(),
-		[](auto InTextureData, auto InRegions)
-	{
-		// Clean up the copied data
-		delete InTextureData;
-		delete InRegions;
-	});
-
-	//UE_LOG(LogLineRendering, Display, TEXT("Added Line #%d"), LineId); // Actually we can!
-
-
+	UpdateTexture(InitialTextureMarker, TextureData->Num(), (uint8*)TextureData->GetData(), bMarkRenderStateDirty);
 	return LineId;
 
 	
@@ -729,17 +772,13 @@ bool UGPUInstancedLineComponent::AddPoint(int32 LineId, const FVector& Point)
 	// Get color and width of the line
 	FGPULineArray& Line = LineMap[LineId];
 
-	
-	const float R = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats];
-	const float G = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 1];
-	const float B = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 2];
 	const float Width = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 3];
 
 	const FIntPoint InitialTextureMarker = CurrentTextureMarker;
 	// Check if it's the last line:
 
 	FGPULineIndices& Indices = Line.IndexArray.Last();
-	const int32 InstanceId = AddNewSegmentInstance({R, G, B}, Width, Indices.TextureIndex);
+	const int32 InstanceId = AddNewSegmentInstance(GetLineColor(LineId), Width, Indices.TextureIndex);
 	Line.IndexArray.Last().InstanceIndex = InstanceId;
 
 	
@@ -899,12 +938,7 @@ bool UGPUInstancedLineComponent::InsertPoint(int32 LineId, int32 SegmentId, cons
 
 bool UGPUInstancedLineComponent::InsertPointWithSameColor(int32 LineId, int32 SegmentId, const FVector& Point)
 {
-	FGPULineArray& Line = LineMap[LineId];	
-	const float R = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats];
-	const float G = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 1];
-	const float B = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 2];
-
-	return InsertPoint(LineId, SegmentId, Point, { R, G, B });
+	return InsertPoint(LineId, SegmentId, Point, GetLineColor(LineId));
 }
 
 bool UGPUInstancedLineComponent::InsertPointWithColor(int32 LineId, int32 SegmentId, const FVector& Point,
@@ -921,9 +955,9 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
 
 	// Get color and width of the line
 	FGPULineArray& Line = LineMap[LineId];
-	const float R = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats];
-	const float G = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 1];
-	const float B = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 2];
+
+	const FLinearColor Color = GetLineColor(LineId);
+	
 	const float Width = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 3];
 
 	const FIntPoint InitialTextureMarker = CurrentTextureMarker;
@@ -938,7 +972,7 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
 	{
 		for (int32 PointIndex = 0; PointIndex < Points.Num(); ++PointIndex)
 		{
-			const int32 InstanceId = AddNewSegmentInstance({ R, G, B }, Width, PointTextureIndex + PointIndex);	
+			const int32 InstanceId = AddNewSegmentInstance(Color, Width, PointTextureIndex + PointIndex);
 
 			// Update the latest dummy entry to point to the actual segment.
 			if (PointIndex == 0)
@@ -960,21 +994,10 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
 
 		// Recreate the data on the heap to allow asynchronous texture update.
 		TArray<FVector4>* TextureData = new TArray<FVector4>(Points);
-		int32 NumberOfRegions = 0;
-		FUpdateTextureRegion2D* Regions = CalculateTextureRegions(InitialTextureMarker, Points.Num(), NumberOfRegions);
-				
-		// Update the actual texture on the gpu
-		const uint32 Pitch = TextureWidth;
-		PositionTexture->UpdateTextureRegions(0, NumberOfRegions, Regions, Pitch * sizeof(FVector4), sizeof(FVector4), (uint8*)TextureData->GetData(),
-			[](auto InTextureData, auto InRegions)
-		{
-			// Clean up the copied data
-			delete InTextureData;
-			delete InRegions;
-		});
-		
+
+		UpdateTexture(InitialTextureMarker, Points.Num(), (uint8*)TextureData->GetData());		
 		
-		MarkRenderStateDirty();
+		//MarkRenderStateDirty(); called in UpdateTexture already
 		return true;
 	}
 
@@ -1000,7 +1023,7 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
 
 	for (int32 PointIndex = 0; PointIndex < Points.Num(); ++PointIndex)
 	{
-		const int32 InstanceId = AddNewSegmentInstance({ R, G, B }, Width, NewPointTextureIndex - 1 + PointIndex);
+		const int32 InstanceId = AddNewSegmentInstance(Color, Width, NewPointTextureIndex - 1 + PointIndex);
 		
 		// Update the latest dummy entry to point to the actual segment.
 		if (PointIndex == 0)
@@ -1043,9 +1066,7 @@ bool UGPUInstancedLineComponent::InsertPoints(int32 LineId, int32 SegmentId, con
 	{
 		return AddPoints(LineId, Points);
 	}
-	const float R = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats];
-	const float G = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 1];
-	const float B = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 2];
+
 	const float Width = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 3];
 
 	const int32 LinearDataIndex = Line.IndexArray[SegmentId].TextureIndex;
@@ -1060,7 +1081,7 @@ bool UGPUInstancedLineComponent::InsertPoints(int32 LineId, int32 SegmentId, con
 	
 	for (int32 PointIndex = 0; PointIndex < Points.Num(); ++PointIndex)
 	{
-		const int32 InstanceId = AddNewSegmentInstance({ R, G, B }, Width, LinearDataIndex + PointIndex);
+		const int32 InstanceId = AddNewSegmentInstance(GetLineColor(LineId), Width, LinearDataIndex + PointIndex);
 		
 		Line.IndexArray.Insert({ InstanceId, LinearDataIndex + PointIndex }, SegmentId + PointIndex);
 		CurrentTextureIndex++;
@@ -1117,15 +1138,7 @@ bool UGPUInstancedLineComponent::UpdateLine(int32 LineId, TArray<FVector>& Point
 	
 	FMemory::Memcpy(LinearLineData.GetData() + TextureIndex, TextureData->GetData(), TextureData->Num() * sizeof(FVector4));
 
-	int32 NumberOfRegions = 0;
-	const FUpdateTextureRegion2D* Regions = CalculateTextureRegions(StartIndex, TextureData->Num(), NumberOfRegions);
-
-	PositionTexture->UpdateTextureRegions(0, NumberOfRegions, Regions, TextureWidth * sizeof(FVector4), sizeof(FVector4), (uint8*)TextureData->GetData(),
-		[](auto InTextureData, auto InRegions)
-	{
-		delete InTextureData;
-		delete InRegions;
-	});
+	UpdateTexture(StartIndex, TextureData->Num(), (uint8*)TextureData->GetData());
 	
 	return true;
 }
@@ -1149,19 +1162,8 @@ bool UGPUInstancedLineComponent::UpdateLinesDataDirectly(int32 LineIdStart, TArr
 		TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UGPUInstancedLineComponent::UpdateLines - MoveTemp Texture Data"))
 		TextureData = new TArray<FVector4>(MoveTemp(Points));
 	}
-	int32 NumberOfRegions = 0;
-	FUpdateTextureRegion2D* Regions;
-	{
-		TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UGPUInstancedLineComponent::UpdateLines - Calculate Texture Regions"))
-		Regions = CalculateTextureRegions(FIntPoint(X, Y), TextureData->Num(), NumberOfRegions);
-	}
-	PositionTexture->UpdateTextureRegions(0, NumberOfRegions, Regions, TextureWidth * sizeof(FVector4), sizeof(FVector4), (uint8*)TextureData->GetData(),
-		[](auto InTextureData, auto InRegions)
-	{
-		delete InTextureData;
-		delete InRegions;
-	});
-	
+
+	UpdateTexture(FIntPoint(X, Y), TextureData->Num(), (uint8*)TextureData->GetData());	
 	return true;
 }
 
@@ -1184,14 +1186,8 @@ bool UGPUInstancedLineComponent::DrawLinesDirectly(int32 LineIdStart, TArray<FVe
 		TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UGPUInstancedLineComponent::DrawLinesDirectly - MoveTemp Texture Data"))
 		TextureData = new TArray<FVector4>(MoveTemp(Points));
 	}
-	int32 NumberOfRegions = 0;
-	FUpdateTextureRegion2D* Regions = CalculateTextureRegions(FIntPoint(X, Y), TextureData->Num(), NumberOfRegions);
-	PositionTexture->UpdateTextureRegions(0, NumberOfRegions, Regions, TextureWidth * sizeof(FVector4), sizeof(FVector4), (uint8*)TextureData->GetData(),
-		[](auto InTextureData, auto InRegions)
-	{
-		delete InTextureData;
-		delete InRegions;
-	});
+	UpdateTexture(FIntPoint(X, Y), TextureData->Num(), (uint8*)TextureData->GetData());
+
 
 	return true;
 }
@@ -1211,14 +1207,7 @@ bool UGPUInstancedLineComponent::DrawLinesDirectly(int32 LineIdStart, TArray<FVe
 	const int32 X = LineIdStart % TextureWidth;
 	const int32 Y = LineIdStart / TextureWidth;
 
-	int32 NumberOfRegions = 0;
-	FUpdateTextureRegion2D* Regions = CalculateTextureRegions(FIntPoint(X, Y), Points->Num(), NumberOfRegions);
-	PositionTexture->UpdateTextureRegions(0, NumberOfRegions, Regions, TextureWidth * sizeof(FVector4), sizeof(FVector4), (uint8*)Points->GetData(),
-		[](auto InTextureData, auto InRegions)
-	{
-		delete InTextureData;
-		delete InRegions;
-	});
+	UpdateTexture(FIntPoint(X, Y), Points->Num(), (uint8*)Points->GetData());
 
 	return true;
 }
@@ -1230,14 +1219,7 @@ bool UGPUInstancedLineComponent::DrawLinesDirectly(int32 LineIdStart, uint8* Src
 	const int32 X = LineIdStart % TextureWidth;
 	const int32 Y = LineIdStart / TextureWidth;
 
-	int32 NumberOfRegions = 0;
-	FUpdateTextureRegion2D* Regions = CalculateTextureRegions(FIntPoint(X, Y), Num, NumberOfRegions);
-	PositionTexture->UpdateTextureRegions(0, NumberOfRegions, Regions, TextureWidth * sizeof(FVector4), sizeof(FVector4), SrcData,
-		[](auto InTextureData, auto InRegions)
-	{
-		delete InTextureData;
-		delete InRegions;
-	});
+	UpdateTexture(FIntPoint(X, Y), Num, SrcData);
 
 	return true;
 }
@@ -1253,10 +1235,7 @@ bool UGPUInstancedLineComponent::UpdatePoint(int32 LineId, int32 PointId, const
 	LinearLineData[PointIndices.TextureIndex].Y = Point.Y;
 	LinearLineData[PointIndices.TextureIndex].Z = Point.Z;
 
-	const int32 InstanceId = (PointIndices.InstanceIndex != -1) ? PointIndices.InstanceIndex : LineMap[LineId].IndexArray[PointId - 1].InstanceIndex;
-
 	const int32 TextureIndex = PointIndices.TextureIndex;
-	//const int32 Y = PerInstanceSMCustomData[InstanceId * NumCustomDataFloats + 5];
 	const int32 X = TextureIndex % TextureWidth;
 	const int32 Y = TextureIndex / TextureWidth;
 
@@ -1269,8 +1248,6 @@ bool UGPUInstancedLineComponent::UpdatePoint(int32 LineId, int32 PointId, const
 			0,
 			0, 1, 1);
 
-
-
 	// Copy for now - no need to do that 
 	TArray<FVector4>* TextureData = new TArray<FVector4>{ LinearLineData[PointIndices.TextureIndex] };
 
@@ -1302,15 +1279,12 @@ bool UGPUInstancedLineComponent::UpdatePoints(int32 LineId, int32 StartingPointI
 		return UpdateLine(LineId, Points);
 	}
 
-	// Should check for validity
-	const FGPULineIndices& FirstPointIndices = LineMap[LineId].IndexArray[StartingPointId];
-
 	TArray<FVector4>* TextureData = new TArray<FVector4>(MoveTemp(Points));
 	if(StartingPointId == 0)
 	{
 		(*TextureData)[0].W = 0;
 	}
-	if (StartingPointId + Points.Num() == Line.IndexArray.Num())
+	if (StartingPointId + TextureData->Num() == Line.IndexArray.Num())
 	{
 		TextureData->Last().W = -1;
 	}
@@ -1319,17 +1293,9 @@ bool UGPUInstancedLineComponent::UpdatePoints(int32 LineId, int32 StartingPointI
 	const FIntPoint StartIndex(StartTextureIndex % TextureWidth, StartTextureIndex / TextureWidth);
 
 	FMemory::Memcpy(LinearLineData.GetData() + StartTextureIndex, TextureData->GetData(), TextureData->Num() * sizeof(FVector4));
-
-	int32 NumberOfRegions = 0;
-	const FUpdateTextureRegion2D* Regions = CalculateTextureRegions(StartIndex, TextureData->Num(), NumberOfRegions);
-
-	PositionTexture->UpdateTextureRegions(0, NumberOfRegions, Regions, TextureWidth * sizeof(FVector4), sizeof(FVector4), (uint8*)TextureData->GetData(),
-		[](auto InTextureData, auto InRegions)
-	{
-		delete InTextureData;
-		delete InRegions;
-	});
-
+	
+	UpdateTexture(StartIndex, TextureData->Num(), (uint8*)TextureData->GetData());
+	
 	return true;
 }
 
@@ -1459,7 +1425,7 @@ bool UGPUInstancedLineComponent::RemovePoint(int32 LineId, int32 PointId)
 			Line.IndexArray[i].TextureIndex -= 1;
 			SetCustomDataValue(Line.IndexArray[i].InstanceIndex, 4, Line.IndexArray[i].TextureIndex, false);
 		}
-		MarkRenderStateDirty();
+		//MarkRenderStateDirty();
 
 		RemoveInstance(RemovedInstanceId);
 	}
diff --git a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
index 87a7b78957ff8acdebb60b6a4ccc86f0e1268872..ee7e845a51d82dae9d0c46e8409781b241838fd3 100644
--- a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
+++ b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
@@ -99,7 +99,6 @@ public:
 
 	virtual void BeginPlay() override;
 
-	virtual void PostInitProperties() override;
 #if WITH_EDITOR
 	virtual void PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent) override;
 	virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; // need this for the widget as for some godforsaken reason the Chain event doesn't fire...
@@ -107,16 +106,7 @@ public:
 	virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
 #endif
 
-	//virtual TStructOnScope<FActorComponentInstanceData> GetComponentInstanceData() const override;
-
-	/** Applies the cached component instance data to a newly blueprint constructed component. */
-	//virtual void ApplyComponentInstanceData(struct FUGPUInstancedLineComponentInstanceData* ComponentInstanceData);
-	
-	virtual void PostLoad() override;
-	virtual void OnComponentCreated() override;
 	virtual void BeginDestroy() override;
-
-	virtual void Serialize(FArchive& Ar) override;
 	
 private:
 
@@ -134,19 +124,21 @@ private:
 
 	void Init();
 
-	//void RegisterSerializedEditorLines();
-
 	void UpdateAllEditorLines();
 
 	FUpdateTextureRegion2D* CalculateTextureRegions(const FIntPoint& StartIndex, int32 NumberOfPoints, int32& NumberOfRegionsOut);
 
-public:
-	// todo
-	void ReleaseData();
+	void ReleaseData(); // todo
+	
+	int32 AddNewSegmentInstance(const FLinearColor& Color, float Width, int32 Index);
+
+	void UpdateTexture(const FIntPoint& StartIndex, int32 NumberOfPoints, uint8* SrcData, bool bMarkRenderStateDirty = true);
 
+
+public:
 	void UpdateWholeTexture() const;
 
-	int32 AddNewSegmentInstance(const FLinearColor& Color, float Width, int32 Index);
+	FLinearColor GetLineColor(int32 LineId);
 	
 	/**
 	 * Reserves internal memory for a given amount of Lines and Segments per Line.
@@ -188,6 +180,9 @@ public:
 	 */
 	UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
 	void InitializeLinesInBulk(int32 NumberOfLines, int32 NumberOfSegmentsPerLine, TArray<FVector4>& Points, const TArray<FLinearColor>& Colors, const TArray<float>& Widths);
+
+	void InitializeLinesInBulkTesselate(int32 NumberOfLines, int32 NumberOfSegmentsPerLine, TArray<FVector4>& Points, const TArray<FLinearColor>& Colors, const TArray<float>& Widths);
+
 	
 	/**
 	 * Adds a line and returns the respective ID of the line, which can be used to identify it for updating, modifying and removing.
@@ -202,7 +197,7 @@ public:
 	int32 AddLine(const TArray<FVector>& Line, FLinearColor Color, float Width = 1.0);
 
 
-	int32 AddLine(TArray<FVector4>& Line, FLinearColor Color, float Width = 1.0);
+	int32 AddLine(TArray<FVector4>& Line, FLinearColor Color, float Width = 1.0, bool bMarkRenderStateDirty = true);
 	
 	/**
 	 * Adds a line and returns the respective ID of the line, which can be used to identify it for updating, modifying and removing.