When I create a 3D scatter plot in Makie some of the points that are “closer” to the camera are plotted behind points that are further from the camera. This can make the plots harder to interpret. Is there a setting or technique to change or improve this behavior?

The below image shows what I mean where some points that are higher on the z-axis and therefore closer to the camera (lighter color)are plotted behind points that are lower down and further from the camera.

Try the following little code. I have added an annotation that points to a specific example and this should be reproducible (although I’m not familiar with the details of seeding the RNG across julia versions/platforms. This was using Julia Version 1.8.5 on Windows).

using CairoMakie, Random
#Seed RNG
Random.seed!(21)
#Create Random Points
x = rand(1000)
y = rand(1000)
z = rand(1000)
#plot aligned along z-axis (higher Z is closer to camera)
fig = Figure()
ax1=Axis3(fig[1, 1], aspect=:data, azimuth = 0,elevation=2pi/4)
scatter!(x,y,z,color = z)
ax1.xlabel = "X"
ax1.ylabel = "Y"
ax1.zlabel = "Z"
#annotate a specific example
text!(1,0.95,1,text="←",color=:red,fontsize=24)
fig

This produces the below plot (in Pluto. Not sure how to pop up a plot viewer or save the figure from the REPL, I’m looking into it). It is a 3D scatter plot that where the camera is aligned with the z-axis. Higher Z is closer to the camera. Points are colored by Z position so we know that a lighter colored point is closer to the camera than a darker colored point. Nonetheless in this example (and indeed if you look a bit I can find several examples for any given seed) there is a darker colored point painted over the top of a lighter colored point.

I believe this is a limitation of the Cairo backend:

CairoMakie as a 2D engine has no concept of z-clipping, therefore its 3D capabilities are quite limited. The z-values of 3D plots will have no effect and will be projected flat onto the canvas. Z-layering is approximated by sorting all plot objects by their z translation value before drawing, after that by parent scene and then insertion order. Therefore, if you want to draw something on top of something else, but it ends up below, try translating it forward via translate!(obj, 0, 0, some_positive_z_value).

In the toy example sorting by z value is pretty easy if it fixes the problem. In the general case where the camera is not aligned with an axis it would be a lot trickier (but not impossible I’m fairly certain).

Well you’d have to specify the axis from which the plots perspective should be, but if you have it the z order should just be the value of the data points projection into the axis right?
I.e.

axis = [1,1,1]
point = [x,y,z]
zorder = point'*axis

And so on.
(Cannot try it out right now but this should do the trick)