GithubHelp home page GithubHelp logo

tokisangames / terrain3d Goto Github PK

View Code? Open in Web Editor NEW
1.6K 33.0 95.0 84.92 MB

A high performance, editable terrain system for Godot 4.

License: MIT License

Python 0.69% C++ 57.26% C 0.45% GDScript 29.09% AppleScript 0.57% Shell 4.03% PowerShell 0.71% GLSL 7.19%
godot-plugin godot4 terrain gamedev-tool gamedevelopment godot-addons godot-engine terrain-editing terrain-visualization game-development gamedev godot heightmap heightmap-terrain

terrain3d's Introduction

Terrain3D

A high performance, editable terrain system for Godot 4.

Features

  • Written in C++ as a GDExtension plugin, which works with official engine builds
  • Can be accessed by GDScript, C#, and any language Godot supports
  • Geometric Clipmap Mesh Terrain, as used in The Witcher 3. See System Architecture
  • Up to 16k x 16k in 1k regions (imagine multiple islands without paying for 16k^2 vram)
  • Up to 10 Levels of Detail (LODs)
  • Up to 32 texture sets using albedo, normal, roughness, height
  • Sculpting, holes, texture painting, texture detiling, painting colors and wetness
  • Supports importing heightmaps from HTerrain, WorldMachine, Unity, Unreal and any tool that can export a heightmap (raw/r16/exr/+). See importing data

See Project Status for details.

Getting Started

  1. Read the Installation instructions, and the rest of the documentation.

  2. For support, read Getting Help or join our Discord server.

  3. Watch the tutorial videos:

Installation, Setup, Basic Usage

Using Terrain3D - Part 1

Texture Painting, Holes, Navigation, Advanced Usage

Using Terrain3D - Part 2

Credit

Developed for the Godot community by:

Cory Petkovsek, Tokisan Games
Roope Palmroos, Outobugi Games

And other contributors displayed on the right of the github page and in AUTHORS.md.

Geometry clipmap mesh code created by Mike J. Savage. Blog and repository code released under the MIT license per email communication with Mike.

Contributing

Please see CONTRIBUTING.md if you would like to help make Terrain3D the best terrain system for Godot.

License

This plugin has been released under the MIT License.

terrain3d's People

Contributors

directedchaossoftware avatar epitaque avatar fishofthenorthstar avatar jacobcoughenour avatar jeffercize avatar lfxu avatar lw64 avatar outobugi avatar painfulexistence avatar rds1983 avatar slashscreen avatar stakira avatar svencan avatar tcoxon avatar tokisangames avatar xtarsia avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

terrain3d's Issues

Change UI to scenes rather than code generated

It's very difficult for us to improve and build upon the UI when generated by code. It should be built as a scene in Godot and instanced by the code.

eg

const UI = "res://addons/gterrain/ui/GTerrainUI.tscn"

ui = load(UI).instantiate()
ui.ted = self
add_control_to_bottom_panel(ui, "Terrain Editor")
make_bottom_panel_item_visible(ui)

Move everything to GDExtension

UI, icons, brushes etc.

GDScript is currently used here only because GDExtension has problems with EditorPlugins. Once those problems are gone, we can convert everything to C++. For the transition to be painless as possible, the UI must done in script.

Support more region sizes

Edit:
Changing region_size broke existing data. And no other size even worked, so I disabled them all except 1024 in ebf9df0.

Now let's get all the other sizes working again and look at much larger spaces like up to 2048 regions (45 square) and up to 2k or 4k region sizes. See #77 (comment)


Changing region size should not change the data at all. It should only change the size of the regions, represented as white boxes in the images below.

Instead it gives all sorts of artifacts:

  • The data on the region map loses order, some sections appear split and move around
  • Some data gets scaled laterally, some is flattened vertically
  • Terrain normals are not recalculated afterwards
  • The total size changes, rather than only the regions changing with the same data.

It may be as simple as running some update functions after changing region size.

4k x 2k @ 1024 region size

image

Change to 2048 region size. The total size is 2x as large. Instead only the white boxes should be bigger. That "mountainous" section in the top left between the split peaks is actually flat. But the normals make it look like there are heights there.

image

Changing to 512 region size and everything got smaller with less resolution. The data should remain the same, and the only difference we should see is the white boxes getting smaller.

image

TextureArrays are not saved

Godot bug probably but can be worked around by having each Image in an array and create a TextureArray from those.

Add ability to clear, or subtract affects region 0

