Seamless displacement
An essential property of the proposed algorithm by Tessendorf, Simulating Ocean Water, is that the result of the FFT actually tiles seamlessly. This means that an individual tile will end in x-direction as it starts in x-direction, with regard to the color gradient going left to right and vice versa.



Left: One individual displacement texture rendered using Tessendorf's algorithm. Middle: 10x10 tiles tiled side by side. Right: Seamsless edges between tiles observed through a skewed angle
This implies that to render a very large ocean, it is only necessary to render one single tile mesh of ocean, and then those can be seamlessly tiled together. One problem with this approach is that if the ocean is observed from far above the surface, so that many tiles are visible simultaneously, then one can spot the recurring patterns in the meshes.
Left: Mesh rendered by displacing pixels in y-direction according to the displacement map.
Right: Mesh with blinn-phong illumination after naively calculating normals.
Even though tiling the meshes should be straight forward, some bugs occurred among the way. First of all, one has to lazily connect the vertices of the two tiled meshes, meaning one is forced to add N + N + 1 extra vertices around the mesh and set the height of those vertices to the height of the corresponding vertices on the other edge. Particularly, we have that vertex (N, N) should map to the same height as vertex (0, 0).
In code, it was easily fixed by indexing the displacement map with a different index than the list of vertices.
The water however still does not look very realistic, and this is due to the naive normal
Left: Mesh rendered by displacing pixels in y-direction according to the displacement map.
Right: Mesh with blinn-phong illumination after naively calculating normals.
Even though tiling the meshes should be straight forward, some bugs occurred among the way. First of all, one has to lazily connect the vertices of the two tiled meshes, meaning one is forced to add N + N + 1 extra vertices around the mesh and set the height of those vertices to the height of the corresponding vertices on the other edge. Particularly, we have that vertex (N, N) should map to the same height as vertex (0, 0).
In code, it was easily fixed by indexing the displacement map with a different index than the list of vertices.
uint32_t N = Np1 - 1;
for (int z = 0; z < Np1; z++) {
for (int x = 0; x < Np1; x++) {
int i_v = z * Np1 + x;
int i_d = (z % N) * N + x % N;
vertices[i_v].position.y = displacement[i_d].real();
}
}
Left: Tiled ocean with visible seams due to non connected vertices. Middle: Tiled ocean with
invisible seams, though vertices are improperly connected by the index buffer. Right: Properly
connected vertices and tiling works without seams.
The water however still does not look very realistic, and this is due to the naive normal
calculation done. The basic idea was to just get some basic lighting going, and to do so I
calculate the normal for every vertex by calculating the surface normal for all triangles
neighboring the vertices. The vertex normals are then summed together and normalized.
This approach is creates a worse looking ocean according to Tessendorf. Instead, it is
suggested to calculate the x and z derivatives through two extra FFT-passes described
in equation 37.
This will be implemented next up, together with choppy waves, which requires displacing
the points in x and z-direction. Choppy waves and slope calculations require yet another
four FFT-passes to calculate, but yields much more naturally behaving waves.
Kommentarer
Skicka en kommentar