Jump to content


Photo

Draw order problem


  • Please log in to reply
4 replies to this topic

#1 TheSnidr

TheSnidr

    That guy

  • Global Moderators
  • 2440 posts
  • Version:GM:Studio

Posted 10 August 2012 - 07:16 PM

So I'm casually working on an RTS game, and I suddenly met a problem when it comes to drawing order.
As you are probably familiar with, drawing transparent stuff in GM makes stuff behind it drawn afterwards disappear. This can be both beneficial and annoying. Let me first show you why it's beneficial. When drawing the fog of war, it has two layers - one completely opaque, and one slightly transparent. The opaque one hides areas not yet explored, and the transparent one hides objects that are currently not being observed by any of your units/buildings. As you can see in the following two images:
Standing over here, no objects are visible under the transparent fog of war:
Posted Image
And when moving further in, an enemy base is revealed:
Posted Image

My units are also supposed to be able to move through water. This means that because of the z buffer, the water needs to be drawn after the units to avoid cutting the units in half. And to remove objects under the transparent fog of war, the fog of war will have to be drawn before the objects.
Now comes the tricky part - to prevent the fog of war from cutting away the water, it needs to be drawn after the water is drawn. However, this makes an obvious loop in priorities...
FOW is drawn before units, units are drawn before water, water is drawn before FOW and so on.

Drawing the fog of war before the water yields this undesirable result:
Posted Image

Any smarter people out there? Can anything be done to fix this? I'm afraid I'll have to use d3d_set_zwriteenable(false) when drawing the water. This will make the units not blend with the water though, and make them appear to be hovering above it.
  • 0

#2 Gamer3D

Gamer3D

    Human* me = this;

  • GMC Member
  • 1590 posts
  • Version:GM8.1

Posted 10 August 2012 - 08:28 PM

I think it may be time to use surfaces and draw the water twice.

  • Draw terrain
  • Draw water with z-writing off.
  • Draw fog of war
  • Draw units
  • Draw water with z-writing on. // explained in full later

The obvious problem is that water inside the fog of war will draw over itself twice (except on units). We need a mask for it.

To create the mask, draw a clear background, then draw all units in black. Draw the water as white with draw_set_blend_mode_ext(bm_inv_dest_alpha, bm_zero). Now only the parts of the units below the water are transparent.

Disable the z-buffer, then render the water using a multiplicative inverse blend mode (bm_inv_dest_alpha, bm_zero). This should apply it only to the parts of the units that should be under water.
Re-enable the z-buffer, then draw this surface over the scene using bm_normal blend mode. (Draw it below the FOW to avoid showing shadows of hidden units)

Edited by Gamer3D, 10 August 2012 - 08:29 PM.

  • 1

#3 TheSnidr

TheSnidr

    That guy

  • Global Moderators
  • 2440 posts
  • Version:GM:Studio

Posted 10 August 2012 - 09:06 PM

Thank you for the quick answer! I will try implementing it tomorrow.
I did actually think of a method myself too: Using the transparent FOW I can make two complementary water surfaces, one where the hidden area is cut out and one where the visible area is cut out, and draw one before and one after the FOW. Any thoughts on this?
I'm wondering which method would be faster/more efficient. Yours would require drawing all units twice, but would only need one surface. This one would need two surfaces.
  • 0

#4 Gamer3D

Gamer3D

    Human* me = this;

  • GMC Member
  • 1590 posts
  • Version:GM8.1

Posted 11 August 2012 - 12:08 AM

Thank you for the quick answer! I will try implementing it tomorrow.
I did actually think of a method myself too: Using the transparent FOW I can make two complementary water surfaces, one where the hidden area is cut out and one where the visible area is cut out, and draw one before and one after the FOW. Any thoughts on this?
I'm wondering which method would be faster/more efficient. Yours would require drawing all units twice, but would only need one surface. This one would need two surfaces.

Your method is more efficient, and you can improve it by rendering a single surface with the hidden area cut out (the one drawn after the FOW will be properly culled by it).

Reason for boosted efficiency: My suggestion requires rendering all units (Possibly terrain too, depending on how you render the surface) twice.

So tell me. Why exactly are you using this culling method instead of a different one? Most units will be calculating the visibility of nearby enemies (naively (n^2 - n) / 2 total calculations) anyway (to determine whether to attack), so why not store that data and use it to determine whether to draw them? (Also helps debug visibility calculations once you start using complex structures to improve speed)
  • 1

#5 TheSnidr

TheSnidr

    That guy

  • Global Moderators
  • 2440 posts
  • Version:GM:Studio

Posted 12 August 2012 - 08:59 PM

I use this method because not only units should be hidden, but resources and buildings too. As all resources are part of the same model, and all buildings are part of another one (that is rebuilt every time one is added or removed), I can't hide them individually. I don't store whether or not units are visible, as aggressive units base their actions on the distance to the nearest enemy (which is checked once every few seconds). I'm making this to run as fast as possible, so I have to use some cheaper methods...
I got it working with my method, but thanks for your suggestion nonetheless!
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users