Camera movement leads to texture loss

I made a scene with a few blocks stacked on each other (on left) and when I swivel around, I see that the top layer texture in the middle disappears (on right):

How do I solve this?
Note: the red thing in middle is just a cube with alpha set to 0.1, when I have this layer empty, this doesn’t happen.

Am I guessing correctly that there are two objects in that area: one that vanishes at certain angles, and one that holds the transparent red bit that remains?

If so, then the problem might be one of drawing-order with transparent objects.

You see, with ordinary transparency (as opposed to certain modes, like additive blending), the order in which objects are rendered becomes important: If a transparent object is rendered before another transparent object, it blends in whatever lies behind both, and writes to the depth-buffer as usual. But because it wrote to the depth-buffer, it may be that the other transparent object will be culled away (depending on its location), leaving only the first transparent object and the background–much as we see in your screenshot.

Now, Panda tries to deal with this by ordering transparent objects from furthest to closest, I believe. This means that transparent objects that lie behind others will be rendered before those others, thus becoming part of the background when those others are rendered.

This works reasonably well, for the most part, I think.

However, there are some cases in which transparent objects are either very close together, or have bounds that cause them to overlap despite such ordering. In these cases, the engine’s attempts to order the objects might not work, or might not work reliably.

So, how to fix this?

If these objects are intended to be rendered in a specific order, you could perhaps force them to render in that order by placing them into the “fixed” culling-bin, with appropriate draw-order values.

The light brown cube and dark brown border around it is one object:
The red bit is the other object.

I tried distancing the objects along X and Y axis, increasing distance between transparent blocks, but keeping the layers face to face at 0 distance. The problem persists.

I am not yet this experienced to try this solution, but thanks.

As long as the two objects are visually overlapping and one right up against the other, the problem may persist, indeed.

It does seem as though my guess may be correct, then.

I do have a question: Is the brown object supposed to be transparent?

If not, perhaps try turning on transparency-detection (by setting “show-transparency 1” in your prc file). If the brown object flashes, then it’s erroneously been identified as “transparent” (perhaps due to a texture with an alpha channel included), and fixing this may fix your problem.

If it is meant to be transparent, then read on!

That’s fair.

It’s pretty straightforward. You can look to this manual page for details, but the short version is this:

Panda has a number of “bins” that it uses for rendering, going through one bin then the next in a set sequence. Aside from this broad-scale ordering of object-rendering–earlier bins before later–each bin controls what, if any, ordering is used per object.

By default, transparent objects are automatically placed into particular bin, simply labelled “transparent”. It renders after opaque objects, and sorts its objects from furthest to nearest. As a result, opaque objects can appear behind transparent objects, and for many purposes transparent objects render as one might expect.

In your case, however, we want to ensure that the objects render in a specific order: the brown object first, and the red object after (if I have it correctly).

To do this, we put our objects into another bin, the “fixed” bin, which, well, renders things in a fixed order. (And which is also rendered after standard opaque objects.) This is achieved by calling “setBin” on the NodePaths in question, passing in the name of the desired bin (in this case “fixed”), and a draw-order.

Like so:

myNodePath1.setBin("fixed", 0)
myNodePath2.setBin("fixed", 1)

If I recall correctly, lower draw-orders render first, meaning that we would presumably want the brown object to have a lower draw-order than the red object. However, it’s possible that I have that the wrong way around, so if it fails, try swapping their draw-orders!

(If you’re modelling this in Blender 2.7, then I think that you can specify this binning via logic-properties applied to the relevant objects, too.)

The brown object is not supposed to be transparent, enabling show-transparency 1 shows that the brown object flashes. I exported the model from Blender, I haven’t touched the alpha channel at all. The setBin also works, however my red bit is not the same, it is way more transparent from 2 sides (left) and normal from the other 2 sides, but has weird lines (right), excluding top and bottom:

The flashing indicates that the brown object is being treated as transparent, I believe.

Okay, well let’s focus on fixing that instead, then–for one thing, it may have performance implications!

What may well be happening here is that the texture that you’re applying to the model of the brown object (if I’m correct in gathering that you have one there) has an alpha channel. That is, that it’s an RGBA image, not an RGB image. This can result in it being treated as transparent, even if the texture-image doesn’t have any alpha-values less than 1, and so appears entirely opaque, if I recall correctly.

In your image-editor, look for a way to remove the alpha channel from your image.

If I’m not much mistaken, in GIMP this can be done by “flattening” the image–in the menu, select “Image->Flatten Image”, then export the image. (Just be careful to perhaps not save your GIMP “.xcf” file after doing so–you lose all layers in this process!)

(Depending on where you export your image to, you may want to either re-export the model or copy the new image over the old one in the relevant directory of your project.)

Once all has been done, use the “show-transparency” prc-option again to check the brown object–if the process has worked, it should no longer flash!

Ah, it looks like your red object is a little more complex than I had thought–I was under the impression that it was a simple flat rectangle at the front of the brown object! That might indeed complicate binning–although it’s not impossible to get it working, I daresay.

Still, perhaps better to step away from binning and stick to fixing the fact that the brown object is being treated as transparent, as described above–that should be a simpler solution, and as mentioned, may even make the rendering of your scene a little more efficient!

Thanks a lot, saving the texture image as only RGB solved it. It is not treated as transparent also! Question: does this boost performance, saving it as RGB whenever possible?

1 Like

I’m glad that you got it fixed! :slight_smile:

I don’t think that it’s definite that it will boost performance, but it may well.

If I’m not much mistaken:

In short, as I previously noted, objects that Panda considers to be transparent are placed into a bin that renders them from furthest to closest. To that end, it sorts them each frame. Thus, the more objects there are in that bin, the more work the sorting requires.

For a handful of objects, this may not be an issue at all. But for a huge number of objects, it may indeed impact performance.