Rather than going through creating a new storage and setting up noise and other parameters, add either:

  • Or allow subtracting region 0 (the last remaining one), which means region 0 gets cleared
  • One click to clear all regions, perhaps w/ a prompt, w/o resetting storage settings
  • or both

Support object placement

Ability to place PackedScenes on the terrain. Probably paintable on a detail layer. Unlike #43 , these can include collision, scripts, and sub scenes, so cannot go through the particle or MMI system.

In one of my tools, I provided the feature to take a directory, and randomly place any of the scenes in that directory, eg any of these 13 tall trees, so I didn't need 13 separate detail layers.

This is so low priority it will probably never be implemented. Scatter is a much more appropriate tool and we provide a script for it to detect the terrain in /project/addons/terrain_3d/extras/project_on_terrain3d.gd

[TRACKER] Documentation & Tutorials

  • - Instructions & basic information (alpha)
  • - Convert from wiki to Readthedocs
  • - Getting started video (December)
  • Document API
    • Terrain3D
    • Terrain3DEditor
    • Terrain3DStorage
    • Terrain3DMaterial
    • Terrain3DTextureList
    • Terrain3DTexture
    • Support classes
    • Shader
  • Build custom doc classes into the library. Now possible w/ godotengine/godot#83747

Add unit tests

Write some unit tests in both C++ and GDScript. Create a function that sends full range and valid and invalid values to each function from both C++ and gdscript.

At the least it should test:

  • nullptr, null
  • empty form of the typed object (e.g. String(), Image())
  • very large form of the typed object
  • High and low values for number parameters
  • Negative values where generally expecting positives
  • If image: valid but unexpected sizes & formats, valid but empty, null pointer

Mouse position ignores terrain height

Mouse position basically ignores height. It will be obvious when #62 is done, but becomes apparent when working on terrain.

Needs:

  • Accurate brushing both far and close
  • Brush effects apply between vertices (spread among them) rather than snapping to vertices (feels clunky)

I had similar problem in GTerrain, and still have an issue with vertex snapping.

I used raycasting to get a collision based intersection. That was reasonably accurate but limited to our collision area and we have a small collision area that follows the camera.

Next, I devised a method to take the current camera direction and XZ position. Then iteratively move a ray along the ground at the appropriate height until it intersected the camera ray. This freed me from physics and worked at much longer distances. However, the distance was constrained by gdscript performance. We are currently using this, and with C++ this could go reach further. The only challenge is that up close for fine grained sculpting, the psuedo collision detection snaps to the vertex grid. We didn't have this problem with raycasting.

https://github.com/TokisanGames/gterrain/blob/570951f8fa16a94ea186df8ca3791fee5c984375/addons/gterrain/src/GTerrainEditor.gd#L53

So my next step would have been to have a hybrid. If we're close to the ground we're looking at, raycast. If we're looking farther away, use method 2.

In this plugin, since we have full LOD0 collision, we could just use physics based raycasting everywhere. Collision can be always enabled in the editor, even if they turn it off in game. Or the current method could be improved, or we can use my second method above.

Artifacts around regions

  • Create a new storage
  • Sculpt w/ Flatten around 100m and cover an entire square to the edges.

image

  • Delete all the extra regions outside of the center one at ~100m.
  • Add a new region, anywhere, adjacent or not

image

  • Click off of the Terrain3D node and notice the new, blank regions have outlines.

image

It may be a shader issue, as it appears that the border color is multipled, rather than a missing mesh

image

image

May be related to #79, but these artifacts do not change based on LODs or camera transformation.

Maps w/ content don't display properly

I generated a 1024x1024 noise image and stuck it on the single heightmap.

image

  1. If this is in a non-repeat mode, then outside the heightmap should be flat.

  2. Close to the camera, the mesh is disappearing as the camera moves, as if the frustum culling is too agressive on the bottom of the screen.

Also I did this test to determine if the seams and lods are lining up properly, but we're not there yet. It would be helpful if there was an automatic import slicer function as I mentioned here. Then I could generate a 4k noise image and pass it in for the system to automatically place. Then I could start working on an importer for external editing, and importing people's existing heightmaps. Also the oppose stitcher function so I can export maps via code.

I will add this as a PR to start off our landscape generation, but for now this will generate a noise map. You could cut out all logging if on your own branch:

// In the class declaration
	void generate_noise();

// In the constructor
	generate_noise();

