4
\$\begingroup\$

Introduction

I hope that this question isn't too broad, my apologies if it is. Anyway, getting to the point, our video game is set in ancient Egypt and, to nobody's surprise I'm sure, Egypt has a lot of sand in it. Sand is one of those substances that is notoriously difficult to simulate, however, in order to create a realistic desert I do have to deal with that aspect. Additionally, it also allows for the landscape to gradually change, which isn't just what real deserts do all the time, but it will also aid with making large stretches of desert seem a bit more interesting.

My primary concern is managing it in real time. On small scales, sand flows almost like a fluid, which needs to be done as characters interact with it, but even as a whole, a desert changes rapidly (compared to most other landscapes) as a result of environmental effects; sand moves, entire dunes displace themselves in a matter of days, and tracks created by humans and animals can quickly dissipate.

Current Approach

Hence I am requesting methods that are good at achieving all these effects in an efficient manner. Personally, I was thinking about using the incompressible Euler equations utilising Lagrangian mechanics, thus working with particles, and then using something like Marching Cubes to render. However, it sounds like that'd be extremely time–consuming, so I wonder if there's a different, better approach.

Technology

Currently we're working on our own game engine that is written in C and uses Vulkan as the primary, and probably only, graphics API. Hence, plenty is possible, although we'd prefer to keep the number of dependencies down to a minimum.


Thanks a lot in advance.

\$\endgroup\$
  • 1
    \$\begingroup\$ "all these effects" — all which effects? If you want a method to achieve a particular outcome, step 1 is clearly defining the outcome. A geologist could probably list dozens of interesting processes by which deserts change over time, but most of us gamedevs aren't geologists, so help us out by clearly describing/illustrating your target. \$\endgroup\$ – DMGregory May 3 '18 at 13:47
  • \$\begingroup\$ A method to achieve a particular outcome, as in, creating a baseline and initial state would be helpful, but isn't my primary concern as of now. For that I've considered particle deposition. My primary concern is managing it in real time. On small scales, and flows almost like a fluid, which needs to be done as characters interact with it, but even as a whole, a desert changes rapidly (compared to most other landscapes) as a result of environmental effects; sand moves, entire dunes displace themselves in a matter of days, and tracks created by humans and animals can quickly dissipate. \$\endgroup\$ – Nick Dietz May 3 '18 at 13:50
  • \$\begingroup\$ If you are really trying to be realistic: in ancient Egypt, virtually nobody lived in the desert. \$\endgroup\$ – Maximus Minimus May 3 '18 at 13:54
  • \$\begingroup\$ True, but the desert is still there, and covers the majority of the landscape. Most of the interesting stuff happened alongside the banks of the Nile, and the Nile was their primary form of transportation, but venturing into the desert was necessary at times. The fact that nobody lives in a desert doesn't mean it's not there. \$\endgroup\$ – Nick Dietz May 3 '18 at 13:57
3
\$\begingroup\$

Notes:

  • I know this is about Egypt, but I will not make this specific to Egypt... because people coming here may find this question and its answers useful for other desert simulations.
  • I am trying to keep this simple, avoiding too complex simulation that may eat too much resources.
  • This is mainly based on Wikipedia. However I also had a read of the Slope Stability article from the Tulane University, which covers landslide among other things. And the article Coasts: Sand and Dunes from the U.S. Geological Survey.
  • This is all speculative, I have never implement a similar system. I would like to see how it ends ups working, though.
  • Also, I'm being a bit sloppy with my writting, sorry about that.

Layers

You need them. We will have a static layer ("bedrock"), and one dynamic heightmap (sand). We will do large scale simulations on the dynamic one, to handle dunes et.al. That will be the main focus.

Note: This model does not handle deserts with different sands types.

We also need to handle placement and movement on the sand. Objects placed on the sand will displace it, making the object sink slighly, depending on the properties of the sand and the local geometry. Also they movement of the sand may take the object out (undug).

Which brings me to... we need a wind vector field, that will tell us the wind direction and speed for every position. The wind is supposed to remove small features, we need it to simulate the movement of the desert, the shape of the desert may affect it, and it can blow objects away.

Given that small features are not permament, I would suggest to have a temporal substractive layer for small local features. Foot prints, for example. Just discard old enough ones - for a sensible definition of old enough, do not bother to simulate wind with them. Thus saving memory and processing time. Using a substractive layer for small temporary features also means that the dynamic layer does not need to have a high resolution.

And of course, particle effects, et.al.


"Bedrock"

This can be - probably - a heightmap, in particular if it is not exposed. However, if you want to have caves, you will have to use full geometry.

Does not need to plain, does not need to rough, does not need to be rendered as rock, or at all. The "bedrock" layer is a static heightmap, predefined for the area. It may serve a way to control how things happen in the upper layer. Since you cannot design the dynamic layer, this is important. I am suggesting to implement it - at least initially - as a smooth heightmap, and tweak as needed.

Remember that not all deserts are made equal, a rocky desert could have a very jaggy "bedrock" and a low dynamic sand layer, for example.

Optional: Since you have wind, and you may have exposed "bedrock", you could simulate erotion on it. Probably not something to be done realtime, unless it is some alien desert where that thing happens fast.


Dynamic sand

Here is the deal: Sand will not overhang, and will not leave cavities. So you do not really need to simulate voxel or anything like that. A heightmap will do. You will be adding this layer on top of the geometry from the "bedrock", so the effective height is the addition.

Not all sand is made equal. In particular we need to know the density of the sand, and angle of repose of the sand (this depends on the surface area of the grains, the density and the gravitatory acceleration). For you, this are values to tweak.

The repose angle will be the angle of dunes on the slip face. Usual values for the angle of repose on Earth are between 30º and 45º.

Yes, you can use random deposition for the starting position. Perlin noise will also do, and would be cheaper. You would need to teak it to make sure it does not violate the repose angle. Nothing should be steeper than the repose angle.

Optional: You can choose to consider humidity (that is up to you, it makes the model more complex). Low water saturation will make the angle of repose higher (you can build stuff out of wet sand), while high water saturation will lower it (the sand flows better). You would need a humidity map, and a function that gives you the angle of repose from the local humidity. You may consider nearby features (rivers, for example) to decide humidity sources, and use wind to spread it. This may also tell you where the - sporadic - vegetation is more likely to appear.

We need a ramping angle (for the other side of the dunes), that should be a fraction of the repose angle. Also tweak as needed.


Now, wind will move sand. In three different ways:

Wind and sand

  1. Creep
  2. Saltation
  3. Suspension
  4. Wind

Tweak the proportions at which these happen.

Creep is easy. We just move values around in the dynamic heightmap, according to the wind vector field, the wind effect factor (so you only move a portion of the sand), and the elapsed time.


Image for reference (the image shows the angle of repose as 34º, Barchan is the type of dune):

Dune diagram

Notice that the ramping angle (on the opposing side of the angle of repose) is lower (less steep).


Notes:

  • Creep should not result in a structure steeper than the ramping angle. You can push the excedent ahead.
  • Sand should fall to the other side if it making an angle greater than the repose angle.
  • Remember to always push in the direction of wind.

Saltation is basically the same thing. The difference is that we pick a landing place for the sand instead. The physics is that of a projectile being launch at the local sand angle. The strength of the launch sould be a function of the local wind vector by a factor you can tweak. Or just ignore saltation.

For Suspension, you add a sand saturation value to the wind. Honestly, I suggest to disregard the effects of suspension in the layer. And even in the wind. And use it instead for particle effects.


Note on sand sources: You can have the wind bring sand from off the map (creep from off the map). You can also have the rivers and sea bring sand. However, I would expect that sand from the wind to be main sand input.


Objects

When an object is placed on the sand, it will displace some of it. While the object is sinking, we can pretend sand behaves as a fluid (that is my engineering talking) and use the Archimedes principle.

Any object, wholly or partially immersed in a fluid, is buoyed up by a force equal to the weight of the fluid displaced by the object.

For an object on the surface, yet to displace any sand, this force will be 0. And the object will enter free fall.

An any given instant that the object is sumerged on the sand, we can mock the displaced sand with the depth, the volume of the object, and its density (wich you would need to anotate). I am suggesting to disregard object geometry and fudge it with the density value instead.

Now, that we know the displaced volume, the opposing force is a function of it. Multiply by yet another factor you tweak.

Instead of simulating the whole thing, I suggest to compute, for each object, at what depth these forces are on equilibrium. It is possible that for some object the equilibrium is not reached. You can choose to let the object sink to a given maximun depth (the "bedrock" layer, for example). Once we know the target depth for the object, we can accelerate and decelerate the object in such a way that it reaches that depth (which will be way cheaper).

Note: This requires to be able to quickly query if an object is under sand. You can do that by reading the height from the heightmapon the coordinates on the object and comparing the depth.

As per the effect on the sand... I does not matter if the sand overlaps the geometry of the object (unless we need to worry about transparent objects). If you need it can use the substractive layer to make a hole that fits the object, or even have the sand partially cover it (considering the repose angle). When the object is removed, the hole will be needed. You can simulate it filling up by reducing the feature in the substractive layer.

Optional: You can use the wheigh of the object, the input speed vector, and yet another fector you tweak, to compute an input crater. It would be better to solve the crater on the dynamic heightmap.

Note: Objects doing animations (not just being put on thrown) on the sand should also leave marks. That is the case of footprints. Just add them as features to the substractive layer.


You should also consider the wind pushing objects. You can search how to implement wind and drag.


The wind vector field

Since we only care about the wind on the surface, we can use a 2D vector field. We can represent it as a texture, where a color channel represents direction and another color channel represents magnitud. We can have another color channel for sand saturation, and the last one - if you decide to use - for humidity.

Note: The optional humidity of the air is not the same as the optional humidy map. The optional humidity map is of the and, and affects the repose angle.

This also allows us to upload it to the GPU to be used as input for particle effects, and animations (you can use it animate things moving in the wind in a vertex shader, or animate textures if you need to).

Optional: We can update the wind direction and magnitud with the height map or other relevant obstacles. I would suggest to only do this if a feature reaches a significant height (for a sensible definition of significant). For the method to update it, I suggest to just divert the vectors around the obstacle.

Addendums:

  • You would also have to update the wind direction when one such object is removed or its height is lowered enough.
  • You can push humidity and sand down to the dynamic layer and the huminidy map, if you choose to simulate suspension and have an humidity map, respectively.
  • You could use a 1D perlin noise to decide how to change the intensity of wind over time. I do realize that wind should not be blowing at the same magnitud all the time, and it could be easier to just multiply by a factor that follows a smooth pseudorandom curve (evaluated according to time) than to update the vector field.

It would be interesting to see this integrated into a full wheater system. However, a desert probably does not need that.


The temporary substractive layer

Since features on this layer are not updated all at once, and we need to query features near to the player. I suggest to use a space partitioning structure.

You may also have a suplementary structure that allows to access them as a queue (probably a circular queue is a good idea), that allows a background thread to walk them and remove them as they become old. Also, evidently, when you query them from the space partitioning structure, you can remove any old elements.

Now, when I say it is a substracting layer, I mean you substract the height from its feature (in their appropiate location) from the height map. And that is how this layer allows you to make holes, footprints and similar features.

Addendum: You can also query and remove features on areas that have experienced significant creep (again, for a sensible definition of significant).


Particle effects, et.al.

As I said, the wind will have sand saturation. If you can animate "sand" particles in the direction and speed of the air, around the player (note: you will have to interpolate the surrounding values from the wind vector field), and make these particles more visible as a function of the sand saturation of the wind, you will have the means for sand storms to happen in the simulation. Or, at least, that is the idea.

Aside form that, you can use shaders to animate sand sliding or creeping in the wind. I am aware that this is not often visible, but in some cases it is. So, take your artistic license on this.

\$\endgroup\$
  • \$\begingroup\$ A simple, general approach is definitely fine; it can't be overly complex as it's in real-time, and, most of the stuff that's specific to Egypt can be tweaked with density values and tweaks to the weather. The layered approach is definitely extremely helpful; it is not something that I had considered (for some reason). We may or may not include a more complex weather simulation—that will depend on our game mechanics; it should contribute something other than prettiness—but if we do, then this easily integrates with that. \$\endgroup\$ – Nick Dietz May 3 '18 at 21:02
  • \$\begingroup\$ One question, though: Are you certain that a simple heightmap is enough as opposed to a voxel? Because from imagery it does seem that dunes can, as they “travel” have slopes that are far steeper than the angle of repose. \$\endgroup\$ – Nick Dietz May 3 '18 at 21:05
  • \$\begingroup\$ @NickDietz Creep should modify the heighmap, the result should not go over the ramping angle (which is lower than the repose angle), if that results in a angle, on the other side, that is greater than the angle of repose, it has to slide... so you push the excedent over. All in the direction of wind, of course. That should make the dune advance. Edit: Updated answer, hope it makes sense. \$\endgroup\$ – Theraot May 3 '18 at 21:12
  • \$\begingroup\$ Alright, awesome! Thank you for your detailed response. \$\endgroup\$ – Nick Dietz May 3 '18 at 21:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.