- Home /
Lava flow simulation on terrain
Alright, so I've been having a bit of fun trying to recreate the Populous 3 'Volcano' spell on a Unity terrain. Here's a video of what those look like: https://www.youtube.com/watch?v=izD_OZmyt0o. In comparison, here's a video of what I've got so far: https://www.youtube.com/watch?v=_-MVMuDuuhk.
Anyway, my current method has 2 major problems:
I use a texture offset to give the idea that the lava is flowing, but that only goes in 1 direction. It looks really silly when you look at the back of the volcano and the lava appears to be flowing upwards.
Updating the splatmap prototypes on a terrain is way too expensive. Terrain I'm using here only has 3 textures on it, adding more makes it even slower, and it already drops to like 12 fps.
There are also a few minor problems - I don't make a 'hole' in the top, but I can do that easily enough (just didn't feel like coding it in yet), - I cover my entire volcano in lava, instead of having a few 'trenches' (I haven't really looked at doing that, yet, though) - and I'm not happy with how the lava-to-rock conversion goes, but that's mostly because I haven't really looked at what that should look like yet.
Here is my method for doing the lava flow as it looks now:
void LavaFlow(){
float percentageTimePassed = timePassed/flowTime;
for(int ix = 0; ix < texDiffX; ix++){
for(int iy = 0; iy < texDiffY; iy++){
float currentRadiusSqr = (textureCenter-new Vector2(ix, iy)).sqrMagnitude;
float radiusPercentage = currentRadiusSqr/radiusSqr;
if(radiusPercentage < percentageTimePassed*flowSpeed){
splatMap[iy,ix,lavaID] = 1f;
splatMap[iy,ix,groundID] = 1-splatMap[iy,ix,lavaID];
}
}
}
tData.SetAlphamaps(minTX,minTY, splatMap);
}
Method that turns te lava flow to rock is almost the same (actually, I should probably turn those into a single method and pass some parameters), it just changes different textures and starts later.
Oh, and the texture offset script for my lava is just this:
Terrain terrain;
SplatPrototype[] splats;
public Vector2 offsetSpeed;
// Use this for initialization
void Start () {
terrain = GetComponent<Terrain>();
splats = terrain.terrainData.splatPrototypes;
}
// Update is called once per frame
void Update () {
splats[1].tileOffset = splats[1].tileOffset + offsetSpeed * Time.deltaTime;
terrain.terrainData.splatPrototypes = splats;
}
But I should probably use something completely different instead. Anyone have any suggestions on how to deal with the major problems I outlined?
I would avoid doing this with the terrain directly. By all means deform your terrain to create the volcano itself. But for the lava, I would procedurally generate a mesh that has a custom shader attached to it (so the lava texture does EXACTLY what you want [hint: you'll be manipulating uvs in the shader). On each frame update, modify the mesh to get a nicer flow (I suggest fractal noise).
This will be more difficult to do, but in the end you'll have a better result, as you'll be able to add some depth to the lava flow ins$$anonymous$$d of them being flat.
hmm, I hadn't thought of procedurally generating a mesh. It could work...
Hmm. I do see some problems with that approach, though. If I use mesh generation to set the 'boundaries' of my lava flow, I'd end up with far too many vertices on a slower flow and I'm not convinced it would look good.
Alternatively, I could create the full mesh that sets the flow boundaries right away, then do something in the shader that sets it transparent and then shows the lava texture depending on some time value. I'd still have to continously deform it to fit the shape of the volcano (while it is raising), though, and I'm not sure how I'd go about that. Hmm. Well, unless...if I decide that all volcanoes have the same size and shape, I could just use a premade mesh ins$$anonymous$$d... that /may/ look good...
Anyway, thanks for the idea, I will experiment.
You don't have to add vertices all the time, you can move them until you reach a predefined maximum edge length/triangle area. Still difficult though.
To answer your question about continuously defor$$anonymous$$g it to fit he shape of the volcano, that is fairly easy. just iterate through all the vertices of your mesh, fire a ray down to the terrain just above the mesh, then use the hit as the position (maybe with a little y padding). It should be fast enough. Better yet would be to incorporate it into the code that creates the volcano over time. just an extra line of code or two to set the relevant vertex of the mesh as well.
$$anonymous$$oving vertices appropriately would be pretty hard. Well, not the moving part, but getting the correct ones. I'd have to look on how I construct the mesh first to see how hard, though. Or,as I said, I could just start with a plane (or circle), with a number of subdivisions, and just deform that to match the terrain. Getting the proper height shouldn't really be a problem.
(by the way, iterating over all the vertices then getting the terrain height at the position doesn't require a raycast. All you need to do is get the world position of that vertex, then project that onto the terrain heightmap using heightmap width and height. That's probably faster then raycasting).
Hardest part would be the shader. No idea how to make a single texture look to be moving in a different direction on different points on the same mesh. Getting that direction may also be a bit difficult.
Answer by Cow-Necromancer · May 03, 2015 at 07:42 AM
you could have a big texture that goes outwards, like this:
this is what you have:
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
this is what you could do: \ | /
\ | / and so one just say it goes center outwards
Answer by Runalotski · Jul 02, 2015 at 12:20 AM
For the flowing lava look of it in the video you sent the texture for the lava dosent even move if you changed your texture for solid red it will look like it maybe add a second yellow texture over to top after a short time if you are going to reCreate the original. however what you have looks awsome!
Your answer
Follow this Question
Related Questions
Disabling colliders in Terrain Trees? 1 Answer
Huge world without huge lag? 1 Answer
Splitting mesh into chunks 1 Answer
Basic drawcall batching question 1 Answer
SketchUp Sandbox vs. Unity Terrain 2 Answers