I try to use "VisibleOnScreenNotifier3D" Node. But for example, if the object is placed behind the wall (MeshInstance3D), the "screen_exited" signal will not be called.
I would be grateful if you could suggest a way for me to check if the object is being rendered or not.
Thanks.

  • xyz replied to this.
  • cynerboy I think you are wrong

    That's highly unlikely πŸ˜ƒ But who knows, I well might be.

    The engine cannot easily tell if an object is behind other object. Even if an objects is totally covered, it will still go through the rendering pipeline and it will be rasterized into pixels. Those pixels may or may not be drawn into final framebuffer, depending on what's in the depth buffer at the time of rasterization, but they will be processed nevertheless. This all happens in the graphics card on the pixel level and your script code has no easy way of concluding if an object is "behind" something.

    In general there are 3 ways to completely skip pushing an object through the rendering pipeline. Their main purpose is performance optimization:

    • explicit visibility toggle - this is self explanatory.
    • frustum culling - object is checked against camera's viewing volume. It will be skipped if it's outside of it.
    • occlusion culling - object is checked for occlusion by other objects in the scene which need to be specially assigned occluders. Those are typically some big, dominant elements in the scene.

    The first two are straightforward and are routinely performed by most engines. The third one is tricky, can be computationally expensive and requires a special setup. Godot 4 can do occlusion culling but you'll need to set things up for every particular scene.

    Godot can also notify you when object's visibility changes via VisibleOnScreenNotifier3D. It works for frustum culling but I'm not sure if it takes occlusion culling into consideration. You'll need to test it.

    Afaik Unreal's WasRecentlyRendered() only works for frustum culling as well.

    As suggested by @axolotl, you could set up an approximative test using raycasts, which would probably be an optimal solution for your needs.

    cynerboy Objects behind other object are rendered i.e. the GPU needs to rasterize them anyway. They will just be drawn over by other objects. What do you need this for? What's your final goal?

      xyz I am making a game where if the player sees the monster, the monster will stop moving.
      I think you are wrong because I was working with Unreal Engine before I was working with Godot and I could do this using the WasRecentlyRendered function.
      That is, if the monster was behind the wall but in the camera frame, it would still start moving until it is visible in front of the player's camera.

      • xyz replied to this.

        Maybe a raytrace from camera to the object, to see if it’s occulded? Then check the angles, to see if it’s outside the FoV?

        cynerboy I think you are wrong

        That's highly unlikely πŸ˜ƒ But who knows, I well might be.

        The engine cannot easily tell if an object is behind other object. Even if an objects is totally covered, it will still go through the rendering pipeline and it will be rasterized into pixels. Those pixels may or may not be drawn into final framebuffer, depending on what's in the depth buffer at the time of rasterization, but they will be processed nevertheless. This all happens in the graphics card on the pixel level and your script code has no easy way of concluding if an object is "behind" something.

        In general there are 3 ways to completely skip pushing an object through the rendering pipeline. Their main purpose is performance optimization:

        • explicit visibility toggle - this is self explanatory.
        • frustum culling - object is checked against camera's viewing volume. It will be skipped if it's outside of it.
        • occlusion culling - object is checked for occlusion by other objects in the scene which need to be specially assigned occluders. Those are typically some big, dominant elements in the scene.

        The first two are straightforward and are routinely performed by most engines. The third one is tricky, can be computationally expensive and requires a special setup. Godot 4 can do occlusion culling but you'll need to set things up for every particular scene.

        Godot can also notify you when object's visibility changes via VisibleOnScreenNotifier3D. It works for frustum culling but I'm not sure if it takes occlusion culling into consideration. You'll need to test it.

        Afaik Unreal's WasRecentlyRendered() only works for frustum culling as well.

        As suggested by @axolotl, you could set up an approximative test using raycasts, which would probably be an optimal solution for your needs.

          If you can target the left and right sides of its collider with two raycasts rather than just the center, that will probably give a better approximation of if it is fully "occluded". Idk if you can and where to easily get those extents from Godot other than just to calculate them yourself though.

          xyz Yes, I finally managed to do it with the help of camera frustum culling and raycast together. Of course, the detection accuracy is low in some positions, but I am satisfied πŸ™‚
          Thank you to everyone, especially xyz πŸ€—

            8 months later

            cynerboy same problem to me
            I’m using a VisibilityNotifier for my 3D project. It seems to be able to see through walls, but I want objects show in front of camera, I don't want objects show in behind the walls, what I will do?

              gd_qq With raycast you can check object visible front of you or not.

                cynerboy thanks for the reply how many raycast use for this, and how to code in raycast, my project have many rooms in large scene

                  5 days later

                  gd_qq A one raycast from the camera towards the desired object.
                  Your code style is:
                  step one: check the object in frustum culling
                  step two: if in frustum you can get point of location object then raycast to them (Note: Make sure your object has StaticBody or Area for colliding)
                  step three: check the collide name of object if true this mean you can see the object from your camera
                  It's easy.

                  Use a rays which is coming from monsters to a specific positions of a camera view. If a rays is not reach that camera view positions then the monster is not visible.