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

codewithtomcodewithtom Posts: 12Member
edited October 2019 in 3D

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)

Answers

  • TwistedTwiglegTwistedTwigleg Posts: 2,873Admin

    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.

  • codewithtomcodewithtom Posts: 12Member

    @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 =)

  • TwistedTwiglegTwistedTwigleg Posts: 2,873Admin

    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.

  • codewithtomcodewithtom Posts: 12Member

    @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. =)

  • TwistedTwiglegTwistedTwigleg Posts: 2,873Admin

    Awesome! I'm glad I was able to help :)

  • codewithtomcodewithtom Posts: 12Member

    @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.

  • TwistedTwiglegTwistedTwigleg Posts: 2,873Admin

    @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 :)

  • Parkert1911Parkert1911 Posts: 1Member

    @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.

  • DschoonmakerDschoonmaker Posts: 260Member

    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.

  • MegalomaniakMegalomaniak Posts: 2,785Admin

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

  • TwistedTwiglegTwistedTwigleg Posts: 2,873Admin
    edited May 9

    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.

  • DschoonmakerDschoonmaker Posts: 260Member

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

  • hzzzlnhzzzln Posts: 6Member

    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?

  • TwistedTwiglegTwistedTwigleg Posts: 2,873Admin

    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.

  • hzzzlnhzzzln Posts: 6Member
    edited July 6

    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?

  • MegalomaniakMegalomaniak Posts: 2,785Admin

    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.

  • hzzzlnhzzzln Posts: 6Member

    @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.

  • MegalomaniakMegalomaniak Posts: 2,785Admin

    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.

  • TwistedTwiglegTwistedTwigleg Posts: 2,873Admin

    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.

  • hzzzlnhzzzln Posts: 6Member

    First of all, thank you guys for still putting up with me :smile: I'm still quite new to this whole thing.

    @TwistedTwigleg said:
    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.

    No alpha channel. This is it:

    @Megalomaniak said:
    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.

    I did some "shader debugging", if you can call it that. I wanted to know where in the resulting material there are negative values. So I wrote a line like this:

    if (screen_fragment.r < 0.0 || screen_fragment.g < 0.0 || screen_fragment.b < 0.0) COLOR.rgb = vec3(0.0,1.0,0.0);

    But to my surprise, no green pixels anywhere. I tinkered around a bit and finally got something with this:

    if (screen_fragment.a > 1.0) color.rgb = vec3(0.0,1.0,0.0);

    Which resulted in green pixels everywhere where the particles and something else from the main scene where overlapping. It seems like additive blending also adds the alpha channels together without clamping them. And then, the mix function does get confused when using something greater 1.0 as interpolation value.

  • TwistedTwiglegTwistedTwigleg Posts: 2,873Admin

    @hzzzln - I added an alpha channel to the grayscale image, mapping the lowest values to fully transparent and the highest to fully opaque:

    I would suggest downloading it and see if having an alpha channel helps fix the issue. In the particles material, you will probably need to make it use transparency in the material itself though, if it is not already setup to use transparency. That might get rid of the black squares in the particles.

  • hzzzlnhzzzln Posts: 6Member
    edited July 9

    I was 100% sure I tried a transparent texture back when I first encountered this problem and it not working correctly. I tried your texture and now it works pretty much perfect. I'll file that under couldn't see the forest for the trees. Thank you very much!

Leave a Comment

BoldItalicStrikethroughOrdered listUnordered list
Emoji
Image
Align leftAlign centerAlign rightToggle HTML viewToggle full pageToggle lights
Drop image/file