Many moons have been up in the sky since our last development post. We sure hope to get up to speed with that… for the posts I mean… the moon stuff is out of our hands and its appearance is somehow fixed… just a guess.
end of disclaimer
When we started Rivers Under Roar, the Kon-Tiki (KTK) episode, we wanted to focus on a more tactical game play, and so our camera was set above and near our raft, with a narrow field of view. To make things a bit cozier, it took place during the night. The player would get some tips by reflections in the water and some lights coming from other parts of the set. Looked good, played badly. It was a bit claustrophobic in nature and maybe that is a good thing for some other games, but it would not fit our idea.
*night and narrow field of view
As the players have some kind of Islands that they need to travel to, they have to (should) see them in the distance, and so, we needed to open up the field of view so we visually needed sky!
*Island in the distance, Image from Expedia.com
Not a big fan of that seemingly transparent stuff usually called sky. Ahhh… that blue tinted air.
As we (and most of all developers except some NASA ones) are not trying to simulate the whole physical properties of the “infinite” sky and how we see it, we will just go with a visual sky, a traditional skybox, a shamefully fake one.
We’re using Unity and Unity has already prefabricated excellent skies for us all to use. Just get a nice looking panoramic photo (or painting), put it in a skybox, and voilà, you have a great looking sky.
*Original skybox texture
Well, it looks good, it behaves well. But it does not fit the rest of the visuals. We are working on a low poly faceted ambiance, so this sky is a no.
And as this are just some images painted on the background, there are no polygons to work with.
No problem here. As you might imagine, just get the original sky, and generate a faceted image, much like a stained glass window. There you have it!
*A faceted skybox texture
*Using a low poly faceted texture on the sky dome
Not quite. Remember this is only an image. Usually skies are spread all over the background and they are blurred, but if you look outside of your window now (is it day time?) you will see that clouds or other colors in the sky are in some blurred state (except for that eventual plane, but that can be simply an overdrawn sprite. Everything works well)
Now, imagine our faceted sky, and stretch it to 360 degrees and look at it again… no more faceted look, no low poly style. Just some strange looking blur, or blurred faces… neither realistic nor low poly. Maybe cool looking… who knows?
Simply extend and generate the faceted image big enough so that when stretched to our skybox, it still keeps its low poly appearance. We could do that, but it would give us an enormous image to paint the sky.
Quick math: If we are using a 60 degrees fov camera, with a 1920 horizontal resolution, we will need something like a 360/60*1920 (or 11560) pixels wide image. We could even halve that to say 5k or 6k pixels. Now add the vertical part and we’re talking about some extra-large kilomegatexture. No way. We would optimize it and so on, make it tileable, shrink it in size, but would ended up in the “blurred” sky we started with.
Or, we could as well create a shader that mapped a fragment to a voronoi cell as well (the faceted image above are just voronoi cells with the colors extracted from the original image), but we didn’t want to get some process in the fragment shader, so it was a not (but would be an yes from the visuals)
Back to the drawing board and make it quick and dirty: If we want a faceted sky, we should have faces! Polygons, triangles, n-gons, whatever makes us happy.
The solution is rather simple: create just the top half of a sphere anchored to our camera position, paint it in the background with some unlit shader, and sample some reference colors from some image. It could be the same image, you know? (We know, and it is)
Ah! Also, cut most of the top of the sphere sky dome as our camera will never look that high. Simple!
We just need a sphere object (3D Object|Sphere) and that’s it… wait… not that default one. We need something with higher polygons… Fortunately, we already had the scripts to create UV and Ico spheres (we chose the later one, of course). It was just a matter of creating the UV projection for “texture” mapping and that was that. Finito.
*Our skybox for several months
This was finished some time ago, but as we continue to work on other parts of the game we were continuously faced with the sky and something was not quite right. Our sky dome looked terribly perfect, linear or patterned.
Not a big issue. In our sphere, we just added some noise to the vertex positions and BAM! Got it! Well, to our surprise, it just looked the same, but wrinkled. We could still see the original perfect ICO Sphere.
While we worked on the health bars for the game, we designed a “crawling damage” that started on one side of a mesh, and wrapped voronoi cells around the object, adding extra cells as the damage increased. That looked more like what we wanted, so we entered a new day with a standard task: “Voronoi cells on a sphere”. While not trivial, two meta-methods do exist: create voronoi cells using “traditional” algorithms adapting it to 3D space, or create a convex hull and the needed points would be semi-randomly distributed on the sphere.
We never tried this path because we were not sure the result was as expected and we were already short on time. So we tried the “crawling” as we did before in the health, but applied to a sphere.
First, we create a triangle on the top of it. Then, using the line that surrounds that triangle, we lower the faces, creating triangles as we stretch the original one. As this is a sphere, as we go down (down to the equator), the triangles get so stretched that become “ugly” or too slanted. Before that happens, we divide the new slanted triangle into several ones, trying to keep them all similar to the first one on top. Of course, after the equator, for the opposite reason, we need to reduce the number of tris, but as nowadays we do not go below the equator, the source code has a comment reading “implement ONLY when needed”.
*a perfect sky dome geometry
Lastly, to remove the similar triangle pattern, as we create each new triangle, we “randomly” slide the new vertices on the sphere. At first, all operation on the sphere were using local Cartesian coordinates, but that introduced similar issues as encountered in UV spheres, so every math we use is polar based: we only deal with angles and all working vertices are “2d-polar”. It is from those polar references that we finally create the mesh… What we do not need on top is also cut from the resulting object, and voilà, a faceted vertex colored unlit sky dome (a vertex colored unlit and faceted sky dome?).
*that is more likely
There are other things to be done (mainly the dynamic sky), but this is our base mesh for the sky.
*our current sky dome
See you soon