Render backface of plane mesh with vertex shader

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Pixelcook

Hi,
yesterday I wrote a vertex+fragment shader to generate a 3D ocean from a plane mesh. As long as the camera is above the water surface everything looks quite good. But when I dive below the water surface I have a culling problem which I cannot solve.

  1. When I set the culling mode to “back” (default) or “disabled” I see the original flat plane mesh without modification by the vertex shader on the zero position below the vertex shader generated water. This plane at the base position only disappears with the culling mode set to “front”.

  2. Regardless of the culling mode, I cannot see the backside of my water. Only the flanks of some distant waves are rendered from the top, the rest of the surface is simply not rendered at all.

I tried inverting the normal directions in the vertex shader, but this only changed how the visible wave flanks are rendered. Turning the whole mesh upside down whenever the camera is below it unfortunately broke my game. The water plane is dynamically moved and rotated to always fill the camera image out, which did not work properly any more when turning it around.

I expected this problem to be very small and solved with a one-liner or a simple click (like here). But unfortunately I am completely stuck with this.

I hope somebody can help me and hopefully proof me wrong by having a simple solution for this problem. :slight_smile:

System info: Godot 3.2.3 stable on Linux with GLES3

:bust_in_silhouette: Reply From: Pixelcook

I found a solution myself, also it is not the nice one-liner I was searching for.

I write down my solution for any other person facing the same problem:

  1. I had to leave the plane mesh from godot behind and create a mesh in blender. This at least had the opportunity that I could decrease the mesh resolution further away from the point I am looking on, which saves some computational resources. This mesh I created in two versions, one with the normals looking upwards and one with the normals looking downwards.

  2. I added both meshes to my game and gave them the ocean shader. Afterwards I added a spatial node as parent to both, which controls their movement and the shader parameters (which was done by the ocean itself before). The mesh with the normals pointing downwards is now hidden by default and the controller node checks if the camera is above or below the surface and switches which ocean mesh is rendered.

  3. The culling mode of the ocean material has to be set to “front” so that both sides of the ocean are rendered correctly. With this option there is still this strange flat mesh at the original position rendered for the ocean mesh with the normals pointing downward. This additional render of the undeformed mesh vanishes when setting depth draw to “never”.

Not a one-liner, but it works so far. I hope this will help somebody in the future. :slight_smile:

EDIT: I forgot to mention: Activating SSR or DOF in the post-processing brings the flat plane back into rendering, so you cannot use these effects.

EDIT 2: A very important thing I forgot to mention. Since the deformed mesh is floating above the original mesh position, observing it from below with the camera sometimes leads to clipping errors since the camera assumes the mesh to be behind it. To ensure that the ocean is always rendered, you have to go to geometry->extra cull margin and enter something huge (like 100). This fixes this clipping problems.