Copying Identical Animated Ocean Planes to a Scrolling GridMap

I have previously created a scrolling terrain gridmap which consists of 3 nested levels of grids. For reference, here are examples of the program without matching colors, with matching colors and with procedurally generated farmland.

I have been trying to create an animated ocean. Here is a version created using a variation of the method shown here by prisoner849, which involves modifying a segmented plane and copying the plane to the grid locations. However, when viewed from altitude, the result seemed repetitive. And adding noise to the equation created gaps between the planes.

Lately, I have been experimenting with the Gerstner wave variation of Ocean which generates waves on a Segmented Plane. I tried using this program to create a 2X2 grid of identical segmented Planes which appears fairly seamless. (This is helped by the fact that the basic Ocean plane is flat and the waves - which modify the plane geometry - can be aligned in directions which are a multiple of 45 degrees).

However, when I scroll out or try to expand this to a larger 16X16 grid, I quickly run into framerate problems. I have reduced the number of segments in the plane from 512x512 to 64x64, shown here, which helps a bit.

What is the best way to do this?

It seems that I should be able to use the Ocean program to generate a single Segmented Plane which I can then copy to all of the grid locations (ideally using the GPU). Or will cloning all those copies simply take too much time? (My target framerate is 60 fps.) I could try further improvements by making copies only for grids that are visible, switching to larger grids etc.

But, before continuing to stumble through this process, I wanted to see if there is a better way to do what I am trying to do.

If it would help, I would be willing to trade off some of the features of ocean which I don’t need. For example, I don’t need as much mirroring as the program offers. I am trying to create a slightly rougher version of the ocean shown below - which has very little mirroring, if any:

1 Like

See my unfinished example at Gerstner Water Shader

You can move the boat using WASD. If you have patience, you can sail to china.

I don’t create tiles of gerstner water for the whole earth. I have only one quite large plane, that moves along with the boat, and ends about the end of the camera far plane.

When the boat moves, so does the water plane. If I remember correct, its a child of the boat. Too tired to check.

Since gerstner water is procedural, I can offset the waves forward/left/right etc.

When the boat moves, it appears to be moving through/over the waves.

See the end few lines of where I pass in the earth coordinates.

Sorry, unfinished work, lots of problems, not easy to use.


Thanks for the reply. I hadn’t thought of moving the Ocean plane with the vehicle.

I thought you had pretty much finished the project. I used your version with the floating boxes as my starting point. It was exactly what I was looking for. Not being an expert in OpenGL, I was having a had a hard time figuring out how the Ocean and Sky shaders work and how to modify them…

Since I don’t need the kind of detail that is needed tor land, I may end up using a hybrid approach. Perhaps something like a huge stationary Ocean square (say 50 mi x 50 mi) with no waves overlaid by a 9x9 scrolling grid of squares (say 1.5 miles x 1.5 mi each) with waves.

Do you know if there is a way to use your program without also using Sky? I liked the sky on my demos - which was a simple blue background with matching blue fog, and a directional light to cast shadows like this (switch to cockpit view to see shadows in the cockpit). I’m not sure if I can add shadows or fog to Sky.

.Just FYI - many years ago when I was creating models for the Microsoft Flight Simulator (FS9 and FSX). I ended up making more models of ships than planes, like this one. Although FSX was a flight simulator, you could also sail ships on the ocean and there were a lot of special effects you could add, such as smoke and wakes. I spent a lot of time trying to create an animated flat plane with waves that I could attach to the ship. The first ship I created was a Liberty Ship and, every now and then I would get an email from a player who was taking it for a round the world cruise.

I created 2 editable fiddles.

First one is the gerstner water that uses the classic Threejs dynamic Sky shader.
Threejs Sky :

Second uses a static skybox created from 6 textures.
Skybox :

By the way, all your self-hosted links are returning 403 errors.


I did not know about your skybox version, so thanks for bringing that to my attention.

You suggestions for eliminating the Sky program seem to be working well. I had previously tried inserting a value for SunPosition, but - for some reason - it didn’t work then. It works now. But I opted for the revised fragment shader and am now able to use my sky…

There are a couple of odd errors.

One of the features of my sky is a fog line along the horizon, which I create with the following lines:
let fogColor = new Color(SkyCol);
scene.fog = new Fog(fogColor, 0.25, 95000);

However, when I try that here, the program says that there is an error in three.module.js:
THREE.WebGLProgram: Shader Error 0 - VALIDATE_STATUS false three.module.js: 18762
Program Info Log: Vertex shader is not compiled.
ERROR: 0:252: ‘mvPosition’ : undeclared identifier
ERROR: 0:252: ‘z’ : field selection requires structure, vector, or interface block on left hand side

252: vFogDepth = - mvPosition.z;

This suggests that when you activate Fog, the 3JS shader goes to line 252 to get the value for vFogDepth, but is unable to find a value for -mvPosition.z since mvPosition is apparently not defined. Have you run across that one? (I wonder if that is a typo and it is supposed to reference myPosition?)

The other error is apparently non-fatal because the program runs. The notice says:
Feedback loop formed between Framebuffer and active Texture
I assume that this is caused by my using clones of the water mesh and is something I will have to deal with.

In my other program, I used a single segmented geometry and a single texture to create an identical mesh for all of the grids. When I created a wave by changing the y-position of the points in the segmented geometry, the program automatically changed all the grids.

I was hoping that this approach would also work with the water mesh created by ocean. Maybe not.

