Camera effect when under water

Godot Version

4.2.1

Question

Hi, I have a third person controller and some water, the water is a subdivided plane with a shader (with vertex displacement). How could I make some kind of fog appear when the camera goes underwater? And can I also make it appear on only the bottom half of the screen when the camera is partially under water?

Thank you!

1 Like

The way I handled it in the FPS demo is to store the position at which the collision happened when the player comes in contact with it (area_entered signal in the water plane). This means the collision point will be at the player’s feet.

In the player’s _physics_process method, check whether the camera position is below the water plane position. If so, apply underwater fog and other effects by making a ColorRect node visible, changing Environment properties in the WorldEnvironment node, and so on.

1 Like

I will try to do that, I can’t currently work on the project, but thanks for your suggestion!

My solution was to apply fog in the fragment function of a custom shader only if that fragment’s y component is negative. Here’s a simplified look at my shader:

global uniform float water_fog_density;
global uniform vec3 water_fog_color;

varying float fog_coord;
varying vec3 world_coord;

void vertex() {
    world_coord = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
    fog_coord = length(CAMERA_POSITION_WORLD - world_coord);
}

void fragment() {
    float blend = water_fog_density * fog_coord;
    blend = 1.0 - exp2(-blend * blend);

    // only apply fog when "under water"
    blend *= step(0.0, -world_coord.y);

    FOG.rgb = water_fog_color;
    FOG.a = blend;
}

As you can see, regardless of whether the camera is submerged or not, there will always be fog that only happens under water.

The drawbacks of this method are that all water planes would have to be set at zero on the y axis, and you are no longer able to use godot’s built-in fog.

This also does not take into account the vertex displacement of the water, but you could try to cover that up by changing the step function to smoothstep.

3 Likes