I’m working on Loading Human VR game and preparing some useful materials for our project.
After some days mixing different ideas here is the result for our sea shader: I tried to mimic (as read on a paper about Assassin’s Creed Black Flag) the Beaufort scale.
I have some parameters such as basic colors and textures, but the overall look is driven by the beafort parameter (from value 1 to 12).
I wanted to generate waves displacement using FFT, but after some tests I decided to use a texture with different cloud patterns stored in its channels.
There is also a “foam” texture with some variations.
What do you think about it?
It will be amazing to have a sort of “collision detection” with the landscape in order to block waves from passing through rocks and stuff…
I’m also thinking about opacity: it could be great to have my sea transparent depending on its depth, but I’m having some problems with it.
I’m still working on it and the development of our game will take quite time… so I’m sure I’ll tweak and change this shader a lot of times.
Here is a short video, showing the runtime changing of the parameter: I have to tune the reflections (open sea is not so reflective) and adjust the speed calculation, because when calm the waves seem to move too slow.
At the moment I think I can’t completely share it with the community, but if ok for you guys I could share with you tips and tricks… until the company decide to release more
I have a “cloud” texture for normal and displacement both… just the scale is different (for normal I used the texture at a smaller scale).
I used the 3 channels of the image to have some movements and variations.
There are 3 foam variations that are blended on the highest part of the waves and near the rocks: for the coastal foam at the moment I use vertex color, but I’d like to automate this process detecting the geometry of the scene in some way.
All the textures are in world scale, so I can change the size of my plane (or terrain) without worrying of the tiling. This gave me a little problem because panning a texture in world scale doesn’t allow me to rotate the sea… so I made a custom “WorldAlignedPanner” that takes in input a direction vector (the same I use to change the tiling of the textures and drive the waves in a specific direction). To keep the math simple I can choose only between the four main direction at the moment (N, S, E , W)
Still working on it… I have to finish another task in these days, so I’ll go on a little slower on this.
Yesterday I made a simple panner driven by a flow texture, to flow the generated displacement map around static objects.
It was quite difficult (to me) to get rid of artifacts keepeing a few nodes but now I have something similar to what I wanted.
It works on big displaced waves now (it doesn’t affect the normal map) but I’ve soon discovered a problem: flow is good for slow fluids (in my case, beaufort parameter from 1 to 4…or maybe 5).
When the sea is stormy, water obviously doesn’t flow around things… but smashes against.
I’m thinking to keep the flow texture but lowering it while increasing beaufort…
Or probably get rid of it and replace with something else!!
Here is a short video of this flowing…
I’ve read a lot in the past days about waves generation… unfortunately math keeps me away from FFT (despite the fact before my degree I passed an exam involving it! ).
Another important point is that in Loading Human we don’t need an hyper-realistic sea: I want to be able to change the weather conditions for narrative reasons during the game, but I could bet that we won’t have sailing sequences
So I decided to call one of the coders and do everithing by myself using the material editor.
I’ve read on Epic Forum this thread by user Kyle_Katarn (all my thanks to you for the inspiration, bud) https://forums.epicgames.com/threads/970990-Gerstner-Wave-Implementation-Am-I-doing-this-right
and tried to switch from texture-driven displacement to generated waves: gerstner waves seems to me a good choice: easier than spectrum-FFT ones and nice result.
So I modified a little Kyle_Katarn structures and displaced a plane mixing 8 waves.
Here is the result.
I should mix more waves, so a way to do that quickly is needed.
Then I also need to obtain a detail normal map… and on that base add again all the other effects you know (beaufort parameters, reflections, foam,ecc)
I’m not sure if I’ll go along this way… but it’s worth a try
At the moment I’m fully busy on several things regarding Loading Human (including this shader) and a mobile game, so I can’t really afford making a tutorial.
But most important, I’m doing a lot of “trial and erros” with this ocean… trying to figure how things work, understanding what I really need and how to fulfill these needs.
So a tutorial done right now will be a confuse mess of unsure things, and I’m afraid not very useful to you guys.
By the way, I promise that I’ll give you some guide when I’ll find the right way to do this headcache-giver sea
I’ve found an error in the GPUGems formula for Gerstner wave generation: it seems quite strange to me that nVidia guys made this mistake… so I’m afraid I’m missing something!
The add the result of the waves mixing to the vertex position… but I’ve found it’s more correct to subtract it (like in the Tessendorf paper): this allow the steepness factor (that controls the sharpness of the wave) to work correctly.
But now I have another problem popping out if using tassellation and World Position Displacement: my shader affects the new vertex from tassellation, but moves these vertex in a strange, noisy way.
They seem to the displaced according to some short wavelenght wave and flattening to the highest position.
You can see here that from a long range the mesh is ok… zooming in the tassellation begins to mess the plane…
I am also using GPUGems and I just changed my material to subtractions and yes the wave steepness seems more pronounced. It does look better. My normals on the other hand no longer matched my waves though.
As for your bug, I did not get your tessellation errors. Looking at your image though it does look like you have very high frequency noise, weird.
I only use tessellation and not vertex position, are you using both? If yes, try tessellation only.
I’m using the “absolute world position” node to obtain the coordinates of the vertices and use as input for the wave calculation.
After that, I plug the result in the W.P.Displacement connector only.
It seem to be strictly related to the density of the original mesh.
I use flat tessellation… here you can see the difference between adaptive tessellation OFF and ON on 2 planes… one with a lot of native vertices and the other low poly…
So… after some days of reading (all these papers gave me dizziness! ) I changed another time my wave generation algorithm.
I abandoned GPUGems way and turned to classical Gerstner equations (the same used in the Tessendorf paper and many others): I find them more understandable and most of all I was successful in finding clear relations between parameters.
Now I only need to specify a main direction, the max wave height (or alternatively a wind speed in Km/h) and a steepness factor to have 4 different waves merged in one ocean.
The overall look of the mesh seems good… and another great things is that I have no more problems with adaptive tessellation!!
Now I should add normal maps and start adding again details like foam.