Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Terrain #6121

Open
reduz opened this issue Jan 18, 2023 · 165 comments
Open

Implement Terrain #6121

reduz opened this issue Jan 18, 2023 · 165 comments

Comments

@reduz
Copy link
Member

reduz commented Jan 18, 2023

Describe the project you are working on

Godot

Describe the problem or limitation you are having in your project

Godot users want terrain. Terrain will not be added to Godot, because to make it properly it requires to be a high level feature.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The idea is to create an official terrain plugin that we will maintain and which can be easily downloaded from the asset library.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

This would be an official terrain plugin using GDExtension. This is the list of how it would probably work and the list of features it will have.

Terrain Materials

For modern terrain rendering, texture arrays must be used. This ensures quick access to all textures needed to render terrain. For creating these textures, we would need something similar to how atlas textures work:

  • A texture would need to be imported as a Terrain texture, this type change can happen at the time its assigned to the terrain.
  • The terrain will have material slots, which are basically albedo, normal and ORM and emissive textures. They need to be filled but can be skipped if not used.
  • The textures selected will probably need to be encoded to an RGBA texture array (3 slots). Emission can be encoded in Albedo with alpha be used as interpolation + energy. Normal can use RA format for quality.

Terrain Rendering

Terrain should utilize a standard heightmap with levels of detail allowing to stream regions in and out. This can also be done with a texture array containing the levels in powers of 2 and using standard clipmaps (that are read in the vertex shader) which can fade into higher mip levels to avoid popping.

The shader works more or less like this:

Up to a certain distance (1km ? 2 km?) the shader reads the "material index" texture, which is basically a 16 bits 4096 x 4096 (as example, can be changed) containing material indices.
The 4 materials to blend are obtained, materials are read and blended (most likely using triplanar).
Beyond that distance, to avoid aliasing in the algorithm above, the terrain is blended into low resolution albedo+e, metallic textures that are read directly.

As an aditional step it should also be possible to store a color map to modulate the material color and generate some extra variation.

Terrain Shader

While setting a different shader for every terrain painting material will not be possible (as drawing happens all at once). It should be possible to customize the shader used for drawing. This would allow games to customize a good amount of things:

  • How blending and UV mapping happens for the terrain materials
  • Weather effects such as snow and rain drops
  • Automate some characteristics depending on height or other factors (draw snow on higher parts, draw caustics if underwater, etc).
  • Blending against objects (can use a decal pass and blend against object bottoms based on depth)
  • Specific effects like having custom activity maps (modify blend based on external stuff like footprints, objects being dragged, etc).

But of course, this is up to each programmer to implement.

Foliage

Foliage (grass, rocks, etc) happens at the same resolution as the terrain, storing a foliage material index (or zero if no foliage).

Upon load of a region, instancing of foliage is done with a multimesh generated on the fly and instantiated with a visibilily LOD. Foliage will also be modulated by the terrain modulation color.

Decorations

Decorations (trees, larger rocks and other chunks of terrain) are also a library of meshes that can be manually placed. They are condensed into mutimeshes at the time of drawing for speed up. The terrain system may also decide to generate impostors for groups of decorations if if intended to be seen from very far away.

Scenes

Scenes are instantiated upon proximity (the scene can determine its proximity).

Terrain Storage

The terrain can be stored directly as high resolution material index regions + mipmaps, so only what is needed is streamed-in. Foliage indices can also be saved as well as decoration indices or LODs for different draw distances.

Terrain Editing

Terrain editing can happen in a dedicated editor for the terrain node. The following should be editable directly:

  • Terrain Height
  • Terrain Material painting
  • Terrain modulation painting
  • Foliage painting
  • Object painting (click to place an object)
  • Place a scene (scenes should probably be configured in a list of scenes usable for terrain, including a max draw range).
  • Use brush plugins. Some may come predefined, but can include doing complex scripted painting, such as paiting with a terrain material + foliage + place some random objects.

Holes

The regular (simpler) way to do holes in terrain is to force an INF into one of the vertices. This kills all triangle associated, but will not generally play great with clipmaps, so this needs to be done in a way where only allowed to happen until a certain distance, then the hole pops back in. The hole often has to be "decorated" with geometry so you don't see the clipped triangles.

Procedural generation

To implement procedural generation, it should be possible to override, intercept or complement the functions that fetch data from disk in order to create procedural data. This should help pregenerate all or partial content based on code rather than having to place everything manually if working on a large game.

FAQ:

Q: How do I define the size of the terrain?
A: Ideally you shouldn't, you simply determine a max view distance and the terrain is infinite (it lifts data if it can find it, otherwise its generates terrain at 0m. You can keep editing it as you move around.

Q: Can I do terrain overhangs with this system?
A: No, most games do this by adding extra geometry (like having some large overhang rock and reusing it all over the place). To do this properly, you would probably need a voxel terrain editor, which has different tradeoffs.

