Studio Matrx Monthly · Volume 1 · Issue 3 · August 2026
Amogh N P
 In loving memory of Amogh N P — Architect · Designer · Visionary 
LODs, Draw Calls & CullingLesson 9.3
RTV for Architecture, Planning & Urban Design/Module 9 · Optimization & Performance

Lesson 9.3 · Optimization & Performance

LODs, Draw Calls & Culling

The classic levers - instance, merge, cull and stream - that claw a heavy building back to frame rate

13 min Interactive lessonFree · open lessonByAmogh N P· Architect & interior designer
The hook

The GPU can draw a hundred million triangles. It struggles with ten thousand separate objects. Optimization is mostly the second problem.

Newcomers assume performance is about triangles. In an archviz scene it is far more often about draw calls - the number of separate objects the CPU has to describe to the GPU each frame. A model imported piece by piece from Revit can be thousands of individual actors, and every one is a phone call from CPU to GPU.

This lesson is the toolbox for the bottleneck the last lesson taught you to diagnose. LODs shed detail with distance, instancing and merging collapse draw calls, culling skips what you cannot see, and texture streaming tames memory. None are exotic - they are the classic levers every real-time artist reaches for, and knowing which one your profile is asking for is the whole craft.

Draw calls first (instance + merge), then cull the unseen, then LOD the far, then stream textures. Always re-measure after ONE change.

Draw calls: the number that usually hurts

A draw call is one instruction from the CPU to the GPU: 'draw this mesh, with this material, at this position.' Each one has fixed overhead on the CPU draw thread regardless of how many triangles it carries. So a scene of ten thousand tiny, individually placed objects can drown the CPU in draw calls while the GPU sits half-idle - the classic CPU-bound-on-Draw signature from stat unit. Reducing draw calls is the highest-value optimization in most archviz scenes.

The first lever is instancing. When the same mesh appears many times - 500 identical chairs, a facade of repeated mullions, a car park of bollards - an Instanced Static Mesh (or Hierarchical Instanced Static Mesh, which adds culling and LODs) lets the CPU describe the mesh once and hand the GPU a list of positions. Five hundred draw calls become one. The pixels on screen are identical; the CPU just stops repeating itself. Unreal will auto-instance identical static meshes in many cases, and the Foliage tool instances by design.

The second lever is merging. Different meshes that will never move - a cluster of fixed props, an architectural assembly - can be combined with Merge Actors into a single mesh with a shared material, turning many draw calls into few. The trade is flexibility: merged geometry moves and culls as one unit, so you merge things that genuinely belong together. A third quiet lever is shared materials - each unique material on a mesh is typically its own draw call, so a mesh with eight materials costs more than one with two. Consolidating materials and using texture atlases pulls the count down. Reach for stat rhi after each of these moves and watch the draw-call number fall - it turns an abstract technique into a figure you can see dropping, which is the fastest way to build an instinct for what each lever is worth.

DRAW CALLS: BEFORE and AFTERBEFORE: 500 chairs placed one by one... x500500 draw callsAFTER: one instanced mesh, 500 transforms... x5001 callSame pixels on screen - the CPU just stops describing the chair 500 times.Instanced Static Mesh, merged actors, and shared materials all pull the draw-call bar down.
Zoom
Instancing collapses draw calls. Five hundred chairs placed one by one cost 500 draw calls; the same 500 as an Instanced Static Mesh cost one call plus a list of transforms. The pixels are identical - the CPU simply stops describing the chair 500 times.

Draw call = one CPU->GPU instruction. 500 chairs placed by hand = 500 calls. One instanced mesh = 1 call. Same pixels.

Culling: do not draw what you cannot see

The cheapest object to render is the one you never draw. Culling is the family of tricks that skips geometry the camera cannot actually see, and Unreal does several kinds automatically - your job is to help them work well.

Frustum culling drops anything outside the camera's field of view - the view frustum, the pyramid of what the lens can see. Look north and the building behind you is not drawn. This is automatic and nearly free. Occlusion culling drops what is inside the frustum but hidden behind something else - the furniture in the next room, blocked by a wall. Unreal computes occlusion each frame, and it works best when big solid occluders (walls, floors, slabs) genuinely block the view; a scene modelled as a hollow shell with gaps lets the engine see - and draw - everything behind it. Distance culling (via a Cull Distance Volume or per-object max-draw-distance) simply stops drawing objects past a set distance, ideal for small clutter that is invisible from far away - you will never see the drawer handles from across the plot, so stop drawing them at thirty metres.

The practical craft: model solid occluders rather than paper-thin hollow shells so occlusion culling has something to work with; set sensible cull distances on small props; and remember that in a wide-open scene with long sightlines, culling helps less, so you lean harder on LODs and instancing. Culling and drawing are two sides of the same budget - every object culled is time handed back to the frame.

THREE KINDS OF CULLINGcameradrawnwalloccludedfrustum-culleddistance-culled (too small / far)Inside the view frustum + not hidden = DRAWNFrustum culling drops what is off-screen; occlusion drops what is hidden behind; distance culling drops the tiny and far.
Zoom
Three kinds of culling from one camera. Frustum culling drops what is off-screen, occlusion culling drops what a solid wall hides, and distance culling drops the tiny and far. Only what is inside the view and not hidden is actually drawn - every object skipped is time handed back to the frame.

Frustum: off-screen. Occlusion: hidden behind. Distance: too far/small. All three = drawing less to draw faster.

LODs: shedding detail the distance hides

For every mesh that is not a Nanite mesh - foliage, translucent surfaces, animated geometry, or anything on the classic path - Levels of Detail remain the workhorse. An LOD chain is a set of progressively simpler versions of a mesh; the engine swaps to a lower one as the object shrinks on screen, because a chair fifty metres away does not need its full triangle count to look right. Unreal can auto-generate LODs from a source mesh, or you can import your own.

The controls that matter are the screen sizes (how small the object must appear before each LOD kicks in) and managing the LOD pop - the visible snap when one level swaps to the next. Set switch distances too aggressively and viewers see geometry visibly simplify; set them too generously and you carry detail you are paying for and cannot see. Dithered transitions soften the pop. For whole clusters of buildings or props, Hierarchical LOD (HLOD) goes further: it merges distant groups of actors into a single low-detail proxy mesh, cutting both triangles and draw calls for far-off parts of a large scene at once.

Getting LODs right is a small craft of its own. Unreal's auto-LOD generation is a fine starting point - you set a number of levels and reduction percentages and let it decimate - but for hero foliage or a signature piece you may import hand-made levels that hold silhouette better. Watch the triangle percentage each level keeps and the screen size at which it activates, and always test by flying the camera the way a viewer actually will: a level that looks fine in a static shot can pop distractingly during a smooth walkthrough. Dithered or temporal transitions blend the swap so the eye never catches it.

Remember the division of labour from earlier in this module: Nanite gives you continuous, automatic LOD for opaque static geometry, so you do not author LOD chains for it. LODs and HLOD are for everything Nanite does not cover, plus for platforms or projects where you are not using Nanite. Knowing which mesh belongs in which system is exactly the judgement this module is building, and it is the difference between an artist who blanket-applies one recipe and one who reaches for the right system per mesh.

LODs = simpler mesh with distance, for non-Nanite geometry. Watch the pop. HLOD merges distant groups (fewer tris AND calls).

Texture streaming and putting the levers together

Geometry is not the only budget. Texture streaming manages video memory (VRAM) by keeping high-resolution textures on disk and loading only the mip level - the resolution - a surface needs at its current on-screen size. A 4K wood texture on a distant floor is streamed in at a low mip; walk up to it and the high mip loads. This keeps VRAM from overflowing, which matters enormously in texture-heavy interiors and doubly in VR, where memory is tight. When you see textures visibly 'pop' from blurry to sharp, or the console warns of a streaming pool over budget, you are watching the streamer work - raise the pool size (r.Streaming.PoolSize) if you have VRAM to spare, or reduce texture resolutions if you do not.

Now put it together as a routine, driven by the profile rather than by habit. If stat unit says CPU-bound on Draw, attack draw calls first: instance the repeated meshes, merge the fixed clusters, consolidate materials, and let HLOD collapse distant groups. If GPU-bound, lean on culling (solid occluders, cull distances), LODs (tighter screen sizes), lighter shadows and translucency, and texture streaming for VRAM. Always change one lever at a time and re-measure with stat unit and stat rhi, watching the draw-call and triangle counts fall. This measured loop - diagnose, apply the matching lever, verify - is how a heavy building that crawled becomes a smooth, walkable experience, and it is the same loop VR will demand at double the intensity in the next lesson.

Texture streaming = load only the mip you need; protects VRAM (critical in VR). Match the lever to the profile; re-measure each change.

Techniques & features you'll meet in this lesson

Instanced Static Mesh

Drawing many copies of one mesh in a single draw call

Describe the mesh once, hand the GPU a list of transforms; the Hierarchical variant adds per-instance culling and LODs. Huge draw-call savings for repeated geometry.

Merge Actors

Combining multiple static meshes into one with a shared material

Turns many draw calls into few for geometry that never moves; trade-off is the merged result moves and culls as a single unit.

Occlusion & frustum culling

Skipping geometry the camera cannot see

Frustum drops off-screen objects, occlusion drops hidden ones; occlusion needs solid occluders (real walls) to work, not hollow shells.

Texture streaming

Loading only the texture resolution a surface currently needs

Keeps VRAM in budget by streaming mip levels; critical in texture-heavy interiors and in VR. Watch the streaming pool warnings.

Hands-on workshop

Workshop - cut the draw calls on a heavy scene

You will take a draw-call-heavy scene, read the baseline with stat rhi, then apply instancing, merging and culling one lever at a time - re-measuring after each - so you see exactly how much each move is worth. This is the profile-driven optimization loop made concrete.

Unreal Engine 5, a draw-call-heavy scene, and the console (backtick) for stat unit and stat rhi. Instancing, Merge Actors and Cull Distance Volumes are all built in.

Given & goal
Goal: measurably reduce draw calls with matched levers
Inputs: Unreal Engine 5 and a scene with many repeated/separate objects (a populated archviz level or your own piece-by-piece import)
Time: ~40 minutes
  1. 1Baseline: type stat unit and stat rhi. Record Frame/Game/Draw/GPU and the draw-call and triangle counts. Confirm from stat unit that you are CPU-bound on Draw (if you are GPU-bound instead, note it - your levers will shift to culling and LODs).
  2. 2Find a mesh repeated many times (chairs, mullions, bollards). Replace the individual placements with an Instanced Static Mesh (or use the Foliage tool). Re-run stat rhi and record how far the draw-call count dropped.
  3. 3Select a cluster of fixed, never-moving meshes and use Merge Actors to combine them, consolidating materials where you can. Re-measure and record the further draw-call reduction.
  4. 4Add a Cull Distance Volume (or set per-object max draw distance) for small clutter, and confirm your big walls are solid occluders so occlusion culling works. Fly the camera and watch stat rhi drop as objects leave view.
  5. 5Compare final stat unit and stat rhi to the baseline. Write down which lever gave the biggest win and why the profile predicted it.

You’ll walk away with
A before/after table of stat rhi draw-call and triangle counts and stat unit ms at each step (baseline, after instancing, after merging, after culling), plus a sentence on which lever was most valuable for this scene and how the profile told you so.

The worked example

Three altitudes on the same idea

Read the band that fits you — or all three.

For the architectImmersive design & client experience

Your biggest performance win usually costs you no visual quality at all: instancing and merging a piece-by-piece BIM import. A Revit model arrives as thousands of separate actors, and collapsing the repeated and fixed elements into instances and merged meshes can slash draw calls without changing a single pixel. Model solid walls and slabs rather than hollow shells, too - occlusion culling can only skip the next room if a real wall is blocking it.

