0
\$\begingroup\$

Sorry if this question doesn't make sense, I'm still very new to WebGL / OpenGL.

Basically, I'm trying to draw a tilemap similar to the one in Stardew Valley. Here's a screenshot from that game: https://i.imgur.com/eEgWu6b.png

So, there are several tile layers that are drawn after one another to simulate depth. And I believe that when two objects are on the same layer, their draw order is based on their Y coordinate. For example, in this screenshot notice how if you are above the scarecrow, you'll be drawn behind it, and otherwise, in front of it.

I'm trying to figure out how to efficiently do this, and there seem to be two main ways:

  1. Use z-buffering in OpenGL. That is, the map is drawn "3d" like in the following image: https://i.imgur.com/Bi8C8z2.jpg where quad has a z value. Then, assuming the camera only translates and never rotates and just always looks top-down, then it should still look like a proper top-down 2D game with depth.

  2. Use the painter's algorithm. That is, first draw everything on the first layer, then everything on the second layer, then everything on the third layer, etc. Your main application code should sort all objects on the same layer based on their Y coordinate so that everything is drawn with the proper depth.

So, I actually really like the idea of the first one. Because I heard that texture swapping was really expensive in OpenGL, and some of my maps are very large so they use 3-5 sprite sheets to draw everything. So with this method, I believe I should be able to just first draw every sprite that uses my first spritesheet, swap to the next texture, draw all sprites that use that texture, etc. Since they have z values, everything can be drawn out-of-order and still be layered properly, right? Also, if I space out the z coordinate for my layers enough, I think I should be able to incorporate the sprite's y coordinate into their z coordinate. That is, as an example, for a 2x2 map, the first layer would have z values 10000, 10001, 10002, 10003, then the next layer will have z values 20000, 20001, 20002, 20003, etc. My only concern is that I heard depth testing and occluding and whatnot can be expensive. And also apparently something called z-fighting can occur?

I think the painter's algorithm is the more traditional way of doing this? My only concern with this one is that it seems like it could be expensive to use software sorting on all the sprites each frame. Also, I don't know how to handle this with texture swapping. If one layer happens to include monsters that are all from different sprite sheets, won't that include a lot of texture swapping when rendering them all out, if we have to do them in order from top left to bottom right?

I'm just not sure which of these I should do. Using the z index sounds like it could make everything a lot easier, but I'm not sure if the price of depth testing is cheaper than software sorting and texture swapping. Also, I'm concerned about possible z fighting. How do people normally do this?

\$\endgroup\$
6
  • \$\begingroup\$ Both of these can work. I wouldn't worry much about expense - modern devices can handle games much more graphically intensive than Stardew Valley. I'd advise jumping in and trying it the way you find appealing. And if you have trouble making it work as desired / with desired performance, then you can come here and ask for help solving that specific problem. \$\endgroup\$ – DMGregory Feb 26 at 16:00
  • \$\begingroup\$ Which one is better though? If you had to make it, which would you choose? There must be best practices for this sort of thing since it's extremely common. \$\endgroup\$ – Ryan Peschel Feb 26 at 16:07
  • 1
    \$\begingroup\$ There are successful games that solve this each of the two ways. "There must be one solution I'm supposed to use" is one of the most common beginner misconceptions we have to shoot down here. Very often, there are reasons to use one sometimes and the other other times. For instance, if you want translucency, Z-buffering won't handle that out of the box, and you need to draw back-to-front. If you want sprites that cover a range of depths, Z-buffering can do that in one pass whereas painter's algorithm would need to split it into layers. Different games = different needs = different solutions. \$\endgroup\$ – DMGregory Feb 26 at 16:23
  • 1
    \$\begingroup\$ Really the word "better" or "best" is very situational. \$\endgroup\$ – Almo Feb 26 at 16:29
  • \$\begingroup\$ I think if there are enough constraints then "better" should become more and more apparent. Apparently I didn't have enough in the post, as I was not aware of this alpha issue. Okay, assuming that eventually I may need to have alpha blending, is the painter's algorithm superior? Or is it still not enough constraints? If so, what other variables inform the decision? \$\endgroup\$ – Ryan Peschel Feb 26 at 16:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.