It has been fun programming this ocean, and I want to optimise its use. What I want to use is a method projecting a flat plane from the camera and its frustum onto the ocean, and then use this plane to create my ocean. This would mean that in terms of the mesh i use for the ocean I will be making use of all of its vertices. A really cool method that was also mentioned in the article about the tech behind assassins creeds oceans that inspired me to start this (Assassins Creed Tech Article).
In the image below you can see what i have to do to get this method to work, not only to i have to project onto this invisible plane, but have to account for what to do if the projection does not hit the plane. So all i have to do is reflect the vector off the roof and fire it back down, some fun little math to get this working.
Accidentally left my music on during the video posted below, so enjoy the Persona 3 sound track.
I even managed to take this further by using a really cool site called Desmos to form some equations to force vertices to cluster around the point of focus on the ocean, making even more efficient use of the vertices, meaning i no longer have half of them rendering parts of the mesh being projected onto the horizon. Below you can see the equations on the site and the effect of the clustering.
I wanted to implement buoyancy in order to get object floating on my ocean. The way I implemented this was through buoyancy spheres. This is what was used in Assassins creed to implement buoyancy in an efficient and accurate manner. Multiple buoyancy spheres are attached to objects in order to provide an approximation of the objects shape. Below I have attached some buoyancy spheres onto a cube. I can then check the height of the ocean at each point of each sphere and determine how much of it is submerged to determine the amount of upwards force.
I factoring in 3 forces into these physics, gravity, buoyancy, and drag. I was having a few issues initially with reaching an equilibrium that would have the objects settle and float normally on the ocean. In the video below you can a real propulsion of objects out of the water.
I added some debug arrows to my buoyancy spheres to represent how much of each force was being applied to each one. This helped me find where the issue was in my math and find the point of equilibrium in my buoyancy. The green arrows is the force of gravity, blue is buoyancy, and yellow is drag, and purple is the overall force.
In the end I got some good results, I was really happy with the approach of buoyancy spheres. They provide great results with a low cost and a flexible application.
I love games which can change the entire mechanics of its self by creating a world that is something different. This is what the Mario Galaxy games did by creating planetary bodies to open up a variety of new mechanics that otherwise would not have been available. And this is also something Assassins Creed Black Flag did with its ocean, creating a non-static world that was something I had never experienced before. It was a world with a personality, that could work with or against you.
Ever since I played the game I wanted to figure out how there ocean worked and create it. Lucky for me I came across an article that interviews an Ubisoft employee who explains how the ocean works entirely (Assassins Creed Tech Article).
One of the first thing I wanted to get right before anything else was getting the waves procedurally animating on a plane. With a series of values that I could adjust to change the size, speed, or shape of waves. Before I could do any of this I had to study into Gerstner waves. A Gerstner wave is a wave that forms peaks and troughs. And the collective Gerstner waves is a summation of multiple individual Gerstner waves of different amplitudes and wave lengths to form a fractal implementation.
I decided to work with the Unreal Engine, because I enjoy working with its Blueprint system for creating shaders. The implementation of Gerstner waves into a shader also went rather well with the use of this GPU gems chapter of water simulation (GPU Gems Water simulation Article). Helpful laying out all the equations I need to implement this functionality. Though I came across an annoying issue that I have never seen before. For some reason Unreal Engine shaders do not use radians or degrees. Instead they use a normalised value between 0 and 1. So 2pi (Radians) = 360 (degrees) = 1 (Unreal). I do not understand why it does this, but it took a long time to debug.
I managed to get the shader set up, and a manager that could send down values to the shader in order to control the shape, speed, or size of the waves being created. The end result was very effective, and am quite happy with this first step.
Been working hard on this planet rendering. Managed to get to terrain data correctly mapping to the surfaces and moved onto managing level of detail on the surface. I noticed certain parts of my planets were very flat and were not making much use of my tessellation shader. So I capped to amount of tessellation that can be applied to certain triangles based on the different in height of each one of its vertices. Below is an image of the effect of this level of detail capping, with the mountains getting a lot of tessellation and flat lands getting very little.
Interestingly I was having slight issues getting the tessellation for the centre of the triangles to a correct value as to reflect the edges. So I decided to factor in the golden ratio which seemed to work really well, which is really cool as the whole point of the golden ratio is perfection. Oddly enough I also use the golden ratio to procedurally generate my icosahedron shapes as well. I definitely want to look more into this number, it seems to have a really interesting history and application.
I had to sort out the lighting, so initially I created a geometry shader and recalculated the normals based on the cross section of each triangle. Though this got me really edgy lighting. So I decided to interpolate it with its original sphere normals to calculate the final normal. It looks really nice from a distance, though gets a few artefacts up close. Ideally I want to create a normal map along with the procedural terrain data, but this is a nice fast solution for the time being.
So I’ve got it all working, and been testing around with multiple planets in a single space. I’ve gone up to 100 (took a long time to generate all the terrain data though, need compute shaders) with no issues. Got a small video below with 4 planets of different sizes in a single space, i fly from planet to planet showing there geometry tessellate and the what it all looks like. I am quite happy with it all.
I decided to go with an icosahedron for the base shape of my planets. With a simple library of functions to procedurally generate the shape and different sizes and levels of tessellation. Here are some images of some shapes i can generate with the function.
Though now I need to get some work done on generating the terrain height data. For the time being I am sticking with a base Perlin noise implementation and simply modifying the data generated to get different effects. Though ran into a little issue as I am using a cube texture to map my terrain data onto my planets. So I needed to use 3D perlin noise instead of 2D so that the edges of the cube texture match up more easily, as they could factor there neighbours in 3 dimensions maintaining a nice smooth effect.
Below are some examples of modifications made to the original Perlin noise data to get different effects. Except the first, which is just a normal Perlin noise image.
I have been experimenting with the XNA library and have been making a geometry style grid to use in a game. The grid is made of nodes that use Hooke’s law. Below is a video showing some basic pulses on the grid and how they interact.