• 3D
  • How to simulate very far away objects? (camea far clipping distance)

I'd like to simulate an extremely far away object (the sun) I don't want the player to be able to approach the sun, but I want it to look large (like the size in the screenshot below).

I've tried various combinations of increasing the initial distance from the player and increasing the scale, but i run into issues with camera far clipping distance which is capped at 10,000. Even with various combinations of scale and distance I can't seem to get an appropriate result without it getting culled.

I've tried placing the object closer to the player to get the correct size, and then moving it in the opposite direction of the player so it always maintains the same distance. But obviously then the sun starts colliding with objects that are actually close to the player (like the asteroids)

My initial thoughts around this whole thing was to render two cameras, one with just the stationy sun on, and then the actual camera the player sees through on top. But i can't find any way of rendering 2 stacked cameras in Godot?

Any help is massively appreciated!

Note: I don't want to add it to the Skybox as I want it to spin and to add particle effects (like a corona and atmosphere)

I have not tested this myself, but I think you can achieve something like this by using two viewports, where one viewport renders the space "background", and another renders the player/world scene.

In your "background" Viewport you place the scene you want to render and all of the objects you want to be in the background, like the sun. It will need own world enabled so the nodes don't interfere with the player/world. You'll also want a WorldEnvironment node with the space skybox in the background scene. Finally, you'll probably want to write a script that syncs the rotation of the "background" Viewport Camera node with the player/world scene Camera, so as the player rotates the view of the background changes.

Then in the world/player scene, you'll want to create a WorldEnvironment with the background set to Canvas. Then make a TextureRect node that uses a the "background" Viewport texture. This should make the background of the world/player scene be what the "background" Viewport sees. To make it where other Control/UI nodes are not drawn on the background, just set the Max layer (or whatever it is called) on the WorldEnvironment background to something like 1 and then place all of the Control/UI nodes on a CanvasLayer with the layer set to 2.


Another thing you could try is a similar dual Viewport setup, but instead of using a WorldEnvironment node, write a simple shader instead. For this to work, I think you'll need to enable transparent bg on the root viewport. Then you just need to have a TextureRect node that takes the "background" Viewport texture and the SCREEN_TEXTURE, and overlays them together.


That is what I would try. I'm not sure how feasible either idea is, nor how easy they would be to implement, but that is what I would try. Using two Viewport nodes function similar to how Valve's 3D skyboxes work in the Source engine. If you want, I can see if I can make a quick prototype once I have the time.

@TwistedTwigleg thank you so much for the detailed response! Your viewport suggestion is effectively the method I was thinking of with dual cameras, I wasn't sure how to achieve this though, so I'm very keen to give that a shot!

If you have time, a prototype would be hugely useful.

I'll also spend some time today trying to implement this.

Thank you again =)

I figured it out! Most of what I wrote above worked like expected, with the only differences being in how the "background" scene is displayed.

Using the canvas as a background idea didn't quite pan out, as the Viewport would need to render the scene at 360 degrees, which isn't currently possible in Godot. Thinking about it though, rendering the scene this way wouldn't have been as good for performance anyway, as the majority of the background/skybox scene wouldn't be visible.

However, using a TextureRect node, I was able to write a simple shader that mixes the 3D skybox with the main scene. After a little tweaking, I even got it working with transparency B)

Please excuse the terrible visuals, I just needed something for testing quickly :sweat_smile:

There are probably a few things that need adjusting here and there, and I didn't document anything due to time constraints. Here is a link to the project on my Google Drive.

@TwistedTwigleg That is exactly what I need! I really appreciate you taking the time to put this demo together for me. I'll have a play around and let you know when I get it working in my own project. =)

@TwistedTwigleg it worked perfectly! You're a legend, thank you so much! Would you mind me putting together a video tutorial for this technique? I would of course credit your work.

@codewithtom Great! I'm glad it is working! As for the video tutorial, I have no issues with it. Feel free to make a tutorial covering the technique :)

7 months later

@codewithtom You said that you said some thing about making a tutorial about how to do this? Was you able to make the tutorial? I have been trying to get this working for a project I want to work on and I'm not able to do it. A tutorial would be a great help. Thank you. Also @TwistedTwigleg great job on the project it is what I have been looking for a while for the project I needed. Thank you also.

I know this is solved, I just wanted to point out that camera far distance is not capped at 10,000, I have a far distance of 20,000 in my game.

Sure, but there's a finite granularity to the depth buffer for an example.

Additionally: The longer the far distance, more objects can be seen in the distance (even if they are only a few pixels large), which could potentially leading to higher draw calls.

I know large view distances can create problems, but it is possible to have a view distance over 10,000.

2 months later

Hi! So I used this technique to add a planet into the background of my space sim kind of game. It works fine, but now my particle effects look messed up: This is what they should look like: I guess it has something to do with the particles blend mode, which is set to "add".

Does anybody have an idea on how to fix this? Or does this technique simply not work with those kind of particles?

Are the particles in the background scene, or the other/main scene? I think you are probably right that it has something to do with using add, but I'm not sure why it would be acting like that, even if the mode is set to add.

The particles are in the "main" scene. Adding them to background, they look fine:

I noticed something. When I get close to the particles, some of the background shines through, but inverted? Check out this gif. You sometimes see the stars from the background skybox through the fire, but black:

Could it be that the "add" mode particles mess with the main viewports alpha value for those pixels, and then the mix() in the shader get's confused?

It's as if there are negative values in your particle material. If you add -1.0 to 0.5 you get -0.5 out of the calculation.

@Megalomaniak said: It's as if there are negative values in your particle material. If you add -1.0 to 0.5 you get -0.5 out of the calculation.

Nice catch. In the shader, clamping the fragment of the main scene viewport to (0.0, 1.0) indeed fixes this see-through problem:

But it's still obviously not quite there. I think I'll have to write a custom additive blending shader for the particles that respects the main viewport's transparent background.

Rather than clamp I think you want to scale your data so that there are no negative values in there. Clamping to remove the see through if the see through is what you are after is probably not the way to go.

Rather than clamping try and add to the value so that there is no negative values. Since they are fireballs(I'm guessing) it should be fine if the values go over 1.0, HDR rendering pipeline and all that.

Also, does the texture you are using have an alpha channel? Or are the parts that are supposed to be discarded black? If the latter, you may be able to avoid writing a custom shader.