2026-02-16--point-cloud

it is often a bit of a rollercoaster ride: sometimes i am REALLY happy with the performance of the Umfeld renderer and sometime it is VERY disappointingly slow. in particular when working on particle system ;) so i thought that this is a good reason to look into this one OpenGL-based optimization strategy that i always wanted to look into: geometry instancing.

the basic idea is that there is a base mesh residing on the graphics card (GPU) and the application running on the computer’s processor (CPU) just requests to render copies of it. these copies can even be requested in huge batches reducing A LOT of CPU-GPU interaction; thus it becomes totally feasable to render huge clouds of shapes.

Point Clouds

the first thing i did was to introduce a way to render points. i used a technique where the base mesh for a point is a screen-aligned square, comprised of two triangles. the dedicated shader can render this geometry either 1. as filled squares, 2. as textured squares ( in the screen shots it is a PNG with a cross ), or 3. as filled circles ( by discarding pixels of the square based on a radius ). that last technique is surprisingly fast ( despite the distance calculation ) and can even improve performance in use cases where the fill rate is the limiter ( i.e the bottleneck is the amount of pixel drawn in contrast to the amount geometry ).

2026-02-16--point-cloud-square

2026-02-16--point-cloud-textured

2026-02-16--point-cloud-circular

the implementation is still a bit … raw. i intend to weave this better into the core render engine at some point but until then it can be used in applications when rendering huge amounts of points.

i also reduced the amount of properties of a point to a bare minimum to save bandwith. each instance of a point has the following properties:

struct Point {  
    glm::vec3 position;  
    float     size;  
    float     rotation; // screen-aligned rotation  
    glm::vec4 color;    // normalized RGBA  
};

in the animation above you can see how we can render HUGE point clouds of more than one million shapes on a MacBook Pro (M3). the point properties can be updated per frame without compromising the frame rate too much … that came as a BIG surprise to me.

the best part, however, is that this technique is compliant with OpenGL 3.3 and OpenGL ES 3.0 ( i.e should also work on Small Devices … not tested though ).

see point-cloud example

Instance Clouds

2026-02-16--instance-cloud

after having implemented the point cloud, i thought it would be nice to make this a bit more generic and create a variation where the base mesh can be defined by the operator. in the example above i have used a box ( with uniform texture coordinates for each similar side ) but much more complex geometry is totally possible as well.

a generic instance has a few more properties than in a point instance:

struct Instance {  
    glm::vec3 position;  
    glm::vec3 scale;    // XYZ scale  
    glm::vec3 rotation; // XYZ Euler rotation (radians)  
    glm::vec4 color;    // normalized RGBA  
};

see instance-cloud example.

Caveats

one thing that is somewhat intrinsic to this technique is that the geometry is not depth-sorted. this is no problem when depth testing is enabled with instance_cloud.draw(g, enable_depth_test);. however, in some scenarios, e.g when using textures with an alpha channel while at the same time disabling depth testing ( which is required e.g when rendering a cube to avoid self-occulusion ) can cause strange visual artifacts. again, this is intrinsic to the technique but also one of those HUGE issues with computer graphics in general … this has been discussed A LOT.

currently base mesh data can only be set once in instance_cloud.init(g, base_mesh, num_instances); and then not be replaced.

another things that is not working ATM, neither for points nor for generic instances, is lighting. i would need to add lighting to the instance shaders … maybe some day i will.