A small depth offset, but a large effect

I’ve encountered a problem in which one object is flickeringly showing through another. See the screenshot below, in which the former is an anomalous black line on the wall, which in turn is the latter:
Screenshot from 2021-04-21 13-35-59

I believe that I have, however, confirmed that the issue seems to be caused by the flickering object having a depth-offset applied to it–which make some sense.

However, the strange thing is that the object in question has a depth offset of only 1, and doesn’t for the most part actually come all that close to the surface through which it’s flickering. o_0

Setting the depth offset to 10 markedly increases the effect, allowing one to see more of the flickering object than just a line.

I’ve tried messing with the near- and far- values for my camera’s lens, thus far to no apparent avail. (And I have confirmed that the settings seemed to have had some effect, as the resultant clipping did change.)

I even tried changing the number of depth-bits used by my main offscreen buffer from 32 to 64, again with no apparent effect. (Although it’s possible that I changed this value in the wrong place.)

It may or may not be worth noting that the flickering object is placed into the “fixed” bin, with a draw-order of 1.

Does anyone know why a depth offset of 1 might be causing so great an effect as this, and what I might do about it?

Managed to find a reference to this config variable after running ConfigVariableManager.getGlobalPtr().listVariables() . I don’t know if it would help your specific case, but it might be worth trying if you haven’t already.

gl-depth-zero-to-one bool
current value = true (from )
default value = 0
Normally, OpenGL uses an NDC coordinate space wherein the Z ranges from -1 to 1. This setting can be used to instead use a range from 0 to 1, matching other graphics APIs. This setting requires OpenGL 4.5, or NVIDIA GeForce 8+ hardware.

I can give it a shot, I suppose!

I’m not sure that I’m using OpenGL 4.5, however–my shaders have been sticking with an older version up until now…

Trying it out, then, it has interesting effects on my shadows… but doesn’t solve the problem here, I’m afraid. :/

Nevertheless, I appreciate the suggestion–thank you for it! :slight_smile:

This may be a stupid question, but perhaps it is possible to simply move the objects further apart?

I could certainly see whether that might help. I don’t know how far I’d have to move the troublesome object, but if it’s within a certain distance then it might be doable.

Sometimes the simpler solutions escape us! ^^;

Thank you for the suggestion–I’ll likely try that out and report back! :slight_smile:

I know I’m late to this, but it looks to be classic z-fighting.

It happens all the time when your z buffer doesn’t have enough precision. Often in big scenes / terrain engines, or extremely small scenes where polys are microscopically close.

Sometimes you can just apply a global scale-up or scale-down to everything in the scene and it works fine. Often the media loaded is the wrong scale, different 3d tools use wildy different scales often.

If you can change the view frustum near/far planes to be closer or further apart that is usually the easiest fix. If media or scene scaling isn’t the option. Some folks modify their shaders to divide the Z component (or multiply, make it logarithmic) to handle extreme cases as in terrain engines or other.

It’s almost certainly z-fighting, indeed.

However, what confuses me is that it’s happening between objects that are not all that close together. :/

This is almost certainly not the case here, I’m afraid. The scene is of a fairly standard scale, and a fairly small extent.

I have already tried that, to no avail, I’m afraid. :/

Something like that really shouldn’t be called for here–there’s no terrain engine running, and the scales are all approximately human, and the objects aren’t extremely close together, etc.

That’s the thing: I’m familiar with z-fighting. It’s just really weird that it’s happening in this specific case.

However, this discussion has prompted one thought, one aspect of the case that might be relevant: The flickering object is essentially flat, and is being seen end-on. There appear to be no real problems when it’s seen face-on.

To explain, let me describe the case in more detail:

In this part of the scene, there is a chamber with a flat end-wall, and in that wall a tunnel. The tunnel is damaged, with a recess and rough stone showing in place of the otherwise-chiselled surface.

That “rough stone” is implemented by placing a copy of the recessed section over the underlying geometry, with a different material and a depth offset. Since it has a depth offset, it renders over the primary surface, giving the effect of a patch that’s different from the rest.

Being just a section of wall-geometry, it naturally has no thickness–and it’s that edge that is showing through the flat wall of the chamber.

Curious!

Now that you mention it, it does look like a polygon edge, not a z buffer error. Latter is usually more grainy. Does it flicker if the camera moves? If so it’s definitely precision related (float errors). If not then probably not precision related (either Z or a float roundoff error)

Quick hack I’d do if it were me - whip up a simple two-plane mesh in Blender, load it, see if it’s the same error. If so then you know it’s precision related (Z or float errors). If not, then it’s an error in media - meaning some vertices need to be moved.

It does indeed. (In fact, it took a bit of manoeuvring to get a screenshot that showed quite as much of it as is shown above.)

That might be worth trying (alongside rdb’s suggestion, which I haven’t yet tried), I think. Thank you for the suggestion! :slight_smile:

Okay, I just tried this, and it does help–but only a little. If I move the troublesome object about one unit away from the wall in question, I see less flickering–but still some.

Likewise, I just tried this in my little test-level.

There, the problem does indeed still show up. Specifically, a little more testing showed that it seemed to occur whenever I had a positive depth-offset applied. When no depth-offset was present, or when the depth-offset was set to zero, the issue did not seem to appear.

And again, this happened with planes separated from each other by what I would think would be more than a single depth-value. :/

I note that with a depth-offset of one, despite moving around a bit in these tests, I only ever seem to see a single-pixel edge of the troublesome object–even when it might be possible to see more. Increasing the depth-offset increases the amount shown.

Here’s a pair of screenshots illustrating what I’m seeing.

This first shows the scene in Blender. Note that this is set near the origin, and note the built-in ruler-tool showing the approximate distance between the “wall” (orange and horizontal), and the troublesome planes (black and vertical just above the “wall”).
Screenshot from 2021-04-27 11-46-21

This second shows the results, along with the depth-offsets applied.

With the troublesome plane that has a depth-offset of one-hundred, I note that moving back and forth significantly changes the amount of the plane that is shown: the closer I am to the “wall”, the less of the plane is visible. This seems to correlate with the issue being a depth-buffer precision matter…

Interestingly, I’ve just noticed that the troublesome planes seem to be shadowed as expected–that is, the parts that anomalously show through the “wall” are shadowed as though they were behind the “wall” (which they are).

I’m wondering whether this could be some issue in my buffer-setup, or something like that…

Could I ask why you have a depth offset applied in the first place?

Are the polygons touching? They look like they are, in the picture, but it may be just an illusion.

What are the near/far values of the camera lens? A too-close near value can have a disastrous effect on depth buffer precision.

In the original application–as opposed to the test-case above–the troublesome surface is a “decal” of sorts laid on top of another surface. (Specifically, an area of damaged stone laid atop an area of neatly-chiselled stone.) Since they’re so close together, I applied a depth offset–ironically in order to prevent depth-fighting!

I don’t believe so, no. In the first test-case screenshot in my most recent post above, look at the solid vertical lines–those are the planes that are being seen “through” the “wall”, which in turn is the solid orange horizontal line. The dotted lines indicate parentage, I believe.

At the bottom-left of that same screenshot, note the solid vertical white line and the number overlaid on it–that’s a ruler provided by Blender, and indicates–if I used it correctly–the approximate distance between the troublesome planes and the “wall”.

I believe that my near-value is 0.03. My far-value I’m not setting directly, but based on a call to “getFar()”, it seems to be 100 000.

Indeed, but too-far a near value can cause problems in first-person games. :/

That said, I have tried messing with these values, including increasing the near-value, but thus far to no avail.

Indeed, running a few quick tests now, setting the near-value to “1” may possibly made the effect a tiny bit less prominent for higher depth-offsets, but didn’t remove it for any non-zero depth-offsets, that I found. Similarly calling “setNearFar(1, 100)”.:/

Looks like its definitely z-buffer related, so no fudging of vertices would help.

Going back to the original issue - it looks like you only want to fudge the ‘depth offset’ to render the decal on the wall correct? Can you add the depth-offset change only on the state for scene node of the actual decal? The rest of the scene seems it should have the setting disabled as it looks to make problems.

Alternatively - you could set up walls for multitexturing, the damage texture has full alpha when wall is full-health, and as you damage the wall the damage texture shows via decreasing the alpha val, or you could have multiple damage textures, etc.

Just ideas, hope it helps.

Hmm… I’m not sure, to be honest. I’m only setting the offset on the actual troublesome object itself–but as I understand it, that offset applies to the object’s output into the depth-buffer, meaning that it will have an effect when compared with other objects regardless.

That said, I may be mistaken, and stand to be corrected!

Indeed, and I do have some shaders that handle such, but I’m hesitant to over-use them as they incur additional texture-lookups for every fragment. (At least with the method that I know by which to implement them, and avoiding branching in my shaders.)

(I don’t have a shader that does this specifically right now, but it would be easy to build from my extant shaders, I do believe.)

It’s a thought, however. I’ll note it in my mind for now, I think.

The ideas are appreciated–thank you for them! :slight_smile:

Yeah, I’m just making some silly guesses here, in the sense - assume the wall and the decal are two separate objects, using the depthoffset on ‘just’ the decal might have a difference, but it looks like you already tried this.

The other ‘hack’ I’ve seen in the past:

  • Render the behind-object with just depth-test, not depth-write
  • Render the decal with depth write & test
  • Render the behind-object with only depth /write/

Of course doing the same in a shader is possible, but just ideas for quick hacks if your scene has very few of these decals.

Best of luck!!!

Maybe you should make a sample mesh so you can download it and see it.

I was about to suggest that you make a snapshot of the scene in question using writeBamFile and send it so I can take a look at it.

If they are not even close to touching, but the depth offset is making it show through, that’s certainly odd and I’d wonder why.

If they are touching, then it is an expected effect, and should be fixed in the modelling program (walls cannot be infinitely thin anyway).

Hmm… At least as I’m modelling this in my head, I’m not sure that that would work.

I think that I’ll do something like that, indeed.

I don’t think that “writeBamFile” is needed–the test-case above is just arbitrary geometry that I put together for testing purposes, not the actual wall and its decal, so this hasn’t proven difficult to reproduce.

Here below is a model that, on my machine at least, displays the problem when depth-offsets are applied.
depthTest.egg (3.1 KB)

And here below is a short test-program that loads it and applies the relevant depth-offsets; it uses tags set in the model to do this.

from direct.showbase.ShowBase import ShowBase

class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        self.accept("escape", base.userExit)

        self.setFrameRateMeter(True)

        self.mew = loader.loadModel("depthTest")

        collection = self.mew.findAllMatches("**/=depthOffset")
        for np in collection:
            offset = int(float(np.getTag("depthOffset")))
            np.setDepthOffset(offset)

        self.mew.reparentTo(render)
        self.mew.setY(4)


app = Game()
app.run()

(You may have to zoom out and rotate the view around in order to see the issue. Note that I’ve left the default camera-controller in place, allowing one to do this.)

And finally, here below is a screenshot showing output of the program on my machine.

I confirm that there is such a strange error. I can see it too.

However, the offset is five units, since converted to INT.
Ah, I realized that this was done to enhance the effect, and I also observe with the unit.

I don’t know whether to be relieved that it’s not just on my end–and not my game-specific code–and sad that it affects others! XD;

Either way, thank you for confirming it!

Indeed: I wanted to be confident that the effect would be fairly easy to spot, and that it would turn up even in default-rendering conditions, I think.