Search Unity

Question How to make underwater effects appear only on part of screen?

Discussion in 'General Graphics' started by Antilight, Aug 11, 2022.

  1. Antilight

    Antilight

    Joined:
    Oct 19, 2018
    Posts:
    7
    I'm trying to figure out how games are creating the transitional into underwater effects.



    I know the simple solution is to just binarily flip water effects on and off depending on weather the camera is above or below the water level. Tried it before and I'm not happy with it. What I want to know is the technique used to only render the effect on the part of the screen that is underwater.

    Most games that I know of with water have this effect. Like Subnautica and even an indie game I played recently Sailwind.


    If someone could point me in the right direction for how to achieve this myself I would very much appreciate it.
     
  2. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    672
    Good question. I don't know how other games do it but maybe this would work:

    Render the water surface around the viewer into a depth buffer from above. Then you can project world positions into this depth buffer to check whether they are above or under water. This wouldn't work for the water surface itself because of numerical inaccuracies but for the water surface you can simply check the normal.

    This could be used for screen-space fog, for example. You can reconstruct the world position from the (regular) depth buffer and the inverse view-projection matrix.

    But maybe I can come up with an easier solution tomorrow - too tired. You could use the stencil buffer as a mask but the problem is how to fill it.
     
  3. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    672
    Or what about this idea:

    Render the water surface into the stencil buffer and set all stencil values to 1 where a back face is rendered and to 0 where a front face is rendered.

    To get a mask, that reaches all the way down to the bottom of the screen, set the y-coordinate to a large negative value for all vertices that are further than ~100 meters away. You probably also have to render the sea floor and set it to 1 in case that you are looking straight down.

    This should give you a mask for all pixels that are underwater. Should even work if you are entirely above or under water.

    Disclaimer: I have not tried this.

    By the way, you could take a renderdoc capture of those games to see how they do it.
     
    Last edited: Aug 11, 2022
  4. Antilight

    Antilight

    Joined:
    Oct 19, 2018
    Posts:
    7
    Thanks for the ideas. I bought an underwater asset pack that I will try to pick apart later to see how they do it but it seems to be more advanced than I thought. At a glance they appear to be creating a custom renderer?
     
  5. warthos3399

    warthos3399

    Joined:
    May 11, 2019
    Posts:
    1,756
    First thing we need to know is what water asset your using, as most all water assets (Aquas, LUX, etc.) have settings you can adjust for this effect. But if your looking to do something that is beyond the scope of what the asset can do, then you will have to use methods like c0d3_m0nk3y is suggesting.