Q: Can I do caves with this system?
A: Not with the terrain, but holes can be used to add a cave, which can be modelled in 3D or done with something like GridMap.

If this enhancement will not be used often, can it be worked around with a few lines of script?

No

Is there a reason why this should be core and not an add-on in the asset library?

It will be an official add-on.

@tsilvs
Copy link

tsilvs commented Jan 18, 2023

I hope for a voxel terrain generation to be implemented in Godot someday.

Features that I'd love to see in that case:

  • Naive surface nets
  • Octree voxel data optimization
  • Dynamic LOD
  • Destructible environments
  • Maybe even particle liquids physics?

@donn-xx
Copy link

donn-xx commented Jan 18, 2023

It would be most excellent if you could conjure some way to go beyond the horizontal-plane. Imagine caves, or a curved landscape (say a mini planet). Imagine games with real 3d; underwater and space.

Also, for ultimate terrain freedom, please have a look at what Zylann has been doing with voxels. That could be a fantastic start: https://github.com/Zylann/godot_voxel

@marcinn
Copy link

marcinn commented Jan 18, 2023

Thanks. I would recommend giving possibility to customize/replace shaders. For the foliage I like to modulate albedo in some random way. Also, maybe there should be a possibility to set color/custom data for multimeshes?

If possible, the terrain should have uv2s and should work with LightmapGI.

BTW: would get_bake_bmeshes() be part of the official interface? It works very well and I'd like to rely on it in my addons.

@tsilvs
Copy link

tsilvs commented Jan 18, 2023

Another interesting feature could be tiling textures shuffleing. It could be some kind of a mask with randomized texture tiles grid cell borders and tile rotation to make terrain look more natural.

@rBrenick
Copy link

rBrenick commented Jan 18, 2023

There's an interesting section about different terrain editors in this GDC talk from 2016:
https://youtu.be/brByJ5EVBn4?t=1601 between (26:41 - 28:56)

While Unreal/Unity both have nifty terrain editors, they're missing a level of fine-control that something like Hammer allows. There's no way to do overhangs or cave-like setups with those types of terrain editors. Which means they all have to be authored by artists instead.

It would be cool to have terrain that's actually more versatile than anything else available.

@Zireael07
Copy link

#445 should probably be closed, shouldn't it?

@WrobotGames
Copy link

WrobotGames commented Jan 18, 2023

Custom shaders with layer painting
One thing we really need is the ability to use custom shaders.
It's important that the layer blending values (coming from the texture painting feature) are exposed in the vertex and fragment shader. This adds A LOT of power to the custom shaders, one example here is with snow:
Imagine some complex shader that makes fancy grass, but you want snow in some spots, but not in places where the terrain is steep. Layer1 would be the grass, Layer2 would be the snow. These two can be blended in the shader in a way that would cost an artist a lot of time.

Edit 1:
To make custom shaders possible, the custom shader would need be an extention of the terrain shader (The one that handles stuff like terrain normals).

@1polygon
Copy link

It would be interesting to have the possibility to edit the terrain in runtime. This would be useful for creating procedural worlds or gameplay elements that require deformation like craters.

@Saul2022
Copy link

I think that something that could help terrain, look better by default without uv use of shaders, is the ability to rotate the textures randomly to break seams . Something kinda like the technique roblox used to break seams, called organic patterm or prob by adding by default a noise texture to the terrain texture to break tiling.

@reduz
Copy link
Member Author

reduz commented Jan 18, 2023

Added some FAQ regarding many of the points raised here.

@Arnklit
Copy link

Arnklit commented Jan 18, 2023

I'd like very much to argue against the comments trying to push for a voxel solution.

While voxels are cool, they are definitely more niche than a heightmap solution. If you are making a game with a voxel terrain that is basically the defining feature of your game and probably is part of your gameplay, whereas heightmap terrains are simply useful for world building a ton of 3d game types.

EDIT:
Something I'd like to see included in a heightmap terrain system is a built-in solution for blending meshes into the terrain. I think Unreal uses depth dithering to do that.

EDIT 2:
Another thing not mentioned yet is that each material should have height information to take into account when mixing the materials using the splatmap, otherwise you end up with very unrealistic transitions. Of course it would be great if this height information also could be used to add fine terrain detail with POM or Tessellation.

@Calinou
Copy link
Member

Calinou commented Jan 18, 2023

Something I'd like to see included in a heightmap terrain system is a built-in solution for blending meshes into the terrain. I think Unreal uses depth dithering to do that.

BaseMaterial3D proximity fade can be used to achieve this. However, to improve performance and avoid transparency sorting issues, we should add a mode that makes proximity fade use dithering instead of forcing alpha blending on the material (or make it use dithering unless the material is already using alpha blending).

or for changing the texture blending algorithm for something else (as in, not triplanar).

As an optimization, it might be worth trying biplanar mapping.

@Arnklit
Copy link

Arnklit commented Jan 18, 2023

BaseMaterial3D proximity fade can be used to achieve this. However, to improve performance and avoid transparency sorting issues, we should add a mode that makes proximity fade use dithering instead of forcing alpha blending on the material (or make it use dithering unless the material is already using alpha blending).

I don't think you could proximity fade without rendering to the transparent render path. That's why I suggested the depth offset dithering thing instead. But I don't know if that only works in a deferred renderer.

@Calinou
Copy link
Member

Calinou commented Jan 18, 2023

I don't think you could proximity fade without rendering to the transparent render path. That's why I suggested the depth offset dithering thing instead. But I don't know if that only works in a deferred renderer.

I've just tried to replace alpha blending with dithering and can confirm it still goes through the transparent pipeline, likely because it has to read DEPTH_TEXTURE. (I removed the line that sets ALPHA.)

diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index d5c3f7730b..3bddbeda54 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -1249,7 +1249,13 @@ void BaseMaterial3D::_update_shader() {
 		code += "	float depth_tex = textureLod(DEPTH_TEXTURE,SCREEN_UV,0.0).r;\n";
 		code += "	vec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV*2.0-1.0,depth_tex,1.0);\n";
 		code += "	world_pos.xyz/=world_pos.w;\n";
-		code += "	ALPHA*=clamp(1.0-smoothstep(world_pos.z+proximity_fade_distance,world_pos.z,VERTEX.z),0.0,1.0);\n";
+		// Use interleaved gradient noise, which is fast but still looks good.
+		code += "	const vec3 magic2 = vec3(0.06711056f, 0.00583715f, 52.9829189f);";
+		code += "	float fade2 = clamp(1.0-smoothstep(world_pos.z+proximity_fade_distance,world_pos.z,VERTEX.z),0.0,1.0);\n";
+		// Use a hard cap to prevent a few stray pixels from remaining when past the fade-out distance.
+		code += "	if (fade2 < 0.001 || fade2 < fract(magic2.z * fract(dot(FRAGCOORD.xy, magic2.xy)))) {\n";
+		code += "		discard;\n";
+		code += "	}\n";
 	}
 
 	if (distance_fade != DISTANCE_FADE_DISABLED) {

@reduz
Copy link
Member Author

reduz commented Jan 18, 2023

@Calinou For a while I thought we should have an extra render pass called decal pass where you can do those things and still remain in opaque pass. This could be used to render the terrain (after everything else) and do a bit of blending into objects that go into the ground.

@MaxIsJoe
Copy link

Will there be Terrain Partitioning support for larger scenes to ease the load on both the editor and runtime?
If yes, is it going to be like Unreal's world partitioning or is it going to be entirely proximity based?

@reduz
Copy link
Member Author

reduz commented Jan 18, 2023

@MaxIsJoe Godot can just handle this with the scene system transparently, no need to implement that kind of things that are more unity/unreal design workarounds.

@Duroxxigar
Copy link

Why was this created instead of continuing discussion on the most popular one?

As for the world partition stuff - it really is pretty straight forward to implement in Godot with the scene system. I did it long before WP was even announced in UE5.

@reduz
Copy link
Member Author

reduz commented Jan 18, 2023

@Duroxxigar this is a proposal with a specific implementation, its easier to discuss details of it here. Can link to it from the other one if you wish.

@mrtripie
Copy link

I think not allowing custom shaders would be quite limiting for a modern terrain system. Shaders allow for several possibilities:

  • Dynamic effects such as getting wetter as it begins raining, with puddles forming based on noise.
  • Blending different textures automatically normal of the mesh, such as having grass where its pointing upward, and cliffs where its pointing to the sides. Placing snow on top as well. This frees up a lot of manual work for the artist where they would have to match the texture painting to the height sculpting.
  • Breaking up tiling automatically, using techniques like rotating tiles, adding color noise, etc. Which is very important for terrains as your textures can only be big enough to tile every few meters.
  • Blending with textures tiled at a larger scale to make distant terrain look good. I believe this technique often adjusts how much the large and small detail textures are blended based on camera distance.

I would suggest having the Terrain3D node have a material property that can take a ORMTerrainMaterial3D and ShaderTerrainMaterial3D resource:

  • Each would have properties to set the number of texture types to blend between, and maybe an option to give the different texture types names (ie: Grass, Sand, etc).
  • ORMTerrainMaterial3D would also have for each texture type options for Albedo, Normal and ORM
  • ShaderTerrainMaterial3D would also have a shader property, and the shader will allow pass in the masks for each texture type, which can be used to blend different textures and add different custom effects to each.

@ozzr
Copy link

ozzr commented Jan 18, 2023

Terrain stiching: Just split the world in smaller patches and force each patch to share the edge pixels.
terrain_patches

Terrain spawning: I have been experimenting for porting my Terrain Module and using simple mesh instances in Vulkan is fast enough as long as they use the same mesh resource (lod morphing should be implemented in the vertex shader) for GLES renderer it should be capable of fall back into multimeshes.

Biomes could be made following the Horizon Zero Down presentation on this topic available at their webpage. Here Compute shader should come very handy to speed
up the calculations at least when using the vulkan renderer

@reduz
Copy link
Member Author

reduz commented Jan 18, 2023

@mrtripie You should be able to have a custom shader for the whole terrain to do the things you mention. What is likely not possible is custom shaders for each terrain paint material.

@reduz
Copy link
Member Author

reduz commented Jan 18, 2023

@ozzr I prefer not go the terrain stitching route and just allow infinite terrain editing. Its just a lot more user friendly to me.

@ozzr
Copy link

ozzr commented Jan 18, 2023

Good point, however I find that a Unity like Terrain should be more Godot friendly

@ozzr
Copy link

ozzr commented Jan 18, 2023

Horizon Zero Down GDC presentation this is the presentation I was talking earlier for Biomes

@reduz
Copy link
Member Author

reduz commented Jan 18, 2023

@ozzr I think with the right hooks it should be possible to generate procedural content to do something like this.

@Mikeysax
Copy link

Mikeysax commented Jan 18, 2023

I would imagine that foliage painting would potentially be a performance issue if a user attempts to paint hundreds of thousands of grass meshes in a location. Given this, I would imagine that the current MultiMeshInstance3D node would potentially need to be more flexible and provide more features similar to the Scatter plugin? (ie https://github.com/HungryProton/scatter)

Update: I re-read the proposal and if I understand this correctly, painting anything will index the foliage instance for use in a multimesh instance per terrain chunk? Maybe my concern is non-existent?

Update 2: Also, if entering something like a Dungeon or a Cave from the terrain, would toggling the visibility on the terrain or using an OccluderInstance be enough to prevent the terrain from rendering? Would there need to be alternate methods of doing this for performance reasons, like an AABB on the terrain or individual terrain chunk / region?

@BastiaanOlij
Copy link

Just my 2cents on the subject.

First, interesting reading through many peoples reactions and for me this only underlines more why it is so important that a terrain module becomes a plugin. The last thing we want is a bloated terrain module that supports every possible terrain system that is out there. The proposal here is for a terrain module based on height maps as it is one of the most common systems founds in large / open world games. It strikes a good balance between performance and a usable terrain that can be further dressed up with meshes.
I see a number of mentions about more complex terrain systems, I still have a wish to implement a dual contouring terrain system some day which would allow caves and destructible terrain but also taxes the system more and is thus much less suitable as a generic solution that also targets lower end computers. It makes far more sense for this to be an alternative terrain plugin, then trying to embed multiple competing systems in one terrain system.

Second, on the proposal itself, I'm missing a few key features that I think should be added in.

Physics

In order for the player (and NPCs) to interact with the terrain, there should be a tie in to the physics engine. As heightmap textures are streamed in, these textures should be converted to heightmap data while still in CPU memory that the terrain system can submit to the physics server. The terrain system can manage this fully so the terrain is automatically managed as a static collider.

A question here is what to do with terrain that isn't loaded, a persistent NPC might run off into the distance as part of a quest and fall through the map when it runs past what is loaded.

Another question here is whether to incorporate collisions for bigger foliage like trees. Personally I actually believe that foliage systems are separate from the terrain system but should be able to access terrain data for placement.

Scene management

As the terrain module loads in chunks, or expels chunks of terrain that are far enough away, there should be some mechanism to hook into this, be it through emitted signals or some further automation, to load in scenes that contain the rest of the game data related to that chunk of the map.

Especially on open world games you don't want to keep the whole worlds worth of buildings, NPCs, and other objects in memory. You're loading those alongside new chunks of terrain.

Stream optimization

This may be overkill for our needs and possibly not as much a problem as it was in yesteryears, especially with modern PCs and consoles having plenty of disk space and copying game data onto harddrives instead of reading them from source media. But if terrain data is stored on fixed media, say Bluray, the maximum data throughput and random access costs can become a hindering factor to getting terrain data streamed into the game fast enough.

Many terrain systems deal with this by duplicating terrain data in various reordered ways to ensure optimal loading no matter the direction of movement. Space is cheap in this case.

Best practice guides

This I think will come naturally when a terrain module becomes widely available but there are a number of common pitfalls and issues around large open world games that we may want to per-emptively catch and educate people about.

An example of this is the aforementioned NPCs falling off the map because a quest line sends them into an area of the map no longer loaded.

Another is dealing with NPC persistence as chunks of the world are unloaded and reloaded.

@SlashScreen
Copy link

Interesting. Can GDExtensions expose stuff to GDScript? I have a plugin ive been working on that generates an entire heightmap all at once, after compositing "stamps" together to generate a heightmap. How would this work?

@mohsenph69
Copy link

Interesting. Can GDExtensions expose stuff to GDScript? I have a plugin ive been working on that generates an entire heightmap all at once, after compositing "stamps" together to generate a heightmap. How would this work?

If you want to generate your heightmap with some function you can also do it now even in gdscript
There is function which is called set_height_by_pixel(x,y,value) you can use something like perlin noise and generate a terrain
It is true that height-map is divided to different region but with this you can imagine the entire terrain like a big image which you can modify
This function will take care of shared pixels and everything else

But I don't understand the second part of your question if you can explain me more

@SlashScreen
Copy link

My plugin creates a heightmap. How it does it isn't important. Would I be able to set the entire heightmap all at once and have it update? Can I also update specific regions?

@mohsenph69
Copy link

Yes off course you can do,
You can update a specific region or entire terrain, put this set_height_by_pixel(x,y,value) inside a loop
for example if your terrain is 1025 by 1025 you can do this

for x in range(0,1025):
    for y in range(0,1025):
        var value = generate_value_with_your_plugin_base_on_x_y
        set_height_by_pixel(x,y,value)

But this will take sometimes, especially if your terrain is big, if you update a small region there is no problem
If you want to make it faster you should use thread, and basically you break the loop above into separate loop and you calculate each part in a different thread
I used thread for generating normals and that made normals generation at least 10 time faster which is alot

@SlashScreen
Copy link

perhaps that would be useful to include with the API?

@Saul2022
Copy link

Thanks for testing Saul2022

How much is big the terrain is it 8km by 8km? is SDFGI

Thanks, for the reply, the terrain size is the same as the one from your tutorial though following it step by step and downloading the RAW link, and it has sdfgi off( because my igpu can't handle it , at least until they rework it maybe), and ye it can help that.

@mohsenph69
Copy link

Thanks for testing Saul2022
How much is big the terrain is it 8km by 8km? is SDFGI

Thanks, for the reply, the terrain size is the same as the one from your tutorial though following it step by step and downloading the RAW link, and it has sdfgi off( because my igpu can't handle it , at least until they rework it maybe), and ye it can help that.

Thanks to you Saul2022 that you test my terrain
You can check the new version of my terrain plugin it has also height brushes
These will work on my system good but on lower system still need to be optimized, if test that let me know how does that work
thum
https://github.com/mohsenph69/Godot-MTerrain-plugin

@TokisanGames
Copy link

TokisanGames commented Jul 17, 2023

The C++ based editable terrain system @outobugi and I have been working on for the last several months has been released. MIT License. Still in alpha, but stable. We're starting to incorporate it into our game, Out of the Ashes.

https://github.com/TokisanGames/Terrain3D

Overview on youtube:

https://www.youtube.com/watch?v=Aj9vWIEaFXg

So we don't clutter this thread with too many messages about any specific system, you can review issues and documentation on our repository page. Or you can join my discord server. https://tokisan.com/discord

@Saul2022
Copy link

Thanks to you Saul2022 that you test my terrain You can check the new version of my terrain plugin it has also height brushes These will work on my system good but on lower system.

Tested it out and works fine for my igpu, though there´s some performance degradation sometimes when sculpting and stays like that until i dissable the sculp brush. I think it could be good to move the conversation to a discord server if you want to create it for your terrain, so more people may know about it, and it could bloat bless this chat.

editor_screenshot_2023-07-18T192209

@mohsenph69
Copy link

Thanks to you Saul2022 that you test my terrain You can check the new version of my terrain plugin it has also height brushes These will work on my system good but on lower system.

Tested it out and works fine for my igpu, though there´s some performance degradation sometimes when sculpting and stays like that until i dissable the sculp brush. I think it could be good to move the conversation to a discord server if you want to create it for your terrain, so more people may know about it, and it could bloat bless this chat.

editor_screenshot_2023-07-18T192209

Hello Dear Saul2022
Thanks for testing my Terrain
Yeah I know what is the problem in future I will find a way to handle that
Basically it tries to send many texture to gpu I should find a way around that
Right now I am busy with grass after getting some result I will take a look at it

@mohsenph69
Copy link

My Achievment for Grass

grass.mp4

This grass is generated with exported data from my plugin

This also has level of detail like terrain
For example this is LOD0
grass_tex_lod0

And this is LOD4
grass_tex_lod4

You can imagine LOD between

Offcourse if you attach a good Shader to it it will be much more nicer
Still working on it, its performance still can be increased
it will be also possible to paint grass if this will work, but still I am not sure about it

@mohsenph69
Copy link

grass

Grass Demo, It is not on Github yet but you can watch that on Youtube:
https://www.youtube.com/watch?v=w31Mrag05cc

@ozzr
Copy link

ozzr commented Nov 16, 2023

editor_screenshot_2023-11-16T093837

Hi, everyone! this is my landscape system taking its final shape.
I must say Godot 4 looks really nice even tough I am not an artist.

I already started working on the Editor itself, and some other quality nodes to modify the landscape.

I am using clip-maps for streaming the textures data, and the collision and quad-tree elevation limits are either prebaked on save or generated at runtime and stored at the user folder as custom files and then streamed on demand.

The system makes heavy use of multi-threading.

terrain_demo_000

terrain_demo_001
terrain_demo_002

Concerns

  1. Updating the clipmaps is smooth until several layers need to be updated at once. This is because of the lack of partial texture update
  2. Biome rendering lowers FPS dramatically if not used responsibly.
  3. The amount of data generated is huge depending on map resolutions and vertex spacing

Questions

  1. Do multimeshes switch lods internally? I am currently doing this manually, but I would like to know if there is any trick I could use to decrease the impact of the biomes while rendering.

@Calinou
Copy link
Member

Calinou commented Nov 16, 2023

  • Do multimeshes switch lods internally? I am currently doing this manually, but I would like to know if there is any trick I could use to decrease the impact of the biomes while rendering.

The entire MultiMesh (or CPUParticles3D) switches LODs at the same time (all use the same LOD level), but individual instances can't use different LOD levels.

@Flynsarmy
Copy link

One issue I'm not sure has been brought up here is that making Terrain an official plugin might not be feasible due to the of time the team has to work on/pay attention to it.

It's been 1.5 years as of the time of writing since this proposal and as far as I'm aware we still don't have the plugin reduzio mentions. Even if one was created, would adequate time be dedicated to adding features, fixing bugs and reviewing/accepting PRs on this separate plugin compared to one built in to Godot?

Third party addons are also not the answer here. They don't get the support a first-class feature gets, and they have too many issues with newer versions of Godot - for example the most popular current addon is Terrain3D which doesn't work correctly in the latest Godot Beta and as far as I'm aware requires recompiling for each new version of Godot released which almost no-one knows how to do.

Terrain is clearly one of the most requested features for 3D. It's brought up in literally every 'What are we missing?' thread. Yes it's a higher level feature and yes, there's no one implementation that can cover literally every use case, however there is an implementation that can cover the majority of use cases, and anything not covered can then have an addon made for it later. Adding terrain to core is a better solution IMO to what we're doing at the moment which is nothing.

@TokisanGames
Copy link

TokisanGames commented Jun 20, 2024

It's been 1.5 years as of the time of writing since this proposal and as far as I'm aware we still don't have the plugin reduzio mentions.

Juan has made it clear multiple times that he doesn't want Terrain built in to Godot. This PR was a way to collect thoughts for a plugin implementation by someone, not a plan for him implementing a system. There are at least 5 good terrain plugins available for Godot, plus the built in gridmap system and other solutions, that provide enough infrastructure to meet the needs of most developers.

Third party addons are also not the answer here.

They are the only answer. Even if you were to become a core developer intending to be the one to implement and maintain a core terrain system, as stated Juan and Co don't want it.

They don't get the support a first-class feature gets

This I partially agree with and have expressed. However, the core team has been good about providing help on our tickets and in the developer chat. We have found workarounds for deal breaking issues, like saved resource files can't be larger than 1gb. And there has been nothing stopping us from contributing fixes or adjustments to the engine or GDExtension except time or need. As a plugin developer, I don't have any major issues or complaints.

and they have too many issues with newer versions of Godot - for example the most popular current addon is Terrain3D which doesn't work correctly in the latest Godot Beta

I don't intend to sound rude, but this is frankly a misunderstanding of beta status. It is an unreasonable expectation that 3rd party plugins will always support every unstable version of Godot. The core developers are changing the engine all the time, and breaking things. It is a moving target. There are still months of development for Godot 4.3 to go through 3-6 betas, then 2-4 RCs.

The open source nature allows experienced developers to use development versions, with the expectation that things are not supported, may require self-support, and may not even work at all. They are not intended for use in production or by inexperienced developers who should only be using stable versions of the engine and plugins.

and as far as I'm aware requires recompiling for each new version of Godot released which almost no-one knows how to do.

You are very mistaken. Terrain3D has worked with forward stable versions since 4.1 last year, due to extended features in GDExtension. Our CI system builds Terrain3D on every push, providing prebuilt binaries for stable and development versions. And we have many developers who are building from source, by following our well documented process.

Occasionally the engine devs break things in future versions which should be obvious that our older version cannot support without a change. Those changes are sometimes pushed into the stable version, but usually put into our development version.

Our stable version works fine with the stable version of Godot. That is the only scenario newer devs should be using until they become capable of self-support.

I can use the latest development version of Terrain3D (available as precompiled nightly builds) with the stable or latest Godot beta just fine. Though the latter is still not supported for the reasons listed.

Terrain is clearly one of the most requested features for 3D. It's brought up in literally every 'What are we missing?' thread.

In the past, it was the most missing, most needed feature. That's why Roope and I built Terrain3D. Now with 5+ systems, any future mention in "what are we missing" threads is frankly due to lack of knowledge of the terrain ecosystem. The solution is sharing and improving the existing systems not waiting for over worked core devs to write a 7th system.

Here's the full list of Terrain Systems for Godot 4 that I'm aware of:

Plus there are partial solutions such as:

  • The built in Godot Gridmap for use with your own meshes.
  • Sculpting a mesh and texturing it in blender, and using one of the fine placement plugins for foliage and world assets such as:
  • Your own custom mesh / foliage generation, of which there are tutorials and code that can be found easily, such as the excellent videos by devmar.
  • There also appears to be a terrain generator (and editor?) built into the Roblox-clone Godot fork, The Mirror, but I have not looked into it.

So I hope this clears up some misunderstandings about the Godot terrain ecosystem and our plugin specifically.

@reduz Unless you plan to change your mind and create a native terrain system, I suggest that the 5+ available solutions have adequately accomplished this proposal and perhaps it's time to close this thread. The only thing not really covered is any "official designation" that you mentioned. I assume that requires more internal discussion and a separate proposal if public feedback is desired. Perhaps in lieu of an "official status" the above information should find its way to a "recommended solutions" page in the documentation or website that lists known working terrain, rivers, oceans, skies, roads, and other commonly needed systems.
cc: @akien-mga

@rossbridger
Copy link

@TokisanGames I agree that the terrain system is too big to be included in core Godot engine, but we probably don't need 5 solutions for the same functionality. Also, state-of-art terrain systems utilize compute shaders to archive faster speed, whereas most existing Godot terrain plugins haven't caught up with it yet. It might be beneficial if Godot can dedicate an official terrain plugin so that everyone concerned can pool their efforts onto developing one single terrain plugin.

@TokisanGames
Copy link

@rossbridger Compute is entirely unnecessary for runtime as it's not a rendering pipeline. It is beneficial only for editing, and even then, only for large sections >200m, or for complex options like smoothing and erosion. It also excludes all OpenGL users. We will support some sort of GPU editing in the future. Zylann's HTerrain already supports GPU editing via viewports. At runtime, our terrain already runs on the GPU and we are regularly increasing features and speed. In the open source community, people contribute where they want. We have a pretty good team of contributors with some amazing MVPs.

@rossbridger
Copy link

Compute is entirely unnecessary for runtime as it's not a rendering pipeline.

Since your implementation uses geometry clipmap, that part is true in your case. However, more recent terrain system like Unity's CBT and Call of Duty's terrain system use compute shaders to update its runtime terrain data structure per frame. I was looking at bevy engine's terrain the other day, it also uses compute shaders for runtime steps like quadtree subdivision and frustum culling. I think it might be superior to all existing terrain systems in Godot so it would be nice if someone can port it to Godot and do a benchmark.

It also excludes all OpenGL users.

If someone is developing a game targeting compatibility profile, it's very unlikely it needs a massive terrain system anyway.

@CsloudX
Copy link

CsloudX commented Jun 21, 2024

I wish some comm features(like terrain, behavior tree etc) can be core. not addons. or, can we mark some addons as offical addons? eg, where was some terrain addons, and like test some. very addon has something i like, and some miss feature thad i need, i don't know which one i should select, and i don't want make report for every addon's author. and, i'm afraid some day the addon that i selected stop update. if where was a offical addon or be core. i'm clear to select and report bugs.

@Saul2022
Copy link

Saul2022 commented Jul 2, 2024

Since your implementation uses geometry clipmap, that part is true in your case. However, more recent terrain system like Unity's CBT and Call of Duty's terrain system use compute shaders to update its runtime terrain data structure per frame.

I get the point though for this terrain the cost is not really on rendering the terrain thx to geo clipmap, but more on the base shader cost as it lets have like 32 textures and 32 foliages with high distances and good lods(that in my case i noticed almost no pop in). For the shader there are already feature request like runtime virtual textures and normal map bake in play mode so it simplifies the shader and the performance gets better.

@ElsAr4e
Copy link

ElsAr4e commented Jul 2, 2024

If you've already have that many addons you would need a setting like opt-in to disable a built-in terrain system - especially if you want to use terrain addons.

And what about mobile? Can Godot Engine for Android handle a built-in terrain system - especially cheap Android devices?
Because ideally desktop and mobile versions should be the same? (I don't want a mobile version that does not have a built-in terrain system but a desktop version that has a built-in terrain system -they should both be the same)

@Saul2022
Copy link

Saul2022 commented Jul 3, 2024

And what about mobile? Can Godot Engine for Android handle a built-in terrain system -

It can as it works on both forward+ and mobile renderer.

@jkulawik
Copy link

jkulawik commented Jul 3, 2024

While I understand why putting a powerful terrain feature into core is unwanted, I think we also have a bit of an XY problem here.

I think for most use cases, all that users really need is a basic terrain mesh, and to make simple adjustments to it in a WYSIWYG way - namely basic sculpting and texture (material) painting. Making adjustments externally, without a reference to the placement of objects in a scene, is just too imprecise and annoying for any real work. Hybrid workflows where some assets are placed from Blender and some in the engine don't really solve this issue.

So what I'm thinking of is something like EditableMesh3D node with a built-in editor mode which:

  • Allows basic sculpting of the mesh
  • Allows painting a texture on the mesh, intended to be used with primary colors to then use in a shader1
  • Saves the edited mesh as a resource
  • (Nice to have) supports stitching and editing multiple of these meshes together, which allows users to optimize performance by not having to use one massive terrain that's rendered in its entirety at all times

Since this would be a regular mesh rather than some plugin construct, it would integrate well with existing features such as:

  • Collision generation (!)
  • Navigation meshes (!!!)
  • Scatter plugins
  • MultiMesh auto-placement
  • Snapping objects to the floor

I know this for a fact - I implemented this with a regular Mesh3D myself because back then none of the terrain plugins worked with navigation meshes. However, updating the mesh was a sticking point that makes this method tedious to work with and the part that would need core support.

While I believe this would cover most use cases, I'm not sure how big of a feature such an editor would be, and by extension - if it would fit in core.

P.S. I also used this method with a heightmap, but this method is better kept for more advanced terrains like the plugins mentioned earlier. Generating heightmaps from Blender is a bit scuffed, and making a mesh displaced with a heightmap shader match the collision mesh without dynamic subdivision is kinda impossible. Also the collider had to be manually updated after each heightmap import, which wasn't great.

Footnotes

  1. Namely, the mesh would have a proper UV and a regular texture would be painted onto it. Black and RGB would serve as 4 texture maps in a shader to render the terrain as the user wants. A similar method which uses vertex painting instead of textures is sometimes mentioned as well, but in my experience it ends up looking uglier because of reduced fidelity.

@rossbridger
Copy link

rossbridger commented Jul 6, 2024

I just took another look at bevy's terrain system, and I noticed that it doesn't generate any mesh data, but it feeds its quadtree data into the vertex shader as SSBO and computes vertices directly on the shader. This can be a huge memory optimization but it seems Godot doesn't support SSBO yet.

@TokisanGames
Copy link

Vertexless meshes certainly do work in Godot. I haven't implemented it in Terrain3D yet, but it's on the list for both terrain and foliage meshes.

@Zylann
Copy link

Zylann commented Jul 6, 2024

Rendering primitives involving little/no vertex buffers is something I'm experimenting in a non-Godot project (not heightmap terrain, but similar needs), and it's such a big win for my project I'm keeping with it. Unfortunately Godot might still lack an optimization feature for doing the same thing I do.

I should probably open a proposal, but to summarize:
I have many meshes with no vertex buffers, but they do have an index buffer. That index buffer is shared for all the meshes, yet every mesh still have their own different number of primitives, so they use only a fraction of the index buffer. I don't think Godot has an API for that "sharing" to happen, AFAIK you only get to provide a PackedInt32Array in every mesh.
This is important because my project exclusively renders quads. If I don't provide any index buffer, I end up with the vertex shader running 6 times per quad instead of 4 (with corresponding VERTEX_ID going by group of 6 instead of 4). So in Godot I would have to provide an index buffer for every mesh, which is wasted memory because it's the same every time, and wasted GPU if I don't because of extra vertex buffer runs.
(on a more general note, having a more low-level mesh resource with actual GPU buffers in it could help, instead of having the very abstracted, wasty/Variant-data-only mesh resources we have now).

When coupled with the ability to read from an SSBO in the vertex shader, it allows to save a lot of memory by having more control on how geometry is provided. That might not be feasible in the compatibility renderer though. Using a texture is also possible when SSBO is not available, but is inconvenient and probably slower.

@rossbridger
Copy link

rossbridger commented Jul 6, 2024

@TokisanGames The technical difficulty here is passing an SSBO to vertex shader, which is not supported by gdshader (working with RenderingServer directly and writing raw GLSL might work, but I haven't seen anyone ever done that, and at this point one probably can use VisualInstance3D or GeometryInstance3D directly).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests