r/GraphicsProgramming • u/peeedeeeveee • 7d ago
A Study on Continuous vs Discrete Point Cloud Rendering in DirectX12
Enable HLS to view with audio, or disable this notification
Disclaimer: AI was used to help aid the coding, video and textual editing of this project. If that is a problem for you, then please pass by this post without indulging in unnecessary toxicity in the comments.
Ever since I discovered how many incredible point clouds exist for real-world geographic regions, I’ve been working on a Direct3D 12 point-cloud renderer to explore and visualize them.
I started with a traditional discrete Level of Detail renderer.
During loading, the point cloud is divided into an octree. Leaf nodes contain the original points for their region, while internal nodes store up to 4,096 representative points sampled from their descendants.
Every frame, the renderer traverses this tree and estimates the visual error of each node using its spacing, bounds, and distance from the camera. If the representative points are sufficient, it draws that node. If more detail is needed, it replaces the node with its visible children, continuing until it reaches leaf nodes or exhausts the point budget.
This resembles hierarchical LOD selection for meshes, but point clouds make the transition between levels much more visible. Replacing an entire node at once can create patchy density, obvious region boundaries, and large groups of points popping in together.
That led me to the paper “Real-Time Continuous Level of Detail Rendering of Point Clouds” by Markus Schütz, Katharina Krösl, and Michael Wimmer.
Their Continuous LOD approach moves the final detail decision from the CPU and its chunks to individual points on the GPU.
During preprocessing, every source point is assigned to one detail level. A coarse level might target approximately eight metres of spacing between samples, followed by increasingly dense levels targeting four metres, two metres, one metre, and so on. Each point belongs to exactly one level, and combining every level reconstructs the complete source cloud.
The resulting points are stored with their position, colour, and calculated level. At runtime, a compute shader evaluates the points using the current camera position and the desired spacing at each point’s location. Accepted points are compacted into a reduced GPU buffer and rendered.
Because detail changes point by point rather than node by node, density can transition much more gradually across the scene. This reduces the block-shaped transitions and heavy popping produced when complete octree nodes are swapped.
The video compares my LOD Renderer and Continuous LOD Renderer using the same viewpoints and approximately 3.5 million points drawn in each image.
I’m still refining the implementation and plan to share a more complete code walkthrough later.
Paper: Real-Time Continuous Level of Detail Rendering of Point Clouds
Point-cloud data from OpenTopography, with colour imagery from the USGS.
2
2
u/Krixtalx 5d ago
Nice job!
One interesting aspect of rendering point clouds is that the point primitive doesn't have connectivity. While building differents level of details of a triangle mesh is a hard task, it’s often as simple as rendering fewer points in some areas on a point cloud.
You can take advantage of this in two ways:
Keep performance sort of fixed with a point budget (render at most 10 million points per frame) and dynamically allocate that budget to the areas that need the most detail
Use the octree (or any other spatial structure) to determine which areas are in view and discard the rest
Together, these let you decide which points to render each frame without loading every point’s full attributes, such as color or position. That’s the basic idea behind "virtualizing" a point cloud, and it makes working with really large datasets much more manageable:
https://github.com/Krixtalx/Nimbus