1
\$\begingroup\$

I want to create a virtual fish pond similar to this in Unity (full video):

enter image description here

The ocean floor and fish are not a problem, but the effect of moving water that displaces the content below the surface is a mystery to me. I have googled and looked at the Unity asset store, but most water assets and questions are regarding more general oceans in 3D games, and not this type of top-down clear water effect. My research has led me to believe that the effect can be achieved with shaders, however I don't know much about shaders.

What I need:

  • Top-down clear transparent water, where the content below the water is displaced by the moving waves

  • The waves need to reflect light (highlights on the wave fronts)

  • Ripples in the water based on collision, so touches will create ripples in the water

How can I achieve this in Unity? Are there any existing assets / tutorials / open source projects that do this, or do I need to write my own shader for it? And if so, what components do I need to include in that shader?

\$\endgroup\$
7
  • \$\begingroup\$ Do you want index of refraction as well? If so, that particular bit is still out of the realm of real-time video game graphics. \$\endgroup\$
    – Almo
    Jul 8, 2019 at 21:43
  • \$\begingroup\$ do you need simple Ripple? \$\endgroup\$ Jul 9, 2019 at 2:29
  • \$\begingroup\$ @Almo Regarding refraction, I don't need the refraction index to be physically accurate, I just want to approximate the effect of the content below the surface being displaced by the moving water, similar to what is shown in the video. \$\endgroup\$
    – Daniel
    Jul 9, 2019 at 7:25
  • \$\begingroup\$ @SeyedMortezaKamali I need ripples to appear where the user touch/click, so multiple ripples can exist at the same time if the user clicks several times. \$\endgroup\$
    – Daniel
    Jul 9, 2019 at 7:30
  • 1
    \$\begingroup\$ @Daniel Ripple \$\endgroup\$ Jul 9, 2019 at 9:24

1 Answer 1

2
\$\begingroup\$

A full example with all of these effects gets a bit involved, but here's a quick overview of the main components you'd use:

To simulate the ripples there are two main approaches:

  • Use RenderTextures to store the height and momentum of each cell of water on your surface. Stamp into these when you want to apply a disturbance to the water. Use a shader that implements the Navier-Stokes equations to integrate the fluid properties each frame.

  • Or, approximate. Still using a RenderTexture to represent a heightmap of your waves, draw expanding ripple particle effects into it emanating from each contact. Here rather than doing a full fluid sim, you're just faking the most noticeable feature: circular waves that radiate out from a contact point.

Once you have the heightmap, you can infer the surface normals from its gradient.

To get the surface shimmer:

  • For each pixel of water you draw, look up into the normal map computed above. Reflect your view ray by this normal and use this to look up into a cubemap for reflections. Mae the reflection brighter at shallow angles and fade it out as the view ray gets more parallel to the surface.

To draw the scene underneath refracted:

  • Use a grab pass to capture the scene rendered so far into a RenderTexture that you can sample in your shader. If you sample this at the same pixel coordinate you're currently drawing on the screen, and output that colour, you'll get the effect of perfect transparency - showing exactly what's behind your water surface. If you shift your sample coordinate using the normal vector, you'll distort the image viewed through the water's surface, creating the appearance of refaction.

  • More sophisticated versions of this effect can use the scene depth information too, to raymarch a refracted ray against the scene to better approximate what you "should" see when viewing at that angle. But you can go a long way toward the subjective appearance of refraction even if it's not geometrically accurate like this.

Add your colour sample from the shifted lookup into the grab texture with the reflection value you calculated and now you have a simple approximation of shallow, clear water.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .