Procedurally generated 2D Terrain that >looks< 3D?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Oian

Hi all,

i want to recreate the terrain (ground, not objects) of the game “Knights and Merchants” (see image) as close as possible. How would i go about doing that?

This game is in 2D, but the terrain obviously looks 3D with shadows, mountains, archers will do more damage when they are on “higher” terrain, etc…

Basically my main problem is, how do i even start?
Do i need to use a TileMap for this? Wouldn´t that just be for squared and flat tiles? How would i implement Shadows then? Should i build a custom TileSystem instead?

Should i do the the terrain just straight up in 3D with meshes (because there are more tutorials on this) and just lay 2D sprites on top of it? I found “MeshInstance2D”, is this approptiate for this kind of task?

Can i perhaps use shaders for this? If so, how?

I know that i need to use procedural generation with white noise etc. at some point. And generating simpel rectangle tiles divided in bioms should also not be a big problem.
But how do i make a 2D ground look 3D with shadows, etc.?

And if you cant answer my original question exactly, please give me some keywords, topics or nodes to look up on my own, that might prove useful here.


(oh yeah, and im using godot 4 currently, but answers for godot 3.x would alos be welcome!)

enter image description here

:bust_in_silhouette: Reply From: zhyrin

With a noise generator you can create a heightmap. The image will be grayscale, dark areas being lower, bright areas being higher.
You can use this to determine how high characters are.

If you want to procedurally shadow and highlight your terrain, you can do that with a shader:

  • In the shader you sample the noise texture at the current location.
  • You also sample the noise texture closer to the sun’s position (= the reverse of the sun direction)
  • If the current location’s sample is darker (lower in elevation), you darken the current output pixel
  • If the current location’s sample is brighter (higher in elevation), you highlight the current output pixel

But the simpler answer would be to use prerendered images as background. If you look at a steep cliff in game, you can see the stone texture streching on the mountain side, this indicates they built the background in 3D software and rendered it to an image.
If you don’t want pixel perfect height data, you could use a TileMap and associate each tile type with a height. You can turn the tilemap inivisble in-game while still querying what type of tile a character is on.

Here is a video on noise texture being used to create a TileMap.

I think you can define smooth transitions in a tile map, and using the same noise texture you use for generating the tilemap, you can use the shader I outlined earlier to add per pixel shading to it.

Here you should look at the texture() functions: Shading language — Godot Engine (stable) documentation in English

Hope this helps you in the right direction.

Great answer, thank you!

Oian | 2023-02-10 11:11