I new to game engines . I have some basic questions :
If I have say , 200 polygon2d nodes then are all of them re-rendered every frame ?
How can I know if a Node was redrawn ? Is there a method that is called before a node is redrawn ?
Is there a way to prevent a Node from re-rendering ?

  • xyz replied to this.
  • druboi If I have say , 200 polygon2d nodes then are all of them re-rendered every frame ?

    Yes, but the engine employs a number of optimizations to draw only what is actually needed.

    How can I know if a Node was redrawn ?

    If it's on screen - it is redrawn.

    Is there a method that is called before a node is redrawn ?

    _process() is called every frame. You can track the visibility of a visual node using visibility notifications and enable/disable the _process() accordingly. Note that for 2D (i.e. canvas items) there are two stages to "drawing it". One is creating its final texture (which may not happen every frame depending on the node type) and other is putting it onto final framebuffer (which happens every frame if the node is visible by the camera i.e. not culled). The former you can intercept by draw notification while the latter you can't.

    Is there a way to prevent a Node from re-rendering ?

    What exactly you're set to accomplish here?

    druboi If I have say , 200 polygon2d nodes then are all of them re-rendered every frame ?

    Yes, but the engine employs a number of optimizations to draw only what is actually needed.

    How can I know if a Node was redrawn ?

    If it's on screen - it is redrawn.

    Is there a method that is called before a node is redrawn ?

    _process() is called every frame. You can track the visibility of a visual node using visibility notifications and enable/disable the _process() accordingly. Note that for 2D (i.e. canvas items) there are two stages to "drawing it". One is creating its final texture (which may not happen every frame depending on the node type) and other is putting it onto final framebuffer (which happens every frame if the node is visible by the camera i.e. not culled). The former you can intercept by draw notification while the latter you can't.

    Is there a way to prevent a Node from re-rendering ?

    What exactly you're set to accomplish here?

    I was changing the window size and new polygon nodes are create for every _on_resized call.
    As the polygon count increase the fps drop. It old nodes don't change however , so I was if there if any optimisation I could make there.
    Thanks !

    • xyz replied to this.

      druboi Maybe you're creating something you don't actually need while forgetting to delete something you don't need. Let's see some minimal code example of what you're actually doing.

      @xyz I am drawing shapes in the nodes _draw() method. When I resize the screen , the method is called repeatedly but nothing new is drawn since it doesn't depend on the screen size. Can I avoid this _draw() call in someway ?

      • xyz replied to this.

        druboi
        You're creating nodes in _draw()?
        Best to post the minimal version of your _draw() function that still causes the problems.

        How and when _draw() is called is determined by the engine. If it thinks it's time to redraw the node that has custom draw implemented - it will call it. Note that this also depends on the stretch mode in your project settings. If it's disabled, every window resize will trigger redraw.

          xyz

          Just drawing circles of random radius. I want to prevent it from redrawing when the screen resizes. Is it possible in someway with saving the random values ?

          `
          func getRandomRadius()->float:
          return float(randi_range(10 , 30))

          func _draw() -> void:
          var radius = getRandomRadius()
          var pos := Vector2(radius , 30.0)
          while pos.y < size.y:
          print("pos",pos)
          draw_circle(pos , radius, Color.MAROON)
          radius = getRandomRadius()
          if pos.x + 10.0 + radius < size.x:
          pos += Vector2(radius + 10.0 , 0.0)
          else:
          pos = Vector2(radius , pos.y + 70.0)
          `

          • xyz replied to this.

            druboi Generate the radius sequence in _ready() and store it in an array so _draw() can read from it.

            Alternatively, use RandomNumberGenerator object
            If you initialize if with the same seed before starting to draw, it will always produce the same sequence of pseudorandom numbers.

              xyz

              Oh , thanks for this !
              Is there also a way to generate a UUID in Godot ?

                druboi Is there also a way to generate a UUID in Godot ?

                There is, but how it that related to your original problem?

                  @kuligs2 Thanks ! I'm new to this , no need to make a meal of it.

                  @xyz As I understand then there is no way to "bake" what I have already drawn on to a "canvas", so that further draw calls don't have have re-render the past drawing. In ProcessingJS , you have to call background() to clear the screen before every draw call , I was trying something similar.

                  I think Subviewport have an update option to additively render to the canvas. But I can't get it to work , is this possible ?
                  Thanks again !

                  • xyz replied to this.

                    druboi Yes, you can do only one time drawing with subviewports. But I'm pretty sure your goal is achievable via less involved means. Today's graphics hardware can do a lot and it's built to perpetually redraw frames. Drawing 200 things each frame is pretty much nothing for a modern GPU.

                    If you want more specific suggestions, describe your actual final goal, not your attempted or presupposed solutions.

                    Conceptually, game engines are somewhat different from rendering frameworks like Processing. In a sense, Processing is much more primitive and low level. It's just a rendering api that doesn't keep any persistent state of drawn objects between frames (unless you manually code it). Game engines, on the other hand, are designed specifically to maintain such state, in a form of scene graphs, nodes etc...

                    Engines mostly spare you from dealing with explicit draw calls. That's the engine's responsibility, and in fact one of the main benefits of using an engine. You only need to manage "high level" persistent objects.

                    So if you need to show 200 things, just instantiate 200 objects (e.g. Sprites nodes) into a scene and let the engine take care of drawing them. It will do its best to optimize the draw calls.

                    7 days later

                    I have been trying to implement some processing sketches in Godot. I realise now that almost all sketches in Processing re-render the whole drawing every frame , (except some painting algorithms). I understand that despite the urge to , I shouldn't try to over optimise by trying to reuse what was rendered earlier because that is not how GPUs work. So your explanation is spot on and very helpful.
                    Thanks again for your time !

                    • xyz replied to this.

                      druboi Yeah don't worry about redrawing. As I said, GPUs are built to redraw.

                      4 days later

                      @xyz
                      I have question related our discussion . Say I create a visual using a Shader , say something like a shadow or a shape using equations. If I am using this visual as a static graphic , then is it more performant for me to create a texture out of the shader output and use that instead ? or does Godot already do that under the hood ?

                      • xyz replied to this.

                        druboi Depends on how complex the shader is. In most cases it's actually ok to just run the shader frame-to-frame. Only if the shader does very complex/lengthy code (that hinders realtime framerate) and the generated image is not meant to be changed or animated. But in that case why use realtime shaders at all? You can pre-render the thing in a 3D app whose shaders are even more versatile than gpu shaders.

                        If a shader is assigned to an object in Godot, it'll run every frame. In fact shaders are the thing that render the frame. If they don't run - nothing is drawn.

                        Again, today's graphic hardware is made for brute force. You can throw a lot at it without hearing it complain 🙂