Implementing two skies

I’m looking for a way to achieve a specific effect, and am hoping that someone will have a suggestion for me:

In a game level that I’m working with, I have an open-topped building, and I want to have the sky as seen through the open roof of the building to be different to the sky as seen from outside. I don’t think that simply switching the sky-texture is likely to work: it should be possible to look through a window and see the “normal” sky. Similarly, a simple flat model placed at the top of the building is hindered by the fact that the building has an uneven top: a flat model placed at the very top would be visible from the outside along certain lines of sight, while placing it lower would presumably cause it to occlude parts of the building.

The best idea that I have at the moment is to place a flat model below the top of the model, as mentioned previously, and then to cause it to render only when the depth buffer is still set to the buffer’s “clear” value, but to write to the depth buffer as usual, with the “normal” sky being rendered after it and with depth-testing active. However, I don’t see a way of implementing this.

So, does anyone see either a way of implementing my idea in the last paragraph above, or another way of doing what I’m trying to achieve?

Placing it lower would work just fine, you’d just have to make sure to disable depth write for it, by calling setDepthWrite(False). You also have to make sure that it is rendered before the building is, for instance by putting it in the “background” bin (and possibly disabling depth testing). This should prevent it from occluding parts of the building.

Of course, you’d need some way of insuring that the sky texture moves with the camera, so that it still gives the impression of being infinitely far away. This can be done using automatic texture coordinate generation, for instance, or a UV offset using setTexPos.

Failing that, if it gets more complicated, you will have to use the stencil buffer and use stencil testing. That’s the sort of thing it was created for, after all. For instance, you could render the “normal” sky first, then render the open roof as a mesh with color and depth write disabled but writing 1 to the stencil buffer, and then rendering the other sky in front of everything but under the stencil test condition that the stencil buffer contains 1.

Ah, that’s pretty clever. One possible implementation of your general idea might be done with the following render sequence:
(1) Render the open-roof skybox, behind everything else, with both depth write and depth test off.
(2) Render a mesh that covers the open roof, with color write and depth test off, but depth write on. The mesh is single-sided and as such only visible from inside.
(3) Render the “normal” skybox, with depth test on. This will render the skybox everywhere except where you drew the invisible mesh into the depth buffer.
(4) Render the rest of the scene in front.

This is a bit similar to the stencil test idea, except that it uses the depth buffer to “mask” out where the ceiling is. Effectively, it punches a hole inside the “normal” skybox, behind which your special skybox is shown.

You can put 1-3 in the “background” bin. Since “background” is a fixed-sort bin, you can specify the order in which they render using the second parameter to setBin.

Aah, I feel really silly for not having thought of that! A quick test indicates that it seems to work well. Thank you! :slight_smile:

Oh yes, I had that in mind already (although I forgot to mention it ^^; )–if I’m not much mistaken, it should call for a texture offset in order to correctly position the sky-image, and a texture scaling to account for the player being able to move up and down (thus correcting for the player managing to get closer to the “sky”).

Ah, right–I suppose that I tend to shy away from the stencil buffer, simply because I’m not familiar with it, which is perhaps a poor habit. ^^;

Thank you. :slight_smile:

Without having tried it, it looks as though what you describe should work (although the covering mesh might take some finesse in order to ensure that a section that covers a high wall isn’t visible from a side with a lower wall). For now, however, I’m content to stick with the simpler option that you at first recommended, but this other idea might be worth keeping in mind as a backup plan.