Godot needs a better way to render separately

yikescloudyikescloud Posts: 9Member
edited May 23 in Shaders

This problem confuse me so long almost 3 years as I learn godot. How can I give a node and its child a fullscreen layer but not affects ohter stuff, or furthermore, how can I choose some object to render same time with a shader? Because the lack of this function, I even can not change multi object opacity same time without the opacity overlay.

If you know gamemaker, it use surfaces, you can render anything on surfaces and then give it a shader or save it, and it's so simple. Some one says I can do it in Godot by use viewport, but that's too overkill, this will mess the hierachy and project. It not suit a complex condition.
As you can see, the metaball shader affect the circle behind it, I don't know how to solve that.

Comments

  • yikescloudyikescloud Posts: 9Member

    If godot cant solve this problem, I think many 2d game effect can not achieve on godot, that's too bad

  • TwistedTwiglegTwistedTwigleg Posts: 2,677Admin

    Welcome to the forums @yikescloud!

    Based on the picture, the expected result is not really using transparency, but is instead just changing the hue and saturation. Transparent circles should mix together like they do in Godot, as that is how you can have things like glass for 2D games that show whatever is behind it.

    However, I understand that in your case, this is not what you are looking for. Instead of changing the alpha, I would look into changing the hue and saturation, as that should give you the expected result you are looking for.
    You could probably write a shader that takes whatever value is in the alpha channel and uses it for hue and saturation modulation, though I have not tried it myself.

    Finally, if you use the _draw function in Godot, you could probably still use transparency and have the expected result you are looking for. However, this will limit the node-based workflow, since you will have to use the same Node2D/Control node to draw all the circles you want to have as a single metaball.

  • yikescloudyikescloud Posts: 9Member
    edited May 23

    @TwistedTwigleg said:
    Welcome to the forums @yikescloud!

    Based on the picture, the expected result is not really using transparency, but is instead just changing the hue and saturation. Transparent circles should mix together like they do in Godot, as that is how you can have things like glass for 2D games that show whatever is behind it.

    However, I understand that in your case, this is not what you are looking for. Instead of changing the alpha, I would look into changing the hue and saturation, as that should give you the expected result you are looking for.
    You could probably write a shader that takes whatever value is in the alpha channel and uses it for hue and saturation modulation, though I have not tried it myself.

    Finally, if you use the _draw function in Godot, you could probably still use transparency and have the expected result you are looking for. However, this will limit the node-based workflow, since you will have to use the same Node2D/Control node to draw all the circles you want to have as a single metaball.

    Thanks your reply :D
    The first opacity picture is a transparent change, the hue looks different just because it merge with the white background, if the background is a image, change the hue will not solve the problem
    Then then metaball problem, if I draw it in a single node, then the metaball can't affect by the physics and they cannot interact any more, so I still think that is a feature missing

  • SIsilicon28SIsilicon28 Posts: 720Moderator
    edited May 23

    You could always try drawing them in a separate Viewport with a solid opacity, then displaying the Viewport 's texture across the screen with a varying opacity. You would need to manage the canvas transform manually, but I think it's a good deal. :)

  • yikescloudyikescloud Posts: 9Member

    @SIsilicon28 said:
    You could always try drawing them in a separate Viewport with a solid opacity, then displaying the Viewport 's texture across the screen with a varying opacity. You would need to manage the canvas transform manually, but I think it's a good deal. :)

    Yeah, seems the only way is use the viewport, but I really dont know how to do that, is that mean I should render the 3 circle in different viewport?

  • TwistedTwiglegTwistedTwigleg Posts: 2,677Admin

    @yikescloud said:

    @SIsilicon28 said:
    You could always try drawing them in a separate Viewport with a solid opacity, then displaying the Viewport 's texture across the screen with a varying opacity. You would need to manage the canvas transform manually, but I think it's a good deal. :)

    Yeah, seems the only way is use the viewport, but I really dont know how to do that, is that mean I should render the 3 circle in different viewport?

    A super quick, probably poorly explain description of how to do this:

    Have all of the circles as child nodes in the viewport with an alpha value of 1 (fully opaque), have the viewport be the same size as the game window (a little code can do this easily) and then have a Camera2D that follows the Camera2D node of your main scene. In the viewport, make sure own world is set and the background/clear color is fully transparent. Finally, have a TextureRect in your main scene that uses the Viewport texture from the circle Viewport, and then set the transparency there! This should, in theory, work as expected :smile:

  • SIsilicon28SIsilicon28 Posts: 720Moderator
    edited May 23

    Yeah, that about sums it up. Just make sure that the TextureRect covers the entire screen.

    And if you want objects to draw over it, use a Sprite instead and parent it to your scene's camera, if you have any.

  • yikescloudyikescloud Posts: 9Member

    @TwistedTwigleg said:

    @yikescloud said:

    @SIsilicon28 said:
    You could always try drawing them in a separate Viewport with a solid opacity, then displaying the Viewport 's texture across the screen with a varying opacity. You would need to manage the canvas transform manually, but I think it's a good deal. :)

    Yeah, seems the only way is use the viewport, but I really dont know how to do that, is that mean I should render the 3 circle in different viewport?

    A super quick, probably poorly explain description of how to do this:

    Have all of the circles as child nodes in the viewport with an alpha value of 1 (fully opaque), have the viewport be the same size as the game window (a little code can do this easily) and then have a Camera2D that follows the Camera2D node of your main scene. In the viewport, make sure own world is set and the background/clear color is fully transparent. Finally, have a TextureRect in your main scene that uses the Viewport texture from the circle Viewport, and then set the transparency there! This should, in theory, work as expected :smile:

    I try it, that way will show the sprite, but if can not interact with mainworld any more ,because viewport is another world. I don't think viewport is design for rendering purpose, that's overkill and will mess everthing, I don't think if I need a bunch of these stuff, then I spawn a bunch of viewport, that's dirty.

  • yikescloudyikescloud Posts: 9Member
    edited May 24

    I think godot must give a new easy way to achieve that, or it will has a big failure on 2d game. Gamemaker is better that godot on rendering, they use surface to achieve that.I really hope godot can fix that problem. Here's the gamemaker surface link https://docs.yoyogames.com/source/dadiospice/002_reference/surfaces/index.html
    And a project I make by gamemaker:https://yikescloud.itch.io/kitty-gen I think it's hard to make with godot now on. I really love godot, and I think it's will be 2d perfect if add this function, I think it still lacking something in 2D by far

    I donno if this can be done by GDNative or make a module

  • SIsilicon28SIsilicon28 Posts: 720Moderator

    Your sprites don't have to interact the world directly. What you could do is setup some sort of sprite "proxy". For each proxy at run-time, it duplicates itself into the Viewport, and copies it's transforms to it while the first one (the proxy) stays invisible. It's achievable if you put your mind to it. :)

  • MegalomaniakMegalomaniak Posts: 2,658Admin

    The viewport should also be only the size it needs to be and no bigger, it would just act as your 'sprite' and be a child of a node that acts as the game object in the game world.

  • SIsilicon28SIsilicon28 Posts: 720Moderator

    It would be more like all the sprite's combined.

  • yikescloudyikescloud Posts: 9Member

    Thank you guys! I will make much experiment later, but I still think godot should add a function like GM's surface IMO, it's so convenient.

  • MegalomaniakMegalomaniak Posts: 2,658Admin

    @SIsilicon28 said:
    It would be more like all the sprite's combined.

    Ah, so @yikescloud is after batching?

  • yikescloudyikescloud Posts: 9Member

    @Megalomaniak said:

    @SIsilicon28 said:
    It would be more like all the sprite's combined.

    Ah, so @yikescloud is after batching?

    Sorry, I don't understand, the image is make in the Adobe XD

  • TwistedTwiglegTwistedTwigleg Posts: 2,677Admin

    @yikescloud said:

    @Megalomaniak said:

    @SIsilicon28 said:
    It would be more like all the sprite's combined.

    Ah, so @yikescloud is after batching?

    Sorry, I don't understand, the image is make in the Adobe XD

    If I understand correctly, batching is where you draw a bunch of similar items together in a single pass. It saves performance because the shader/GPU doesn't have to load different textures, uniforms, etc, and instead can just render everything in a single pass. This gives, among other things, performance boosts due to the lower overhead and data transfer needed.
    Additionally, with batching, everything has to be drawn the same, one on top of the other in a single pass. This would, in theory at least, give you what you are looking for when it comes to transparency.

    However, to do this, you'd need to use the _draw function so all of the pixels being drawn is done in a single pass. Using a Viewport allows you to use multiple draw passes in that viewport, which then you can use the result of in a single pass in the scene viewport (using a TextureRect with the scale of the viewport).

    The gist of it is: You can view Viewports like layers in photoshop. You can have multiple things on the layer, but they ultimately get combined into a single texture, a single layer. You can this use this layer to draw on top of the layers below it. You can change the opacity of the entire layer, which will make the entire thing become transparent evenly, rather than have each metaball be transparent and have the metaballs mix where they overlap.

    That said, that is assuming I understand everything correctly. It can get confusing depending on what you are looking to do, which technique you use, and how you it is implemented. For that reason, it can be hard to explain :sweat_smile:

  • SIsilicon28SIsilicon28 Posts: 720Moderator
    edited May 24

    He's not trying to implement batching. He's trying some sort of "shared transparency". If you look back at the OP's image, you'll see what I mean. The approach I was suggesting was to render the sprites in a separate viewport to be rendered on the screen with an opacity of choice.

  • yikescloudyikescloud Posts: 9Member

    @TwistedTwigleg
    Indeed, the first try I do is using draw function, but what a surrpise, seems everything in draw is processed separately, I will get the same result. Even I use shader. Seems shader is apply to every draw code.
    You can check this stuff I submitted before:
    https://github.com/godotengine/godot/issues/35167
    https://raw.githubusercontent.com/firecloud888/picture_stack/master/2020-01-05_042709.png
    The problem is draw() function is not draw all the things on a cache, then apply the shader, then draw it on the screen, it apply the shader after every time you call function like drawcircle(), draw_rect(), etc. So I cant draw some mask effects like the first image shows. And I try light2D, because light2D only support texture, so I cant use custom draw either.
    And the draw_texture works same

Leave a Comment

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