# Transparency limited by rounding issues

7 views (last 30 days)
T A on 3 Aug 2020
Edited: T A on 28 Aug 2020
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.
alphas=[0.001,0.002,0.01,0.1,1]; %transparencies to use, 1=opaque
figure
for cnt1=1:numel(alphas)
%plot 1e5 coincident dots at x=cnt1, y=0, and of transparency alphas(cnt1)
scatter(zeros(1e5,1)+cnt1,zeros(1e5,1),100,'k','markerfacecolor',[0,0.7,0.7],'markeredgecolor',[0,0,0],'markerfacealpha',alphas(cnt1))
hold on
xticklabels{cnt1}=num2str(alphas(cnt1));
end
axis([1,numel(alphas),-1,1])
set(gca,'xtick',1:numel(alphas),'xticklabel',xticklabels,'ytick',[])
xlabel('alpha')
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.
alphas=0.1; %transparency
intervalRepeat=1; %step size for repeats
nRepeat=30; %maximum number of repeats (overlapping dots) to plot
% alphas=0.01; %transparency
% intervalRepeat=10; %step size for repeats
% nRepeat=300; %maximum number of repeats (overlapping dots) to plot
%2d plot
figure
% dockit
for cnt1=1:intervalRepeat:nRepeat
%plot cnt1 coincident dots in 2D at x=cnt1, y=0 and of transparency alphas
scatter(cnt1+zeros(cnt1,1),zeros(cnt1,1),100,'k',...
'markeredgecolor','none','markerfacecolor',[0,0.7,0.7],'markerfacealpha',alphas)
hold on
end
%plot a final opaque dot on the right-hand side
scatter3(cnt1+intervalRepeat,0,1,100,'k',...
'markeredgecolor','none','markerfacecolor',[0,0.7,0.7],'markerfacealpha',1)
grid on
% title('2D')
%3d plot
% figure
% % dockit
for cnt1=1:intervalRepeat:nRepeat
%plot cnt1 coincident dots in 3D at x=cnt1, y=1, z=1:cnt1 and of transparency alphas
scatter3(cnt1+zeros(cnt1,1),zeros(cnt1,1)+1,1:cnt1+zeros(cnt1,1),100,'k',...
'markeredgecolor','none','markerfacecolor',[0,0.7,0.7],'markerfacealpha',alphas)
hold on
end
%plot a final opaque dot on the right-hand side
scatter3(cnt1+intervalRepeat,0+1,1,100,'k',...
'markeredgecolor','none','markerfacecolor',[0,0.7,0.7],'markerfacealpha',1)
xlabel('number of overlapping points')
ylim([-1,2])
set(gca,'ytick',[0,1],'yticklabel',{'2D','3D'})
% grid off
% title('3D')
view(2) %make view angle be the same as that of a 2D plot
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.
T A on 4 Aug 2020
I had, but that's not what it's doing. The only explanation I see for the particular colors produced is the rounding issue. In my (somewhat limited) knowledge of alpha compositing, there's no other reason for the color that is produced. 20 colocated dots with alpha 0.1 shouldn't lead to the same color as 100,000 dots with the same alpha.

T A on 28 Aug 2020
Edited: T A on 28 Aug 2020
I contacted Mathworks support and, after a dialog, they posted this question and answer:
In it, they confirm my suspicion that this is an integer rounding issue and that it is related to lower-level graphics controls. As an independent test, I used a drawing program, Inkscape, to draw a sequence of overlapping semi-transparent dots, just as in this test. It showed the same behavior of converging to the wrong color. The observed numeric color values were different, probably because the background color and alpha were different. Here's a screen shot of it:

R2020a

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!