According to the math of alpha compositing and color blending (also on Wikipedia), no matter the transparency (alpha), a sufficiently large number of overlapping dots of a color should look the same as an opaque dot of the same color. Yet, while attempting to visualize the density of point clouds using point transparency, I found that the color never saturated, no matter how dense the point cloud. Instead, the "final" color reached depended on the alpha of the dots, which it should not. By "final", I mean the color for which adding more dots doesn't change the color. To demonstrate this, in the following example, in each pass through the for loop, I'm plotting a very large number, 100,000, of coincident points of the same color and transparency; each pass is for a different alpha (transparency). The number of coincident points plotted is large enough that the apparent color is constant, i.e. plotting more coincident points doesn't change the apparent color.
Per the first sentence of this post, all the dots in the figure this makes should appear, as an integer RGP triplet, as [0,179,179], but due to the issue, only the opaque dot achieves this color. The apparent colors are, from left to right:
[255,255,255], [128,255,255], [41,221,221], [4,4,183], [0,179,179]
Note the left-most dot is transparent; the transparencies also vary in an incorrect fashion. Via some research and testing, I've found that the exact problem appears to be due to roundoff error in the calculation of color with transparency. Specifically, working with integer colors from 0 to 255, when the change in apparent color due to adding one more dot is smaller than 0.5, adding another dot doesn't change the apparent color. This is a function of the level of transparency used: the higher the transparency, the larger the error in "final" color. It is also affected by the background color. The higher the transparency, the more severe the problem, as the example figure shows.
I'm using the default hardware OpenGL renderer. If I switch to opengl software, the problem worsens. If I switch to painters, it changes marginally. Behavior is consistent across multiple Windows-based machines.
Is this a fundamental limitation of 2D rendering in OpenGL, an issue with Matlab's implementation, or is there some way around it?
Per the discussion in the comments with J. Alex Lee, we can see that in 3D, this does not happen.
xlabel('number of overlapping points')
Although this plots the same thing in 2D and 3D, only the 3D leads to the correct alpha compositing and color blending. If you run the code, you can rotate the view to see the 3D dots.