[solved] Sorting drawn objects by distance from camera

Hi there,

I am working on a 2.5D engine, which will use 3D models for the environment, and billboards (3D planes with 2D sprites drawn on them) for characters.

My initial problem was that, while the terrain models are opaque, the billboards use alpha blending. So, to be able to correctly draw opaque and alpha blended objects, I followed this article: https://blogs.msdn.microsoft.com/shawnhar/2009/02/18/depth-sorting-alpha-blended-objects/

So basically what I want to do is:

  1. set BlendState.Opaque and DepthStencilState.Default;
  2. draw all the opaque models;
  3. set BlendState.AlphaBlend and DepthStencilState.DepthRead;
  4. draw all the alpha blended billboards according to distance from the camera (farthest to nearest).

The problem I am having right now is with the last point. What I tried to do was creating a list of all the billboards, ordering them according to a distanceFromCamera float, and then drawing them in that order. So I tried using either linq:

            foreach (Billboard b in billboards.OrderByDescending(o => o.distanceFromCamera).ToList())
            {
                b.DrawObject();
            }

or another approach, without linq:

            billboards.Sort((y, x) => x.distanceFromCamera.CompareTo(y.distanceFromCamera));

            foreach (Billboard b in billboards)
            {
                b.DrawObject();
            }

However, for some reason both of those seem to be only sorting the objects once. So, all the objects are drawn in the correct order on launch:

but once they move around, I’m getting issues:

I tested a couple of things, and I know that the distanceFromCamera floats are calculated properly when the objects move around, and the position of the camera changes correctly too. What may I be doing wrong here? Is there a better approach to this?

Why do I always come up with a solution for my own problem right after posting here?

I was calculating the distanceFromCamera float in my Update fuction, when I should have been calculating it inside the Draw function. Calculating it inside the Draw function solved the issue.

You can use the DistanceSquared method which will be faster than the regular one, by saving a squareroot for each frame for each object.

1 Like
6 Likes

Yeah, I think I need to start doing that ;DD

Thanks! I changed my solution to use DistanceSquared following what you wrote. I couldn’t notice any results with the tiny amount of objects I am using now, but I will run some tests just for the heck of it. There seems to be a general consensus that using squared distance is faster.