(solved) Walkbehind issue with DirectX 9

Started by Radiant, Sun 01/09/2013 10:57:05

Previous topic - Next topic

Dave Gilbert

#20
Quote from: Calin Leafshade on Mon 02/09/2013 19:48:13
It sounds to me like a z-sorting issue of some kind and it would make sense that certain drivers resolve z-sorting differently.

One the one hand, that makes sense, but on the other hand... I don't see why I haven't gotten this complaint before. Ten games, all using Direct3D, sold to at least ten thousand people. Even if this only affected a small number of drivers, it seems like this would have come up at least once in one of WEG's games. Either I'm doing something differently when I set up my objects, or I've been very very lucky. It makes me think that there is something specific in the way that those objects are being set up  - in addition to the driver issue - that is causing this problem.

Ali

It occurs to me - how often does a character stand at exactly the same Ypos as a walkbehind? It looks bad if a character passes through a walkbehind, so surely most of the time the walkable area is setup in such a way as that rarely if ever happens? Could that contribute to why lots of us haven't noticed?

Radiant

Yes. This strikes me as typically something that many programmers just intuitively don't do, so it won't happen to them.

Dave Gilbert

That... makes perfect sense! There's no practical reason for the player character to have the same Y position as an object, and be behind that object at the same time. I suppose this would only be a major issue when you have one object in front of the other. If the character is at the Y position of the object in front, the front object will jump behind the object in back. Theoretically, anyway?

Andail

In Ancient Aliens, which, I admit, is the only game I've encountered this bug in - there are some objects on a table. In DirectDraw, they're drawn properly behind the main character when he passes in front of the table.

If I switch to Direct3d and try the same scene, the objects will inexplicably end up in front of the character, and he can walk several pixels up and down (along the Z axis) with the problem persisting, so it's not a matter of just one pixel.


There's plenty of space between the near edge of the table and the bottom of the screen for the character to walk, but he will never end up in front of the objects.

Dave Gilbert

#25
It could be those two objects have the same baseline number? I know that caused a lot of havoc in Puzzle Bots (which I made in Direct3D mode!) and object baselines would often react very unpredictably. I didn't realize what was happening at the time, but I did notice that using different baseline numbers for every object fixed the problem. I've made a habit out of using different baseline numbers for objects ever since, which would explain why this has never happened to me (or - at least - why I never NOTICED it happening to me!).

Khris

I can replicate this.
Interestingly, the mouse cursor text will still properly show "Chet" when hovering over a part of the wallet that should be obscured by the character, so it's a purely graphical issue.

Here's a wild guess: the sorting algorithm used by Direct3D assumes that A.Baseline is always either less or greater than B.Baseline, which makes both objects end up at the end of the sort list and thus drawn in front of everything else.

miguel

When you create a new object, if you don't specify its baseline manually then the object's base becomes the baseline, right?
Working on a RON game!!!!!

Yeppoh

#28
Quote from: Ali on Mon 02/09/2013 20:00:35
It occurs to me - how often does a character stand at exactly the same Ypos as a walkbehind? It looks bad if a character passes through a walkbehind, so surely most of the time the walkable area is setup in such a way as that rarely if ever happens? Could that contribute to why lots of us haven't noticed?

Well, it can happen when we have a background of a field with high weeds for example and we want the characters to go through those weeds. We draw enough layers of objects or walkbehind and the characters can go through the objects/walkbehinds to give the illusion of shuffling through the weeds.
This is one example of a situation where the characters can have a matching y-position with the baselines.

To better illustrate, if an artist/level designer wants to do stuff like this :

Ali

Good example, Nefasto, but I didn't meant to imply this wasn't a problem. I was just trying to work out why so few of us had noticed it. I'm sure the same thing could happen with mist/fog, a waterfall, a forcefield or anything else which a character can walk through.

Yeppoh

It's okay, Ali. I wanted to add this example as a key point to also strengthen your statement.

This kind of examples aren't found very often in AGS games. It takes its share of time and work to create (assets and/or walk-behind masks) and setup in the editor. It can become an hassle, depending. Which is also why few of us noticed the problem with the walk-behinds and all.

DazJ

We now know that it's not hardware-related too as it's still the same with a different card.

Crimson Wizard

#32
The baseline acting weirdly indeed.

I created 4 mutually overlapping room objects with the same overriden baseline.

With DX5 the drawing order of objects is following (from the topmost): 1st, 4th, 3rd, 2nd. (!!!)
With D3D: 4th, 3rd, 2nd, 1st (reverse to object index)

I would not dare to say that DX5 mode is the one that acts properly here... I'd rather say that D3D acts at least consistently.

I am also more than convinced that before fixing anything we must consider what IS the correct behavior.


EDIT: I added character with the same basline to this, and
With DX5: the character overlaps all objects except the 1st, which overlaps the character.
With D3D9: the character overlaps all objects...
It looks like with the DX5 the 1st object in the room has incorrect inconsistent drawing order... I will make same test on other computer to see if the results will stay the same.

Radiant

In this case, it strikes me that D3D has the correct behavior.

However, there is a real bug aside from this inconsistency. Please check the savegame linked below with the build of Heroine's Quest I sent you earlier. The door in this room (object 2) has an Y position of 138 and a baseline of 133. The heroine is standing at Y 151, yet she is displayed underneath the object. This error does not happen if I use winsetup to set the graphics driver to DirectX 5. I would really appreciate it if you could look into this, as it is a very important issue for HQ, and presumably other games.

http://crystalshard.net/test/agssave.000

Crimson Wizard

OK, I'll do.
But I'd really appreciate instructions on how to create such situation in a simple test game (this will be easier to work with). I'll see what happens if I just reconstruct this in a one-room game...

Radiant

I'll likewise try to reconstruct it; this just came up during beta testing (in about two dozen different rooms...)

Radiant

GOTCHA.

The key is in setting the IgnoreWalkbehinds flag of an object. With DirectX 5 an object that ignores walkbehinds is still placed in its normal layer, but ignores walkbehinds. With DirectX 9, an object that ignores walkbehinds is also placed in front of other objects and characters that it should not be in front of.

Crimson Wizard

I found a place in engine where it sets an internal flag only if hardware acceleration is supported.
Disabling that flag makes D3D9 place objects same way as DX5, but screws flipped view frames when character is beyond walk-behind.

Radiant

What would you suggest? Using ignore_walkbehinds, it's technically possible to set three objects/walkbehinds/characters so that A is behind B, B is behind C, and C is behind A. It wouldn't surprise me to learn that hardware-accelerated 3D doesn't support that.

Crimson Wizard

#39
Ok, I found the EXACT piece of code that screwes this.

This is how an object's baseline is fixed for D3D9:
Code: cpp

        if (objs[aa].flags & OBJF_NOWALKBEHINDS) {
            // ignore walk-behinds, do nothing
            if (walkBehindMethod == DrawAsSeparateSprite)
            {
                usebasel += thisroom.height;
            }
        }


This left me is total confusion. The object's baseline is simply modified to be higher than anything.
No wonder characters appear behind.
I commented out the line, and now characters are properly drawn over the objects.

EDIT: Err, okay, I am wrong, now objects fail to overlay walk-behind :(.

SMF spam blocked by CleanTalk