# Instanced static meshes do not LOD properly

**URL:** <https://forums.unrealengine.com/t/instanced-static-meshes-do-not-lod-properly/296391>\
**Category:** Asset Creation\
**Tags:** unreal-engine, Instanced-Mesh, question\
**Created:** [October 16, 2014, 8:56pm UTC](https://forums.unrealengine.com/t/instanced-static-meshes-do-not-lod-properly/296391 "2014-10-16T20:56:50Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Hyperloop](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/hyperloop/32/1203427_2.png) [@Hyperloop](https://forums.unrealengine.com/u/Hyperloop)\
**Post date:** [October 16, 2014, 8:56pm UTC](https://forums.unrealengine.com/t/instanced-static-meshes-do-not-lod-properly/296391/1 "2014-10-16T20:56:50Z")

</div>

Win 7 64 bit, Editor 4.4.3

When placing a static mesh individually, it will respect LOD settings, but the behavior differs when the same mesh is placed as an instanced static mesh via blueprint.

Based on my research I suspect this is because instanced static meshes are improperly considering the screen size of ALL the instances as if they are one huge mesh.

I understand that every instance of the mesh will LOD at the same time, which of course makes sense, but I believe that calculating the LOD against the TOTAL size of all the instances together is undesirable behavior most of the time because screen size of the individual instances is still going to be the primary indicator of whether or not using a higher LOD makes sense.

---

<div class="post-metadata">

**Author:** ![Tim\_Hobson](https://d3kjluh73b9h9o.cloudfront.net/original/4X/2/8/5/28502927f1d97ba1051b3b47ccfe17233bf41ef0.png) [@Tim\_Hobson](https://forums.unrealengine.com/u/Tim_Hobson)\
**Post date:** [November 11, 2014, 9:31pm UTC](https://forums.unrealengine.com/t/instanced-static-meshes-do-not-lod-properly/296391/2 "2014-11-11T21:31:20Z")

</div>

Hi Hyperloop,

This is a known issue and has been requested before. It is also listed under our documentation for Foliage Instanced Meshes as a caveat in our documenation.

> Currently the entire cluster of  
> instances change LODs simultaneously.  
> We may add support for distance-based  
> fading per instance in the future.

While this is listed in the foliage section the same is true for instances that are in blueprints as well.

Thank you!

Tim

---

<div class="post-metadata">

**Author:** ![Hyperloop](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/hyperloop/32/1203427_2.png) [@Hyperloop](https://forums.unrealengine.com/u/Hyperloop)\
**Post date:** [November 11, 2014, 9:53pm UTC](https://forums.unrealengine.com/t/instanced-static-meshes-do-not-lod-properly/296391/3 "2014-11-11T21:53:47Z")

</div>

Tim, thank you for the reply.

I think I might not be explaining the issue well, it actually has nothing to do with all of the instances LOD’ing at once. As you mentioned, this is what the documentation reflects and is expected behavior.

This issue I’m bringing up has nothing to do with that.

What I’m seeing is that an instanced object does not LOD at _the same screen size_ as a non-instanced object with identical settings.

---

<div class="post-metadata">

**Author:** ![Tim\_Hobson](https://d3kjluh73b9h9o.cloudfront.net/original/4X/2/8/5/28502927f1d97ba1051b3b47ccfe17233bf41ef0.png) [@Tim\_Hobson](https://forums.unrealengine.com/u/Tim_Hobson)\
**Post date:** [November 11, 2014, 10:22pm UTC](https://forums.unrealengine.com/t/instanced-static-meshes-do-not-lod-properly/296391/4 "2014-11-11T22:22:20Z")

</div>

Ah gotcha, Sorry I missed that. I submitted the report for this issue (UE-5327).

Thanks!

Tim

---

<div class="post-metadata">

**Author:** ![Hyperloop](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/hyperloop/32/1203427_2.png) [@Hyperloop](https://forums.unrealengine.com/u/Hyperloop)\
**Post date:** [November 11, 2014, 11:42pm UTC](https://forums.unrealengine.com/t/instanced-static-meshes-do-not-lod-properly/296391/5 "2014-11-11T23:42:47Z")

</div>

No problem!

---

<div class="post-metadata">

**Author:** ![StapledBattery](https://d3kjluh73b9h9o.cloudfront.net/original/4X/2/8/5/28502927f1d97ba1051b3b47ccfe17233bf41ef0.png) [@StapledBattery](https://forums.unrealengine.com/u/StapledBattery)\
**Post date:** [January 27, 2024, 10:35pm UTC](https://forums.unrealengine.com/t/instanced-static-meshes-do-not-lod-properly/296391/6 "2024-01-27T22:35:13Z")

</div>

This issue still exists in 2024, so I’ve created a hacky workaround.

Header file:

```auto
// See https://issues.unrealengine.com/issue/UE-5327
// Unknown whether this works for components created in the level editor.
UCLASS()
class UInstancedStaticMeshComponentWithProperLods : public UInstancedStaticMeshComponent {
	GENERATED_BODY()

	virtual FPrimitiveSceneProxy* CreateSceneProxy() override;

	FStaticMeshRenderData* dupeRenderData = nullptr;
	void freeDupeRenderData();
	virtual ~UInstancedStaticMeshComponentWithProperLods() override { freeDupeRenderData(); }
};

```

cpp file:

```auto
static double vectorSum(FVector vec) {
	return vec.X + vec.Y + vec.Z;
}
class FInstancedStaticMeshSceneProxyWithAccessors : public FInstancedStaticMeshSceneProxy {
public:
	FStaticMeshRenderData* GetRenderData() { return RenderData; }
	void SetRenderData(FStaticMeshRenderData* data) { RenderData = data; }
};

void UInstancedStaticMeshComponentWithProperLods::freeDupeRenderData() {
	if (dupeRenderData != nullptr) {
		free(dupeRenderData);
		dupeRenderData = nullptr;
	}
}
FPrimitiveSceneProxy* UInstancedStaticMeshComponentWithProperLods::CreateSceneProxy() {
	FInstancedStaticMeshSceneProxyWithAccessors* proxy = static_cast<FInstancedStaticMeshSceneProxyWithAccessors*>(Super::CreateSceneProxy());
	if (proxy == nullptr) return proxy;

	FStaticMeshRenderData* origRenderData = proxy->GetRenderData();	

	FVector minScale(0), maxScale(0);
	GetInstancesMinMaxScale(minScale, maxScale);
	double averageScale = (vectorSum(minScale) + vectorSum(maxScale)) / 6;

	double compSize = CalcBounds(GetComponentTransform()).SphereRadius;
	double meshSize = origRenderData->Bounds.SphereRadius;
	double embiggenment = compSize / (meshSize * averageScale);

	// Duplicate the render data, avoiding needing to call the (nonexistent) copy constructor
	freeDupeRenderData();
	dupeRenderData = (FStaticMeshRenderData*) malloc(sizeof(FStaticMeshRenderData));
	memcpy(dupeRenderData, origRenderData, sizeof(FStaticMeshRenderData));

	// We need to do it this way to avoid calling any destructors
	memset(&dupeRenderData->ScreenSize, 0, sizeof(dupeRenderData->ScreenSize));

	for (int i = 0; i < MAX_STATIC_MESH_LODS; ++i) {
		dupeRenderData->ScreenSize[i].Default = origRenderData->ScreenSize[i].GetValue() * embiggenment;
	}

	proxy->SetRenderData(dupeRenderData);

	return proxy;
}

```
