Now that we have some rocks and grass set up in the scene, I want to explore another element that often comes up when creating a realistic environment: water. Water can be very hard to get right, especially in EEVEE. Considering EEVEE only uses approximations of light and reflection, it can be really difficult to create a lake or ocean that really accurately reflects your surroundings. Also, because humans are deeply attuned to nature, it can be really easy to spot a fake environment if something is just not quite right. In this chapter, we're going to set up the water shader and then tune the settings of our render to get perfect results. A new concept that we haven't covered yet that I'll start to introduce in this chapter is the usage of light probes. Using light probes is an alternative way to calculate light in EEVEE and should help us in this chapter to create a really nice lake that adds to the natural beauty of the environment we're trying to create.
In this chapter, we will cover the following:
Download the starting file of this chapter, MiniProject 2-Chapter6-Start.blend, or use the project we worked on in the last chapter to start. I want to give the choice to skip chapters, which is why I provide a starting file for each chapter, but if you worked through Chapter 5, Setting Up an Environment with Geometry Nodes, you should have a file that is ready to start from, without needing to download it from GitHub. We'll be using procedural methods to add some noise to the water in this chapter, so there are no extra files to download.
The sample files used in this chapter are available here:
Before we start to create the water shader, it's pertinent to go over what exactly screen space reflection means. Screen space reflection is a method of creating a reflection in a real-time rendering engine. The reflection is calculated using a depth buffer (a way of representing depth in 3D graphics) to calculate reflections based on the screen view we are using. As a result, reflections from a point of view other than the camera in a render might not be accurate. Screen space reflections are much more accurate than using reflection probes and also allow us to use a reflection plane to further inform the direction of the reflection effect. We'll use screen space reflections in this chapter to create a reflection effect on the surface of the water. Let's jump into creating the water shader. I started this chapter by disabling the Geometry Nodes Modifier we created in Chapter 5, Setting Up an Environment with Geometry Nodes, by clicking the Monitor button for each system.
This hides them from the viewport so that our computer doesn't lag while we're trying to create water. My rule of thumb is to hide anything from the viewport that doesn't affect the part of the scene we're working on. That way, we can create small pieces of a complex scene and then render them all together at the end, reducing the strain on our computer.
The first thing we'll do is add a shader that creates a reflective surface for our WaterVolume object:
The water shader will now look like it's reflecting the sky! This is pretty cool, considering all we did was change two aspects of the Principled shader.
From this image, we could call it a day, consider our water shader done, and go home. But let's test it first, to make sure we have true reflectivity. Create a Cube object (or any other object of your choice) and suspend it over the water.
There are no reflections! True water would reflect an object, the cube, and we would see the reflection on the water. So, obviously, this water shader isn't working exactly as we want. The way to fix this behavior in EEVEE is to turn on Screen Space Reflections so that we actually get the cube reflecting in the water. Let's try that right now:
Now, if we look at the viewport, the cube is being reflected in the water!
Screen Space Reflections can enhance any reflective material, from windows to water, so make sure you use it when needed. I think it gives great results, but as usual, we could always make them better. Let's try using a reflection light probe in the next section and refine this reflection even further!
Light probes, as we touched on briefly earlier, are auxiliary objects in the scene (they won't be visible in the render) that we can use to tell EEVEE to compute lighting or reflectivity more accurately than just the default. In this section, we'll use a reflection plane probe to add more accuracy to the reflectivity of the water. Let's get started:
Try comparing the result with the reflection plane enabled and the previous reflection, before you added the light probe, as shown in Figure 6.8. The reflection plane enables us to get much more accuracy on reflections and even allows us to tweak the reflection with the Light Probe properties, so we have much more control over our scene. We'll explore light probes more in future chapters. Now, we're going to move back to the water shader and create a more advanced version that takes into account the real physical properties of water to make our water really over the top.
What we have so far for the water is pretty good, but let's not let ourselves settle for "pretty good"! Let's make it completely amazing. We'll start by changing some of the properties of our water shader, so let's select the WaterVolume object and get back to the Material Editor:
We have some transparency in the shallows of the water now, and it changes to less transparency the further away from the camera we go.
The result I have at this point is looking pretty good. The only thing I think we can improve upon is giving the water some depth.
You may not notice a huge change by adding volume to the water. The change is most pronounced when you want to submerge something in the water, as you'll get the correct refraction and coloration of the object as if it really were underwater.
That finishes our water shader! In this section, we took what was just a flat water plane and turned it into a fully dimensional lake that interacts with our environment properly. This way, we can be sure the water in our scene is realistic, but also that it doesn't add too much to our render times.
At this point, I think our water shader looks amazing. Creating the more advanced version and being able to control our reflectivity through a light probe also makes this system of water shading more flexible. There's the ability to create any type of water, from ocean to swamp, depending on the scene. From this chapter, you should understand some of the principles regarding water shading in EEVEE and be able to apply them to other projects where you need water. Considering how much water there is in the world, you might find yourself using the water shader we made here a lot more than you'd think. We also dipped our toes into light probes and talked about how to optimize reflections for EEVEE.
In the next chapter, we're going to take a look at making our scene even more refined, by adding depth of field and baking some of the lighting so that EEVEE doesn't have to calculate it at runtime.