#include "terrain_logger.h"
void Terrain3DStorage::generate_noise() {
	LOG(DEBUG, "Creating fastnoise");
	Ref<FastNoiseLite> fnoise;
	fnoise.instantiate();

	LOG(DEBUG, "Creating noise image");
	Ref<Image> img = fnoise->get_seamless_image(1024, 1024);

	LOG(DEBUG, "getting image format.");
	int fmt = img->get_format();
	LOG(DEBUG, "image stats, s: ", String(img->get_size()), " f: ", String::num_int64(fmt));

	if (height_maps.size() < 1) {
		LOG(DEBUG, "height_maps.size() == 0. Adding map.");
		add_map(Vector3(0, 0, 0));
	}

	LOG(DEBUG, "assigning to height_maps[0]");
	height_maps[0] = img;
	LOG(DEBUG, "updating material");
	_update_material();
}

Implement Collision

Heightmap based collision is faulty.
godotengine/godot#68238

In my game if the heightmap segments are too steep, my player falls through. I have to have my player include a terrain.get_height() check after doing the physics move_and_slide() to make sure she won't fall through.

If we can generate a convex collision shape that should be much more reliable.

Trying to call a function on a null value. `layers.set_visible(visible)`

Opening up the editor, I keep getting this error. At startup, adding a new terrain, and even if I have white layer square on the terrain, and click off and back on the terrain3d node.

SCRIPT ERROR: Trying to call a function on a null value.
          at: _make_visible (res://addons/terrain/editor/editor.gd:55)

which corresponds to the layers line:

func _make_visible(visible: bool):
	toolbar.set_visible(visible)
	layers.set_visible(visible)
	
	map_gizmo.set_hidden(!visible)

Nothing sculpts for me, but I'm sure you're working on it.

Update AABB on changes

Second issue in #17 isn't resolved.

Close to the camera, the mesh disappears as the camera moves, as if the frustum culling is too aggressive on the bottom of the screen.

Outobugi stated:

AABB is not changed at all after initial mesh generation.

It might also be fixed on increasing the extra_cull_margin on the mesh instance. I had to increase this on my terrain to 500 as the terrain would disappear when standing on the ground and looking up. Presumably the AABB was already correct. Both may be necessary.
https://docs.godotengine.org/en/latest/classes/class_geometryinstance3d.html#class-geometryinstance3d-property-extra-cull-margin

image

Crash on loading two scenes simultaneously

Crash: If you create two scenes w/ terrains, save them, it works to open and switch back and forth. However if you restart the engine with both open, when it opens up both again, it crashes:

Terrain3D::_update_material: Generating terrain height & control maps
Terrain3D::_update_textures: Generating terrain texture arrays
Terrain3D::_update_material: Generating terrain height & control maps
Terrain3D::_update_textures: Generating terrain texture arrays
Terrain3D::_update_material: Generating terrain height & control maps
Terrain3D::_update_textures: Generating terrain texture arrays
Terrain3D::clear: Clearing the terrain
Terrain3D::build: Building the terrain
Terrain3D::generate: Generating meshes of size: 48 levels: 7
ERROR: Condition "!is_inside_world()" is true. Returning: Ref<World3D>()
   at: get_world_3d (scene/3d/node_3d.cpp:665)

Support doubles

Update: #232 has added the ability to build Terrain3D with double precision.

To get it working you need to:

  • Build Godot with scons precision=double
  • Regenerate godot-cpp bindings with this new executable
  • Build Terrain3D (which includes godot-cpp) with scons precision=double custom_api_file=YOUR_CUSTOM_FILE

@zuriel13 reported the demo is working fine using Godot 4.2.1 and Terrain3D 0.9.1-dev.

Using a single precision engine, the terrain and shader look fine when moving the camera even 100k units away from the origin. This may break down at extremes though and bears testing.

Shaders do not support double precision, however the engine does include some double emulation. Clayjohn wrote an article describing how to emulate double precision in shaders for positional elements. He writes that the camera and model transform matrices needed to be emulated, and that is now done automatically in the engine.

https://godotengine.org/article/emulating-double-precision-gpu-render-large-worlds/

It's possible that other elements of the shader will need to emulate double precision, but no issues are apparent, yet.

Related to regenerating bindings: godotengine/godot-cpp#1386


Include a build flag that supports doubles in both the shader and C++ where relevant. Probably only locations. This is done in godot source:

//math_defs.h
/**
 * The "Real" type is an abstract type used for real numbers, such as 1.5,
 * in contrast to integer numbers. Precision can be controlled with the
 * presence or absence of the REAL_T_IS_DOUBLE define.
 */
#ifdef REAL_T_IS_DOUBLE
typedef double real_t;
#else
typedef float real_t;
#endif

// Elsewhere
#ifdef REAL_T_IS_DOUBLE
	if (p_feature == "double") {
		return true;
	}
#else
	if (p_feature == "single") {
		return true;
	}
#endif // REAL_T_IS_DOUBLE

10k out
image

1M out, corruption and the mesh jitters all over the place
image

Support custom terrain shader

We need to provide our shader as a base, either as a separate file, or as a right-click-convert to shader.

It will help us immensely now so we can troubleshoot and develop shaders live in Godot, rather than having to compile the plugin and restart godot.

Terrain doesn't save reliably

Under certain circumstances the terrain doesn't save. Bug is present in my current branches and back in c92254d. Tested w/ saving to an external .res, which everyone should be using.


  1. Spray paint on ground
  2. Run scene: FAIL, No change in game, even though the paint is visible in the editor.
  3. Restart editor: FAIL, New Paint is gone

  1. Spray paint on ground
  2. Save scene
  3. Run scene: OK Paint is visible
  4. Restart: OK Paint is visible

  1. Sculpt
  2. Run scene: OK one time
  3. Sculpt
  4. Run scene: Fail

  1. Sculpt, paint
  2. Save scene
  3. Run scene: OK
  4. Sculpt, paint
  5. Save scene
  6. Run scene: FAIL
  7. Restart engine: FAIL

Implement brush selection

In GTerrain allowed loading of alpha masks, either PNG or exr, white on black or white on alpha. I displayed this on the ground w/ a decal. It should rotate the brush based on camera orientation.

Implement Color Map & Painting

9ce54a2 provided the data containers. Now just plug it into the shader, multiply albedo by the color map, and provide a painting mode that applys RGB to the color map.

TerrainStorage doesn't load saved data

Make a terrain, a storage, sculpt, save. Reload the scene and the data is gone.

It appears that data does get written to the file, so it's likely an issue on the reading side.

And it's no longer sculptable after loading a saved scene.

The problem arose in this commit ee3ac9d

Gaps between LODs

Sculpt something large like this, using the full range, up to 1000 on the right. Then move the camera location around and you'll quickly see gaps between lods. They aren't always visible, just when the seams hit the right spot on the mesh.

image

image

image

Support all editor cameras

Currently the terrain snaps to the current viewport in the game, and Camera 0 in the editor. However the editor has 4 cameras, one for each viewport. It should switch between them.

terrain.cpp::get_camera() already gets all four cameras. It takes the first and throws away the rest. It should retain all four.
Which ever camera moves should be considered "active", which is the one the snapping function centers the terrain on.

I thought we could do something like this:

func _forward_3d_gui_input(p_viewport_camera: Camera3D, p_event: InputEvent) -> int:

	if terrain.get_camera() != p_viewport_camera:
		print("Current camera: %s, New camera: %s" % [ terrain.get_camera(), p_viewport_camera ])	
		var cam: Object = p_viewport_camera
		terrain.set_camera(p_viewport_camera)

However, Godot 4.0.2 has another bug that calls _forward_3d_gui_input for inactive viewports. So moving the mouse in one viewport and the others get called. The better way is to do it in C++ which has all 4 cameras from _find_cameras() and query the editor plugin to see which viewport is active, then switch to that.

Add cursor decal

Add a visual indicator as to where on the terrain we'll be sculpting or painting. I don't think the mouse pointer is 100% accurate and this will show that for one thing.

I started by adding a circle in the shader, but then decided to switch to a decal, which was easier to manage. I was able to put the brush texture into the decal, and offered different colors based upon the operation or the color map.

Search decal here:
https://github.com/TokisanGames/gterrain/blob/master/addons/gterrain/src/GTerrainPainter.gd

Implement Sculpting

Add basic operations:

  • Raise
  • Lower
  • Smooth
  • Flatten
  • Slope (optional now, or later)

Algorithms available in my code and zylann's

Support Navigation Server

Likely needs to just support collision. Perhaps temporarily baking a very large collision, long enough to bake navigation, then it can revert to a smaller size. Devmar had a video about it for his clipmap terrain.

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


Update:
@SlashScreen has been working on experimenting with the nav server. They've setup a repo with a makeshift nav baker
https://github.com/SlashScreen/terrain3d_nav_bake

Read discord conversation starting here
https://discord.com/channels/691957978680786944/1130291534802202735/1136232663989100554

The current primary navigation server core developer was asked about using it on large terrains and this was the conversation:
image

Slashscreen currrently has a nav baker that can bake a large mesh in about 30 seconds and reports this information:

The general low-level process is as follows:

  1. Geometry is parsed from the scene and put into a NavigationMeshSourceGeometryData3D object. This is done on the main thread, since the scene tree is not thread safe.
  2. The geometry data and a Navmesh is fed into the NavigationMeshGenerator singleton to bake. This can be done multi-threaded, like I did, and/or a separate thread in the background.
  3. The resulting Navmesh can then be put into the scene, usually by creating a NavigationRegion3D, but it looks like you may be able to add a mesh directly to the server without creating a new node.
  • Theoretically, as you generate chunks for the collision, you could upload them to the Geometry Data directly, as it has an add_mesh function, and bake that in a separate thread. (A navmesh can be limited to a certain AABB, so you don't have to re-bake the entire thing.)

  • I have also found that the slowest part of the process is parsing the scene tree, rather than baking. I like to lazy-load things, so how I would go about parsing the scene tree is to cast a big box on the chunk you wish to bake, grab all of the colliders hit, and add those to the Geometry Data too before baking, to allow for, say, buildings or whatever. To me it seems like doing that every so often won't be super intensive.

[TRACKER] Terrain Tools

Now that the bakers are added to the Tools menu, we can track other tool issues here. Future tools include:

  • Arraymesh baker

  • Occlusion Culling baker

  • Navigation baker

  • Channel packer #125

  • Channel packer improvements #308

  • Region viewer (heightmap / normal / color / control thumbnail view of each region)

  • An information panel (# regions, total space used, map resolution, texture resolution, memory used, texture resolution, filenames, etc) (shown: GTerrain, precursor to Terrain3D)

image

  • A terrain generator (shown: Zylann's HTerrain) #101

image

  • An importer/exporter (shown: Zylann's HTerrain)

image

  • Image processing (de/normalize, swap texture ids by changing the control map pixels, moving regions, resize maps)

Support custom uniforms

How do I control the uniforms? The inspector needs to expose these. Perhaps you should make the override a ShaderMaterial instead.

Custom shaders were added in #83, also see #39. But we need a way to add custom uniforms that support any format regular shaders do: textures, colors, etc.

This should also expose any useful variables in the current shader. Such as UV scaling.

Fix initial import errors & crash

After installing the plugin, upon initial startup, I got all of these error messages and often a crash. The plugin doesn't load until a restart.

I think we can refactor the import files so they aren't tied to non-existent cached data.


ERROR: Unable to open file: res://.godot/imported/icon_terrain3d.svg-7b79ba28bfbcfe67d066affa10c60bff.ctex.
   at: (scene/resources/texture.cpp:814)
ERROR: Failed loading resource: res://.godot/imported/icon_terrain3d.svg-7b79ba28bfbcfe67d066affa10c60bff.ctex. Make sure resources have been imported by opening the project in th.
   at: (core/io/resource_loader.cpp:214)
ERROR: Failed loading resource: res://addons/terrain/icons/icon_terrain3d.svg. Make sure resources have been imported by opening the project in the editor at least once.
   at: (core/io/resource_loader.cpp:214)
ERROR: Unable to open file: res://.godot/imported/icon_terrain_material.svg-3e0aae3669fe2efeaf707a6892b5f063.ctex.
   at: (scene/resources/texture.cpp:814)
ERROR: Failed loading resource: res://.godot/imported/icon_terrain_material.svg-3e0aae3669fe2efeaf707a6892b5f063.ctex. Make sure resources have been imported by opening the projec.
   at: (core/io/resource_loader.cpp:214)
ERROR: Failed loading resource: res://addons/terrain/icons/icon_terrain_material.svg. Make sure resources have been imported by opening the project in the editor at least once.
   at: (core/io/resource_loader.cpp:214)
ERROR: Unable to open file: res://.godot/imported/icon_terrain_layer_material.svg-810362a81388cf3fc0c37a0a04912bb9.ctex.
   at: (scene/resources/texture.cpp:814)
ERROR: Failed loading resource: res://.godot/imported/icon_terrain_layer_material.svg-810362a81388cf3fc0c37a0a04912bb9.ctex. Make sure resources have been imported by opening the .
   at: (core/io/resource_loader.cpp:214)
ERROR: Failed loading resource: res://addons/terrain/icons/icon_terrain_layer_material.svg. Make sure resources have been imported by opening the project in the editor at least on.
   at: (core/io/resource_loader.cpp:214)
ERROR: Unable to open file: res://.godot/imported/icon_map_add.svg-bc7f88fd1deaf4cbf31b1d4c8c6d0b2c.ctex.
   at: (scene/resources/texture.cpp:814)
ERROR: Failed loading resource: res://.godot/imported/icon_map_add.svg-bc7f88fd1deaf4cbf31b1d4c8c6d0b2c.ctex. Make sure resources have been imported by opening the project in the .
   at: (core/io/resource_loader.cpp:214)
ERROR: Failed loading resource: res://addons/terrain/icons/icon_map_add.svg. Make sure resources have been imported by opening the project in the editor at least once.
   at: (core/io/resource_loader.cpp:214)
ERROR: Unable to open file: res://.godot/imported/icon_map_remove.svg-150dbd16519910c64a5accd6a15577ea.ctex.
   at: (scene/resources/texture.cpp:814)
ERROR: Failed loading resource: res://.godot/imported/icon_map_remove.svg-150dbd16519910c64a5accd6a15577ea.ctex. Make sure resources have been imported by opening the project in t.
   at: (core/io/resource_loader.cpp:214)
ERROR: Failed loading resource: res://addons/terrain/icons/icon_map_remove.svg. Make sure resources have been imported by opening the project in the editor at least once.
   at: (core/io/resource_loader.cpp:214)
ERROR: Unable to open file: res://.godot/imported/icon_height_add.svg-84485c2ba0abdc6736a7102d21854ca4.ctex.
   at: (scene/resources/texture.cpp:814)
ERROR: Failed loading resource: res://.godot/imported/icon_height_add.svg-84485c2ba0abdc6736a7102d21854ca4.ctex. Make sure resources have been imported by opening the project in t.
   at: (core/io/resource_loader.cpp:214)
ERROR: Failed loading resource: res://addons/terrain/icons/icon_height_add.svg. Make sure resources have been imported by opening the project in the editor at least once.
   at: (core/io/resource_loader.cpp:214)
ERROR: Unable to open file: res://.godot/imported/icon_height_sub.svg-bd2b838af515ef43c8b3c9bc412ab7b6.ctex.
   at: (scene/resources/texture.cpp:814)
ERROR: Failed loading resource: res://.godot/imported/icon_height_sub.svg-bd2b838af515ef43c8b3c9bc412ab7b6.ctex. Make sure resources have been imported by opening the project in t.
   at: (core/io/resource_loader.cpp:214)
ERROR: Failed loading resource: res://addons/terrain/icons/icon_height_sub.svg. Make sure resources have been imported by opening the project in the editor at least once.
   at: (core/io/resource_loader.cpp:214)
ERROR: Unable to open file: res://.godot/imported/icon_height_mul.svg-94df27cd9453a24dccf06b437c08d376.ctex.
   at: (scene/resources/texture.cpp:814)
ERROR: Failed loading resource: res://.godot/imported/icon_height_mul.svg-94df27cd9453a24dccf06b437c08d376.ctex. Make sure resources have been imported by opening the project in t.
   at: (core/io/resource_loader.cpp:214)
ERROR: Failed loading resource: res://addons/terrain/icons/icon_height_mul.svg. Make sure resources have been imported by opening the project in the editor at least once.
   at: (core/io/resource_loader.cpp:214)
ERROR: Unable to open file: res://.godot/imported/icon_height_flat.svg-dcafa26c94284e57fa4f103237659863.ctex.
   at: (scene/resources/texture.cpp:814)
ERROR: Failed loading resource: res://.godot/imported/icon_height_flat.svg-dcafa26c94284e57fa4f103237659863.ctex. Make sure resources have been imported by opening the project in .
   at: (core/io/resource_loader.cpp:214)
ERROR: Failed loading resource: res://addons/terrain/icons/icon_height_flat.svg. Make sure resources have been imported by opening the project in the editor at least once.
   at: (core/io/resource_loader.cpp:214)
SCRIPT ERROR: Parse Error: Could not preload resource file "res://addons/terrain/icons/icon_terrain3d.svg".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:4)
SCRIPT ERROR: Parse Error: Could not resolve type for constant "ICON_TERRAIN".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:4)
SCRIPT ERROR: Parse Error: Could not preload resource file "res://addons/terrain/icons/icon_terrain_material.svg".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:5)
SCRIPT ERROR: Parse Error: Could not resolve type for constant "ICON_TERRAIN_MATERIAL".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:5)
SCRIPT ERROR: Parse Error: Could not preload resource file "res://addons/terrain/icons/icon_terrain_layer_material.svg".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:6)
SCRIPT ERROR: Parse Error: Could not resolve type for constant "ICON_LAYER_MATERIAL".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:6)
SCRIPT ERROR: Parse Error: "Terrain3D" was not found in the current scope.
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:8)
SCRIPT ERROR: Parse Error: Could not preload resource file "res://addons/terrain/icons/icon_map_add.svg".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:183)
SCRIPT ERROR: Parse Error: Could not resolve type for constant "ICON_MAP_ADD".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:183)
SCRIPT ERROR: Parse Error: Could not preload resource file "res://addons/terrain/icons/icon_map_remove.svg".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:184)
SCRIPT ERROR: Parse Error: Could not resolve type for constant "ICON_MAP_REMOVE".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:184)
SCRIPT ERROR: Parse Error: Could not preload resource file "res://addons/terrain/icons/icon_height_add.svg".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:185)
SCRIPT ERROR: Parse Error: Could not resolve type for constant "ICON_HEIGHT_ADD".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:185)
SCRIPT ERROR: Parse Error: Could not preload resource file "res://addons/terrain/icons/icon_height_sub.svg".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:186)
SCRIPT ERROR: Parse Error: Could not resolve type for constant "ICON_HEIGHT_SUB".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:186)
SCRIPT ERROR: Parse Error: Could not preload resource file "res://addons/terrain/icons/icon_height_mul.svg".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:187)
SCRIPT ERROR: Parse Error: Could not resolve type for constant "ICON_HEIGHT_MUL".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:187)
SCRIPT ERROR: Parse Error: Could not preload resource file "res://addons/terrain/icons/icon_height_flat.svg".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:188)
SCRIPT ERROR: Parse Error: Could not resolve type for constant "ICON_HEIGHT_FLAT".
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:188)
SCRIPT ERROR: Parse Error: Identifier "Terrain3D" not declared in the current scope.
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:42)
SCRIPT ERROR: Parse Error: Identifier "Terrain3D" not declared in the current scope.
          at: GDScript::reload (res://addons/terrain/editor/editor.gd:45)

Crash on loading saved scene

Making an empty terrain3d, saving the scene, closing and reloading works.

Making a terrain3d, with a terrainstorage, saving the scene and reloading produces this error and crashes the engine:

ERROR: Condition "!is_inside_world()" is true. Returning: Ref<World3D>()
   at: get_world_3d (scene/3d/node_3d.cpp:665)

Implement holes

See the discussion here:
https://discord.com/channels/691957978680786944/1065519581013229578/1076953191482130582

This probably means:

  • Ability to paint a hole
  • It puts a nan on the heightmap for the pixel/vertex (alternatively a bit on a control map)
  • When meshing, nan/inf the vertex (search "holes" on Juan's proposal for notes from Juan and Calinou godotengine/godot-proposals#6121)
  • Alternatively, since we're generating our own mesh and collision mesh, I think it might be possible to just punch a hole in the meshes themselves. That is reshape the mesh around the hole data. Although with a clipmap terrain where we're reusing meshes this may not be practical.

Requires #115

Shader optimizations

Performance

  • 1. Precalculate this in C++ whenever terrain_size is changed and pass in the uniform: terrain_size_inv rather than in the shader. WIll save millions of divides per second.
    code += " vec2 ps = vec2(1.0) / terrain_size;\n"; // TODO can be precalculated

e.g.


  • 3. Lookup region only once per vertex. Move into vertex() and save as a varrying for the colormap in fragment. - Looks bad on lower LODs when using this to calculate pixel data as the vertices are far apart.

  • 4. Consider replacing texturegrad with texture, if we don't need it for 3D Projection. See #169 update 2 and #169 (comment)

  • 5. As above remove all derivative functions and at least get them out of branches. Test optimizing branches

https://community.khronos.org/t/if-statements-in-shaders-confused-by-results/73518/15


  • 6. Replace 16x16 Region map with an array. No need for a texture lookup

  • 7. Replace 512x512 region blend map w/ a zoomed UV lookup of the region map, or a mathematical version from an array.

  • 8. Since we're blending 4 adjacent vertices, move lookups to vertex() and weight in fragment. - Doesn't look good on lower LODs as the vertices are farther apart, but see redesign below.


  • 10. Instead of sampling base/overlay texture lookups for each vertex, bilinear interpolate the UV for the texture lookup and sample albedo/normal once.

  • 11. light() is wasteful for mobile according to lfxu. Rewrite it to do only what is needed.

Functional

Sometimes I've had the need for antialiasing and have typically faded out (vertex grid, macrovariation) instead of aliasing. Perhaps anti-aliasing is better.
https://stackoverflow.com/questions/20204561/advanced-moir%C3%A9-a-pattern-reduction-in-hlsl-glsl-procedural-textures-shader-a
https://www.yaldex.com/open-gl/ch17lev1sec4.html#ch17fig04

Redesign

Implement foliage instancing

My idea for a paintable instancer is:

  • Painting occurs on a splat/control map that can be saved in storage, but never goes in VRAM.
  • MMI chunks are generated as the camera moves
  • MMI chunks are regenerated if contained in the edited aabb of any terrain modifications

#324 and #278 need to be completed before this.

Reasoning:

  • A control map based particle shader means placement around vertices with noise offsets. MMI nodes can be placed exactly where painted.
  • Erasing instances is easy when painting on a control map. It's difficult to find and erase instances with an MMI, but regenerating a whole chunk while editing isn't a big deal.
  • Particle shaders might be 2-4% faster, but will require yet another control map in VRAM. Fine if it's placement based on ground texture, but not if paintable. We're already consuming 4GB VRAM in OOTA and need to conserve.
  • Particles can be frustum and distance culled. MMIs cannot, but with small enough chunks should be fine.
  • MMIs seem to operate with Godot's autolod system (from what I see in SGT code). Haven't tested it, and don't know about particles.

Other Notes

The current control map format has 11 bits free, and most likely need 9 of them for paintable uv scale, slope, and rotation. 2 more could possibly be added to the base & overlay, or used for non-destructive layers.

Thus we probably need a second control map that could allocate foliage particles, water, and other items. However this other control map may not need to be in vram. It could be used to populate an MMI or a buffer filled with positions for a vertex shader.

Surprisingly, Godot's autolod apparently works with MMIs, according to SimpleGrassTextured, so this should be tested with MMIs and particle shaders.

Other solutions

My ideas

  • A paintable control map Image that does not get stored in vram. This is used to generate MMI chunks. Chunks are regenerated upon sculpting updates within the editable AABB.
  • Use a vram control map that feeds directly into a particle shader. Offer 2 particle types per vertex and a (paintable?) density. Several instances of the specified particles are placed around the vertex based on sampled noise and density.
  • Collision could be generated on enabled particles, especially with the chunk based generator.
  • Compute based grass https://ueshita.hatenablog.jp/entry/2023/12/06/220451
  • Either particle or MMI
  • Should be paintable w/ multiple levels eg. paint grass, sunflowers, rocks
  • Collision is not expected, but could be generated with our chunk system
  • Maybe an option for the user to provide either a textured mesh, or just a 2D texture that gets applied to a generated quad

https://godotshaders.com/shader/wandering-clipmap-stylized-grass/
https://godotshaders.com/shader/wandering-clipmap-foliage-particle-process/

Static debug_level value changes w/ multiple scenes

See terrain.h::static int debug_level and how it's used with terrain_logger.h It works fine in one scene. But if you open up another scene with a different debug value, it changes. Even if you open a scene, set it to DEBUG, save, close, and open a scene with it set to ERRORS, then close it and reopen the first, what should have been saved as DEBUG it now shows as ERRORS. Also if you have two scenes open, when you switch back and forth, it changes.

Edit:
I don't think this is an issue. Consider it a plugin wide setting, rather than a scene setting.

Saving TerrainStorage as a .res doesn't write to disk on subsequent saves

If I save the TerrainStorage as a .res so all that data doesn't go as text in the scene file, it doesn't resave on subsequent changes when I press CTRL+S. It only retains what I saved upon writing to the external file. It will work if you click terrain storage in the inspector and resave it.

It needs to capture the save notification and manually save the resource.

https://github.com/TokisanGames/gterrain/blob/570951f8fa16a94ea186df8ca3791fee5c984375/addons/gterrain/src/GTerrain.gd#L271

Edit: still an issue in 4.0-stable.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.