For the interior designerWalkable interiors & material studies

Interiors are draw-call and texture heavy - repeated decor, many materials, high-res finishes - so instancing and texture streaming are your friends. Instance the repeated chairs, books and tiles; consolidate materials where finishes are shared; and let texture streaming keep your 4K fabrics from swamping VRAM. Set cull distances on small clutter the client will never see from across the room, and you reclaim frame rate the eye never misses.

For the studentReal-time skills, portfolio & archviz jobs

These four levers - LODs, instancing/merging, culling, streaming - are the vocabulary of every real-time performance conversation, so learning them makes you fluent. The skill that impresses is not knowing they exist but matching the right one to a profiling read: draw-call problems get instancing and merging, GPU problems get culling and LODs. Practise reading stat unit and reaching for the matching lever, and you will optimize with intent instead of trial and error.

Misconception check

Optimizing a real-time scene is mostly about reducing the polygon count.

Triangles matter, but in a typical archviz scene the object count - and the draw calls it generates - is far more often the real bottleneck. A draw call is one instruction from the CPU to the GPU per mesh-and-material, with fixed overhead regardless of how many triangles it carries, so ten thousand tiny separate objects can bury the CPU while the GPU is barely working. That is why instancing (describing a repeated mesh once and handing the GPU a list of positions) and merging (combining fixed meshes) are usually higher-value than decimating geometry, and why Nanite - which fixes triangle cost - does nothing for draw calls. Culling helps by never drawing what you cannot see, and texture streaming protects memory. Reducing polygon count is one lever among several, and rarely the one your profile is actually asking for. Diagnose with stat unit and stat rhi, then pull the lever the numbers point to.
Try it

Do it yourself

Match each lever to the problem it solves - that is the exam this module sets.

  1. 1What is a draw call, and why can ten thousand tiny objects hurt more than one huge mesh?
  2. 2When would you instance a mesh versus merge actors, and what does each cost you in flexibility?
  3. 3Name the three kinds of culling and, for occlusion, what your model must provide for it to work.
  4. 4For which meshes do you still author LOD chains now that Nanite exists, and what is HLOD for?
  5. 5What does texture streaming protect, and why does it matter even more in VR?
Take this with you

The one line to carry out

Most real-time optimization is cutting draw calls (instance and merge), skipping the unseen (frustum, occlusion and distance culling), shedding distant detail (LODs and HLOD) and streaming textures to protect VRAM - each pulled in response to what the profile, not habit, says.
Take it further
References & further reading

Peer-reviewed journals & authoritative standards

  1. 01Level of detail (computer graphics)Wikipedia, 2026.
  2. 02Back-face cullingWikipedia, 2026.
  3. 03Texture mappingWikipedia, 2026.
  4. 04Unreal Engine 5 DocumentationEpic Games Developer Documentation, 2026.
Related lessons
Recap
In archviz the draw-call count - one CPU-to-GPU instruction per mesh-and-material - is usually the real bottleneck, so instancing repeated meshes and merging fixed ones is the highest-value optimization, above decimating triangles. Culling skips what the camera cannot see: frustum for off-screen, occlusion for hidden (needs solid occluders), distance for far and small. LODs and HLOD shed detail with distance for non-Nanite geometry, and texture streaming loads only the mip a surface needs, protecting VRAM. Match the lever to the stat unit and stat rhi read, change one thing, and re-measure.
Carry forward →

You now have the levers to make a heavy scene run on a desktop. VR raises the bar sharply - two eyes, a higher frame rate, a shorter budget - and it also demands specific hardware. Next we face VR performance and the machine head-on.

A

The author

Amogh N P

Architect, interior designer, and creative polymath. Studio Matrx began in his notebooks — his vision of design made honest, useful, and open to everyone. Its Academy is written and taught in his memory, and free, forever.

More about Amogh →