[Solved] Rendering an object at an Infinite Distance

So, I’m building a skybox with a dynamic day-night cycle. One thing I wanted to do was add a sun to the background that moves around as day and night progress. What I need to do is to get the sun geometry to be placed infinitely far away from the player (so that the player can’t reach it), but still visible. Obviously, traditional rendering won’t work. I was thinking about using a viewport with an orthogonal camera, but this is

  1. Somewhat inelegant
  2. Doesn’t work in practice. The preViewports don’t seem to want to show up if I’m rendering in the post-viewport, and I can’t seem to figure out how to re-order main view ports.

Do you all have any advice as to how to accomplish this?

1 Like

if im not wrong, you can just use:

Bucket.Sky

this will render everything behind scene (even when close)

i have not yet written my own sky system so im not sure i can give good advise
however i am quite familiar with how jme renders stuff so here are some notes:

viewports have clear flags, so when for example clearing color is set to true, the color attachment of the framebuffer of this viewport will get cleared before the scenes of the viewport are rendered onto it

viewports can have framebuffers set, so if you have 2 viewports with the same framebuffer (note: a framebuffer of “null” indicates the default framebuffer aka the actual window you see) rendering the second viewports will clear everything that was drawn during rendering the first viewports scenes
(have a look at the initCamera() method of LegacyApplication.java for example, it sets up the “guiViewPort” to render to the same framebuffer as the “viewPort” and consequently sets the clear flags to false)

there is different buckets, you probably know Opaque and Transparent Bucket, but there is one for sky as well, which is rendered after the opaque objects but before the transparent ones (so depth testing will safe the fragment shader from running for any fragment that was covered by a geometry in the opaque bucket) and most notably forces a depth range of 1f - 1f so everything in the sky bucket will always be rendered at the far plane basically

i guess other advises would be specific to what you really want, like clouds for example that could potentially occlude the sun, how you want to do lighting like fade the whole sky to black over night, which is not really related to drawing a sun onto the screen, how willing you are to go that route instead of using ready-to-use solutions, because those solutions exist

2 Likes

By the way, are you aware of SkyControl?

It has a day/night cycle, stars, multiple cloud layers, auto-update viewport and ambient light colors,…

Also, you can change the default sun and moon textures to your custom textures.

It’s really cool :slightly_smiling_face:

4 Likes

SkyControl simulates an infinitely distant sky by translating all the sky geometries to match the camera position.

1 Like

And here I was, spending all afternoon building my own shaders. This library seems rather complex, but once I figure it out, it should do exactly what I need. Thanks!

That idea did occur to me as well, but I was wondering if there was a better way of doing it.

2 Likes

If this is intended use, then I think Bucket.Sky is not working properly.

A while back, I wanted to make it so that the waterfalls in the distance always render, and not get culled when the camera is too far away. I thought Bucket.Sky should work based on my research, but if i recall correctly it did not work when I tried it

So I am interested in the solution to this topic as well :slightly_smiling_face:

I think buckets have to do with rendering order, not culling.

The best way to disable culling is to set the spatial’s cull hint using spatial.setCullHint(Spatial.CullHint.Never);

1 Like

I just tried this again to double check, and it appears that CullHint.Never does not have an effect on culling distance. Even when I set the waterfall’s geometry to CullHint.Never, parts of the geometry still begin to disappear when the camera moves past the view distance.

1 Like

@yaRnMcDonuts CullHint is one thing, but there is also camera frustrum near and FAR, while camera FAR is causing probably that it disappear.

For waterfall you should not use Bucket.Sky, because it just change render order, but still terrain/etc will overrender it.

For you it should be just camera FAR to set it more higher value or use lower world scale.

This would also affect all of the other world objects, and would reduce the FPS. In my game I also let the player adjust the frustrum far in the settings so it can be played on a wide range of devices.

I am talking about a situation like the OP mentioned, where I want a single geometry to not be culled at a distance further than frustrum far - or to achieve something else that atleast resembles these results.

1 Like

Impossible as written. Frustum far is the limit the GPU is using to render things. z is transformed to a value between 0 and 1 where 0 is near plane and 1 is the far plane anything outside of that is clipped in the GPU.

If you want to render something “outside the far plane” then you have to do some trick so that it is not “outside the far plane”. Either render it in a different viewport layer or put it in the sky bucket and have it flattened (with no z-buffering to sort its own geometry) at 1.0/far plane. Other some other shader tricks similar to the sky bucket.

…or some combination of all three.

But to render a Sky and the objects in it… which is what OP i trying to do… put it in the sky bucket and setIgnoreTransform(true) on it so it ‘moves’ with the camera. (Edit: and set cull hint to never so that regular JME culling doesn’t cull it.)

3 Likes

My original plan was to just get a “skybox effect” with certain objects, where not only would they render behind everything else (which is what the Sky bucket does), but also they wouldn’t appear to move, thus appearing to be at infinite distance where parallax goes to the maximum.

To be fair, this solution does accomplish that second goal fairly well, but I had a hunch that there was a rendering method built into the engine to handle it automatically. Based on the discussion so far, though, I likely was mistaken.

That’s supposed to be what:

…is supposed to do.

This is why SkyFactory does:

1 Like

I probably spent over an hour browsing through that code over the past couple of days, yet I never saw that one.


Thanks @pspeed. If I ever need to add waterfalls or the Eye of Cthulu to my background, I’ll keep that in mind.

Just a note: the pointer setIgnoreTransform() and the pointer to the SkyFactory code are not connected thoughts.

In fact, I thought it was strange that SkyFactory is NOT calling setIgnoreTransform()… and I half remember that sgold had some problems with setIgnoreTransform() and so opted a different solution.

Note also: for a lot of games, the camera does not move in x,z and the scene moves around it (like in 99% of my terrain based games) and in the case the sky already moves with the camera. :slight_smile:

And just to round things out, for straight up math-based atmospheric effects I have my SimFX library:

attach a sky state, attach a lighting state… and get sky + sun.

Also with the ability to have atmospheric effects applied to regular Lighting.j3md style objects (graying/bluing with distance, etc.)

It’s what’s used in the sky for pretty much all of my recent demo videos, for example:

Edit: shortened integration example:

public class Main extends SimpleApplication {

    static Logger log = LoggerFactory.getLogger(Main.class);

    public static void main( String... args ) throws Exception {

        Main main = new Main();
        AppSettings settings = new AppSettings(true);

        // Set some defaults that will get overwritten if
        // there were previously saved settings from the last time the user
        // ran.
        settings.setWidth(1280);
        settings.setHeight(720);
        settings.setVSync(true);

        settings.load("MOSS-Phys Demo");
        settings.setTitle("MOSS-Phys Demo");

        settings.setUseJoysticks(true);

        main.setSettings(settings);

        main.start();
    }

    public Main() {
        super(new StatsAppState(), new DebugKeysAppState(), new BasicProfilerState(false),
              new DebugHudState(),
              new MemoryDebugState(),
              new LightingState(),
              new SkyState(true),
              ....
              new ScreenshotAppState("", System.currentTimeMillis()));
    }

    public void simpleInitApp() {

        setPauseOnLostFocus(false);
        setDisplayFps(false);
        setDisplayStatView(false);

        ....

        SkyState sky = stateManager.getState(SkyState.class);
        sky.getGroundColor().set(0.3f, 0.5f, 0.1f, 1);

        // Set the time of day
        LightingState lighting = stateManager.getState(LightingState.class);        
        float timeOfDay = 0.2f;
        lighting.setTimeOfDay(timeOfDay);
        lighting.setSunColor(ColorRGBA.White.mult(1.75f));       

        ....
    }
}    

Key parts are the app states on the super constructor and in simpleInitApp() configuring settings other than the defaults.

2 Likes

it appears that CullHint.Never does not have an effect on culling distance. Even when I set the waterfall’s geometry to CullHint.Never, parts of the geometry still begin to disappear when the camera moves past the view distance.

I’m not very knowledgeable about graphics, but I think the phenomenon you reported is “clipping” not “culling”. Culling is an optimization that happens at the Geometry level. Clipping happens in the renderer, at the level of individual triangles or edges.

2 Likes