My hosted website is with Earthlink and, like all their hosted websites, is supposedly at a server in Australia. You shouldn’t be getting errors. Let me know if they persist.

my vertex shader was missing the line
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );

here is a version with fog
With Fog : Threejs Boilerplate - JSFiddle - Code Playground



The feedback loop error may have something to do with the reflection. See this message.

I believe that Ocean creates a camera to handle reflections. That is a feature that I really don’t need. So it would be nice to turn it off and that would probably improve rendering time significantly.

As the picture below shows, as the ocean gets rougher, distinct reflections quickly start to disappear. This ocean is not very rough, but the reflections of the two white clouds in the water have already become hard to see. The white is still being reflected, but - with millions of tiny mirrors pointed in different directions - is becoming mixed in with the sky color.


As shown below, from a distance, all that is reflected is the dominant sky color. So the ocean is bluer under a blue sky and whiter under an overcast sky.


I want to keep the sunlight and shadows created by the sun, But we should be able to handle that without a reflection camera.

In case the stationary plane approach works best, what are the variables where you would insert the XZ motion of the aircraft (or boat)?

I might use something like a triple layer - a huge plane (e.g. 90000ft x 90000ft) that extends to the horizon and does not have any motion or waves; overlaid by a slightly elevated medium plane (e.g. 30000ft x 30000ft) that has some motion; overlaid by a slightly elevated smaller plane (e.g. 10000ft x 10000ft) that has full waves and motion. My XZ speed would be different for each plane: 100% for the inner plane, 33% for the medium plane; and 11% for the outer plane.

The segments per plane could also vary, with the biggest plane having very few; the middle plane with more and the smallest plane with the most.

So I would have reduced my requirements down to 3 planes - which should be doable.

This would also work with objects like islands and other vehicles since I move them separately above the water.

Does that make sense?

as a side note: I would start with this example Help getting the actual position of a vertices in a buffer geometry! - #4 by prisoner849

1 Like

Here is a mash up fiddle.
Land On A Square : Threejs Boilerplate - JSFiddle - Code Playground

The ocean follows the helicopter and is offset based on helicopters x, z.

Comment line 197, then uncomment 198, this will show a much smaller square of the ocean, and when you fly the helicopter, you will see that the ocean texture follows.

1 Like

I used your demo to create my first version of animated waves So it was very helpful.

I replaced your random generator with equations for waves and added a texture and a Perlin bumpmap to create the random noise. The result looked pretty good. Or if you can’t see the result, see the picture below:
(Unfortunately, this does not show the moving waves very well.)

At altitude, there was some obvious tiling that can probably be fixed by creating and using more than one version of the mesh - with different bumpmaps.

I ran into problems when I tried to add sharper definition to the waves and water, by adding your noise and removing the textures. This highlighted two issues:

  1. Adding the noise caused the geometry to be different along the edges. See below:
    I should be able to fix this by making the geometry for the top and bottom rows identical and the left and right columns identical.

  2. But even without the noise, I found that removing the textures caused a marked division between the grids to appear. See below:

I suspect this is because the program does not compute the normals along the sides the same way as in the middle - that it tries to smooth the normals by considering adjacent segments - which don’t exist along the edges. I might be able to fix this by creating an extra geometry that extends one segment out from the current geometry, computing the normals for that geometry and then copying the subset of normals to my current geometry.

But perhaps you have already addressed these problems or know what is needed to fix these problems?

1 Like

Thanks! I will give that a try. You have apparently put a lot of work into converting Ocean from a static program to a dynamic program - which makes it far more useful.

I like the helicopter. I tried creating a flight demo with a helicopter and ended up using a similar control scheme. I used the mouse to control pitch and speed (assuming that the pilot would add power to maintain altitude) and used the mouse wheel to control vertical speed (power). I used the mouse buttons for left and right rudder - although this becomes more limited as speed increases and the helicopter tends to weathervane into the direction of flight.

Okay, I got it to work using a blend of your two shaders - this one and the one without sun position. A few questions:

First, is 1024 the design dimension of the mesh - i.e. where 1 meter of movement translates to 1 meter of offset on the mesh?

Second, If so and if I doubled the size of the mesh, it would seen that I should decrease the movement by 1/2, and double the tiling number and the number of waves (and possibly the number of segments). Does that make sense and are there other adjustments I would have to make to the waves?

While I could theoretically increase the size of the mesh forever, there is a point where the animation is no longer visible. For example a mesh size of 8192 meters would equal 5 miles across, or a range of 2.5 miles visibility.

Third, it seems that the best way to cover the remaining ground would be create a stationary static mesh that underlays the animated mesh and that reaches out to the horizon. However, it might be a bit of a challenge to get them to visually merge. Any suggestions?


sorry. its licensed MIT, no warranties or guarantees of any kind. If it looked good to me when I made it, then I’m happy with it and I continue on other things.
I’ve shared several examples of using it, and they all look good to me. That’s all it needs to be.
I think you need to experiment with sizes, if it looks too big, then make it smaller.
I think tiling will work ok, unless you wrap it into a sphere. I didn’t solve that problem.
I prefer not to use tiling because of the extra issues that you end up discovering that are too hard to solve if you need to consider ROI.I make no money from it.
I prefer to keep the ocean centred at my player, and use the players world x, z to offset the algorithm.
See lines 420-425 in this last example: Land on a Square

1 Like

Well thanks for all your help. All the sample programs you provided were helpful and I think the last program best answered my original post by providing an alternative way of addressing the problem.