YTread Logo
YTread Logo

Coding Adventure: Terraforming

Jun 02, 2021
Hello everyone, welcome to another episode of

coding

adventure

s creating planets in the past. I've always taken the approach of starting with a sphere and then sampling a 3D noise feature at each point and stretching those points in or out based on that noise value by blending. and by overlaying different noise functions and experimenting with different equations we can get some pretty interesting results, but this approach has a limitation: each point can only have one height associated with it, which of course means no caves, tunnels or ledges of any kind. . This is the approach. I went when I was playing around with this little Outer Wilds-inspired project and while it's nice to take a walk on a moon made of math, it's a little sad knowing that there's no chance of finding a lava tube to explore, for example, or dig one of your own. small cave to shelter in, so in this video I want to try to create a small planet and a

terraforming

tool to be able to make caves and tunnels and shape the terrain to my liking as a starting point.
coding adventure terraforming
I'm going to use an old project of mine where after some difficulties I managed to implement an algorithm called marching cubes. I have a whole video on that, but the basic idea is this: we take eight points at the corners of an imaginary cube and each of these points has a random value associated with it. According to our noise function, values ​​above zero mean that those points are in open space. I like to think of them as air points, whereas when the value is below zero, those are rock points because they're inside the planet, between the air and the rock, that's where we are.
coding adventure terraforming

More Interesting Facts About,

coding adventure terraforming...

I want to draw the mesh of the surface of our planet now with eight points, there are 256 possible configurations, but they are actually only 15 unique cases and the rest are just various symmetries of those and as you can see, all of these surfaces are built from of triangles because computers love drawn triangles, so to make our planet we will have a three-dimensional grid of values ​​classified as air or rock and we will join that space cube by cube building the surface mesh for each as we go. The algorithm for this running cube was published. It all dates back to 1987 for the purpose of viewing medical scan results, but it's also perfect for gaming.
coding adventure terraforming
I'll show the code for this quickly for anyone who might be curious, so most of it is really just a giant table describing how to connect the triangles for each of those 256 configurations I mentioned and I'll be forever grateful I didn't have to. I have to solve them myself because there are a lot of numbers in the core of the algorithm, although I wrote something called hlsl and that allows many cubes to be processed in parallel on the gpu here we start by calculating the coordinates of the eight corners of the current cube and then here we look for each of their values ​​and we use them to determine which of the 256 configurations this cube is.
coding adventure terraforming
So from that giant table we can figure out which edges of the cube the surface passes through. These edges are organized in groups of three and we need to connect them to form the triangles, so I have these two little matrices that just let's take one edge and find the two points at each end, so we do that here for each of our three edges , finally we have to decide where along each edge we want to place the vertices and for now I have only placed them. everything in the middle points, so let's do something with this.
I've written this little script that simply calculates the values ​​of a sphere and stores them in a 3D texture. I want to take a quick look at portions of that texture just to make sure it's working correctly. these lighter regions are outside the surface, everything drawn in black is below the surface and the red line shows the boundary between the two, so where the value is zero, I thought it looked good, so if you like I tell the corresponding cube script to get its data With this texture we should end up with a beautiful 3D sphere and here it is, although it is a blocky looking sphere and although blocks are not necessarily bad, I would like to soften it a little, so in Instead of placing each vertex at the midpoint of an edge, let's do a little function called calculate vertex position and what that function will do is look at the value of both points that it has been given, one will be positive and the other will be negative and will determine where the zero should be along the edge. and that's where the vertex will go, that little change takes us from this to this that looks pretty smooth, so I'll quickly go back to where we're calculating those sphere values ​​and we'll try to sprinkle some noise layers on top, so this is what Our 3D texture looks like this, so let's once again use our matching cubes to build a mesh.
It seems like we're finally getting somewhere. Unfortunately, with this technique we occasionally get random rocks floating in the air and although it should be possible to remove them. with some kind of flooding algorithm, I suspect it would be quite slow and much more practical is to just rule it out with some physics nonsense, so just for fun I thought I'd ask an AI to try and offer some explanations for this floating rock phenomenon. Let's see what he came up with: Rocks float in the air because they are not dense enough to stay on the ground. There is less gravitational attraction on rocks floating in the air because they are at high altitudes and therefore tend to This phenomenon cannot be explained, although some theories suggest that it is a mirage caused by very hot rays of the sun.
This is because the magnetic forces inside the rock repel each other and push the rock into the air and finally hit me with something hard. Facts rocks don't float in the air, they're too heavy for that anyway, clearly there are plenty of excuses for our rocks to float so let's label it as a feature and move on to the more pressing concern of this terrain mesh already using for a million vertices, many of them are probably duplicates because I'm not sure how to share vertices between the cubes, since I don't understand all this fancy parallel gpu stuff very well, if I'm honest, but since I need to read the we mesh the data back to the CPU to generate the collision mesh.
We are now in a c-sharp zone so I can simply loop through all the vertices and remove duplicates using a dictionary which is surprisingly fast, this has the side effect of making the shading smooth which I really want for this project , so that's good and if I show the mesh information again, it looks like we've reduced the vertex count to about 180,000 anyway, now I've created a simple player. controller that works for planets where the direction of gravity obviously depends on where you are standing. It has some issues right now, but I'm working on it now. My main goal here is a

terraforming

ability so you can click to create a tunnel, for example, but it would be quite inefficient to regenerate the entire planet every time a change is made, so I need to split it into parts.
I've been working on the code for that for quite some time, so it's a long time coming. and fear that I'm finally ready to give it a good try. I think it goes without saying that that's not even remotely what I had in mind, but it shouldn't be too hard to fix. That's still not quite right, but it looks like we're going in the right direction, it just needs some tweaking, I'm not sure how, but it looks like I've turned the planet into some kind of weird mushroom. I have an idea what could be going wrong, great though, nothing's happening now.
Oh. it looks like he was actually doing something, he was busy building this interesting monstrosity, well, I guess you could call that a sample of greek ed programming. I need to take a break, coming back to this the next day. Fortunately I was able to locate the problem. pretty quick and I finally got it working, my mistake as usual was pretty silly, but in case anyone wants to know, this is what happened on the c sharp side of things, unity provides two types of 3D vectors, one for integers and one for floating point numbers. Turns out I have a vector3 int with some data that I wanted to send to my compute shader, so I thought about using this handy vector set function, but it complained that it didn't like the type of variable I was giving it and without thinking about it really, I just converted it to a normal 3 vector like this and that made the wavy red line disappear, which of course is all I'm really trying to achieve when I'm programming in the shader.
I was using the equivalent of a 3 inch vector which has an intri, so this is what was happening first. I have some data stored in a 3 inch vector and in binary that data looks like this, then I transfer it to a normal vector3 so that annoying error goes away and even though they are the same values ​​there, the actual binary data of course is They look quite different because they are now in floating point format, but I almost never think about raw binary data in my daily programming, so while technically I knew that these exact bits would end up on the GPU for my little chunk id variable that It didn't set off any alarms in my head.
Now, when you expected a value of 22, for example, you would actually get 1,102,53,376, which, as you saw, resulted in For some problems, the solution to all of this, by the way, was to simply use the correct function for the job , which is not a configured vector as the error message was trying to imply to me, but rather configured programming can be a pleasure sometimes anyway with those chunks in place. I've been working a bit on terraforming, this was actually very simple . I simply cast a ray from the player to see where it hits the surface and in a small sphere around that point I then add or subtract values ​​from the map.
Depending on whether you hold down the left or right mouse button and then of course you need to regenerate the affected fragments, the performance is still not that good with the main bottleneck I think is reading the data from the gpu to the cpu to build the collision mesh If I take this experiment much further, I'll definitely need to address that, but a more pressing concern is that if I try to terraform with my feet, I immediately plummet through the surface into the depths, so I added some additional checks. to the player's controller for when the nearby terrain is modified and it's still a little unstable, but it's definitely a step up from before.
What's bothering me the most right now is how boring it is to look at the planet, so the first thing I'll do is try it. Animating it a little is generating a sphere to act as a simple ocean layer. It doesn't look that watery at the moment though, so it will need some work. I'll start by figuring out how far we are looking through the water to the terrain below and we can do this using the camera depth texture which tells us how far from the camera each pixel on the screen is. The water itself has not been included here because it is using a transparent shader and only solid geometry is included, so in the water shader we can take the depth value of the current pixel and subtract the distance to the water pixel we are currently drawing and that allows us to visualize the distance we are looking across the water.
What we can do now is take. that value and use it to mix between a surface color and a deep color like this and this is how it looks, it already looks much better. I think the water is still completely opaque, so I've been playing around with the code a bit. To make it more transparent when viewed from a steeper angle and also to make it quite transparent in shallow regions like along the coast, maybe I've made it too clear now, but I can always modify it later. I'd like to do it. Sunlight reflects off water, so I'll use this code snippet for my old planet video to calculate a specular glow.
It's a little intense right now, so I'll tone it down to something more reasonable. I think I would like it. However, to be more stylized, so instead of allowing the intensity to decrease smoothly, I'm going to split it into three bands with this code snippet and that takes us from this to this, it looks a little strange because obviously the water doesn't ought. It won't be flat enough to give us a perfectly round highlight, so I'll try to move a normal map like this across the surface to simulate some little ripples. If I increase the influence of that normal map, we should see it start to split. the reflected light pretty well, these fake waves only affect the light so I want to add some bigger waves that actually move the vertices of the mesh I've been playing with in the vertex shader for a while playing with sine waves but if anyone knows a good approach to handle waves in a sphere.
I'd love tolisten to it because what I ended up here looks pretty ridiculous, although if I scale it down they at least do a good job of breaking up that perfectly spherical outline. that the ocean had before, the last thing I want to add to the water for now is some simple foam lines around the shore, but for that we need to know how far the shore is, so remember this 3D map texture we have. good approximation of how far the nearest surface is from any point in space, the values ​​are not literally distances because they change at different rates in different places, but if we visualize them on the surface of the water we can see that the darker values ​​are throughout the show and so we can easily isolate a small band like this.
I then played with it for a while applying sine waves that move with time and breaking them up with some noise until I finally found a result that I was at least reasonably happy with. I'm a little hesitant to show the code for this because it's a real mess. . I wrote this the other day and I already have no idea what half of these numbers are supposed to do anyway, I'm just going to play. With this a bit and try to figure out where to go from here. I also wanted to show the strange results I got when I accidentally increased the resolution of my water mesh beyond what the default mesh settings allow, but that was easy to fix with this line of code, I think what I'm going to do next. is adding an atmosphere to the planet, luckily I already made a project and video detailing that exact topic so I can just drag and drop the files from there, the only problem is that the atmosphere is eating the water. and this goes back to the fact that water is not included in the depth texture, but after doing some research I discovered that I could set up a second camera dedicated just to drawing the depth texture of the water;
The two depth textures can then be simply combined one and now the atmosphere works, so all we have to do is find a good place to have a picnic and watch the sunrise. Another thing I could probably add relatively easily is the clouds from another of my old videos. This will take a little more work because they weren't. It's not really designed with the planets in mind, basically the clouds are contained within a big box in the sky, but I've been modifying this to use a sort of spherical shadow at the moment. The results are a little iffy, but I feel like I'm on my way. in the right direction, maybe after a bit more work I think this now looks a lot better, although if you look closely there is still a bit of weirdness and the performance is far from amazing, especially for a coverage of dense clouds and ideally the clouds should be integrated. in the atmosphere so that at sunset, for example, we get a nice orange glow, but my first attempt had little success, I think that instead of trying to combine these two shades together at some point in the future, I will work on a new and improved version of both that match each other very well, so for now the clouds are basically glued on top, so the lighting doesn't really work when it's not data.
I reduced the detail of the clouds a little to try to make them fit together a little. better with the fairly low poly terrain looking at it, although I wonder if the clouds shouldn't have a completely different style, for example, I just remembered this old experiment looking at my hard drive, maybe something else along those lines could work anyway modes for now. I just want to add some color to the terrain. One idea I had was to take our 3D stock map again and make a copy at the beginning that is not affected by terraforming and then by sampling in the terrain shader we can determine if we are inside a tunnel that the player has dug and we give it a different color.
It's usually pretty dark inside the tunnels, so I made something called a sticky light that you can throw to illuminate an area. I will also calculate the slope of Basically, by just taking the dot product of the direction from the center of the planet to the current pixel and the normal vector of that pixel, we can do a simple coloring based on that slope value, for example by giving the flat regions a grassy green color. and the steeper areas a rockier brown color. I also added some noise to the colors to give a little variety. Once that's done, let's take our intrepid little astronaut on an expedition, so that's been a lot of fun.
We're working on this, but obviously there's still a huge challenge left in terms of making the world really interesting to explore because it essentially looks the same right now wherever you go, that's something I might try to address in the future, time will. will say for now, although I hope you know. I enjoyed the video and thanks for watching, cheers, that's stuck in my head.

If you have any copyright issue, please Contact