Background image covering geometry

I have used the following code to add an image that I want to be the background of my scene. However, varying the y value gives no depth to the placement of the image meaning that it is always obscuring my geometry. How can I add this image as an actual background?

    imageObject = OnscreenImage(image='stars.jpg', pos=(0, 10, 0))
    imageObject.setTransparency(TransparencyAttrib.MAlpha)

Thanks

Hmm… I believe that OnscreenImage is by default attached to either “aspect2d” or “render2d” (I forget which, offhand), which I think is rendered after the standard 3D scene-graph. This makes it awkward to render such an object behind objects attached to the 3D scene-graph.

You could perhaps achieve what you want by parenting the OnscreenImage to the 3D camera, scaling it so that it fits the screen, putting it into the “background” culling-bin, and disabling depth-writing for it.

In short:

  • Parenting it to the camera not only moves the image into the standard 3D scene-graph, but also causes it to move with the camera, thus making it to appear to be a static 2D element.
  • Scaling it should, well, make it fit the screen.
  • Putting it in the “background” culling-bin causes it to be rendered before other objects. (Presuming that you have no custom culling-bins below the “background” bin, at least.)
  • And disabling depth-writing prevents it from obscuring other objects, even if it’s technically closer than they are, thus giving the effect of it being “behind” them.

There are a few caveats, however:

For one, I’m not confident that you won’t see some occasional flickering at the edges of the image, as a result of tiny imprecisions in the placement of the edges. If this does happen–it may not–perhaps you could mitigate it by making the image very, very slightly larger than theoretically called for.

And for another, an OnscreenImage handled this way may not respond to screen-resizing as it might if left in its default state. I’m honestly not sure, and testing might be called for to determine whether there’s an issue there!

Simple example-code:

imageObject = OnscreenImage(image='stars.jpg', pos=(0, 10, 0), parent = base.cam, scale = 2)
# Note the inclusion of the "parent" keyword.
# The scale is likely not correct; I leave it to you to find a proper value for it!
imageObject.setBin("background", 0)
imageObject.setDepthWrite(False)

Fantastic, that did the job.

1 Like

Note that OnscreenImage is part of a 2D interface that Is drawn on top of 3D. For 3D, you should use a 3D mesh with a stretched texture, it may also be necessary to turn off the lighting for it.

I imagine that, in the background, OnscreenImage just creates a card and attaches it to the 2D scene-graph, meaning that it likely is exactly what you describe: a simple quad with a texture applied to it. I’m not sure that there’s much difference between rendering on one or the other scene-graph for these purposes. (Well, as perhaps shown by the fact that the suggestion that I gave above does indeed work.)

The problem is that OnscreenImage spoils the aspect ratio of the image, you need additional math to load 1:1. I do not recommend accessing the GUI when working with 3D. Do you remember how puzzled you were about Cardmesh? you need the normals that he didn’t have. So pitfalls may arise here.

Based on the description given here, I doubt that normals will likely be a problem: they seem to want a simple unlit backdrop, for which normals are unlikely to be used.

As to the aspect ratio, it looks like OnscreenImage produces a square image regardless of whether it’s on the 2D scene-graph or the 3D one, so that’s an issue that the original poster would be dealing with either way. And since they haven’t expressed any frustrations with the aspect ratio, I’m inclined to presume that they don’t have an issue there until indicated otherwise.

On top of all that, if they’re altering the window aspect ratio at all (such as by supporting a variety of resolutions), then they may have to deal with altering the size of their backdrop anyway, it seems to me.

(Well, unless they attach it to “render2d”–but that brings us back to the issue of drawing it behind everything else.)

Yes, formally you are right, and your answer covers the question. But I’m talking about the prospects of this approach.

That’s fair–but I think that one can end up worrying about problems that don’t apply to the intended feature, and which may end up thus recommending an approach that’s over-complicated for that feature.

I really appreciate both these ways of approaching the problem. In practice I did want to do what Thaumaturge suggested and very simply add a 2d image as a backdrop to a 3d scene. Thank you both!

1 Like

It’s my pleasure for my part, and I’m glad if I’ve been of help, whether in the above debate or more directly. :slight_smile: