Generate Procedural Mesh

Is this basically doing frustum culling on each section?

It allows you to pre-emptively cull backfacing mesh CPU-side, by creating six VertexFactories for each SceneProxy (+/- X/Y/Z).

In any Minecraft-style cube world like BrickGrid the performance boost is change-your-design-constraints huge. My primary project is more semi-uniform (cubes topped with 5x5 vert heightmaps), but since camera and primary shadowcaster are guaranteed +Z & -Pitch it yields equivalent benefits in practice.

I don’t know whether off-axis geometry would see a benefit from attempting a combinatoric approach, and I’m fairly certain there’s nothing here for marching cubes/isosurface implementations.

The secret sauce is in the VertexFactory, looks like this (just going to paste lightly modified BrickRenderComponent.cpp):


	void Init(const FExampleVertexBuffer& VertexBuffer,const FPrimitiveSceneProxy* InPrimitiveSceneProxy,uint8 InFaceIndex)
	{
		PrimitiveSceneProxy = InPrimitiveSceneProxy;
		FaceIndex = InFaceIndex;

		// Bog-standard VertexFactory Init code here
	}

	// Elsewhere in VertexFactory...
#if UE4_HAS_IMPROVED_MESHBATCH_ELEMENT_VISIBILITY
	virtual uint64 GetStaticBatchElementVisibility(const class FSceneView& View, const struct FMeshBatch* Batch) const override
	{
		return IsStaticBatchVisible(View.ViewMatrices.ViewOrigin,Batch) ? 1 : 0;
	}
	virtual uint64 GetStaticBatchElementShadowVisibility(const class FSceneView& View, const FLightSceneProxy* LightSceneProxy, const struct FMeshBatch* Batch) const override
	{
		return IsStaticBatchVisible(LightSceneProxy->GetPosition(),Batch) ? 1 : 0;
	}
#endif //UE4_HAS_IMPROVED_MESHBATCH_ELEMENT_VISIBILITY

private:
	const FPrimitiveSceneProxy* PrimitiveSceneProxy;
	uint8 FaceIndex;

	bool IsStaticBatchVisible(const FVector4& ViewPosition,const struct FMeshBatch* Batch) const
	{
		const uint8 FaceIndex = Batch->Elements[0].UserIndex;
		const FBox BoundingBox = PrimitiveSceneProxy->GetBounds().GetBox();
		const FVector MinRelativePosition = ViewPosition - BoundingBox.Min * ViewPosition.W;
		const FVector MaxRelativePosition = ViewPosition - BoundingBox.Max * ViewPosition.W;
		switch(FaceIndex)
		{
		case 0:	return MaxRelativePosition.X < 0.0f;
		case 1:	return MinRelativePosition.X > 0.0f;
		case 2:	return MaxRelativePosition.Y < 0.0f;
		case 3:	return MinRelativePosition.Y > 0.0f;
		case 4:	return MaxRelativePosition.Z < 0.0f;
		case 5:	return MinRelativePosition.Z > 0.0f;
		default: return false;
		}
	}

Some other changes for Static relevance and per-facing mesh batching are required SceneProxy-side to support, but it’s pretty straightforward stuff. Ctrl-F “void InitMeshBatch(” and “struct FFaceBatch” in BrickRenderComponent.cpp.

I’m not sure how much work would be required.

The actual code would be a matter of a few hours, but the primary issues I can see would be:

  1. This is specific to static SceneProxies (ProceduralMeshComponent is bDynamicRelevance = true), and
  2. requiring the user to submit sections with an axis-facing enum, or something similar.

The former may introduce complications I’m not aware of (Static works just fine for all of my projects, but I adhere to a fixed world grid), and for the latter I’m not sure how comfortable you are with exposing something so potentially fragile to Blueprint, which was part of the reason I asked.

I’m not actually familiar with that code, would you consider making a pull request that adds support?

I’m honestly more of a Tech Designer, but I’d be happy to take a stab at it once 's pull request is in a Release build, if you think it would be worthwhile in light of the caveats.