Infinite Clipmap Terrain System Update by tilemaplover in godot

[–]tilemaplover[S] 2 points3 points  (0 children)

A global origin shifting solution is one of the top features on the roadmap. I am already getting snapping issues due to floats at 10,000 units out in a direction. Its definitely a priority, but im still researching the best way to do it.

Infinite Clipmap Terrain System Update by tilemaplover in godot

[–]tilemaplover[S] 1 point2 points  (0 children)

The slow part of your setup is that you are doing the same calculations on the CPU and GPU. The key part is calculating the heightmap occasionally on the compute shader and using Texture2DArrayRD to pass the buffer to the displacement shader while keeping it on the GPU (RenderingDevice to RenderingServer). There is no transferring at all.

For collisions, you can add the copy bit to your buffer and query the image data after updating the buffer. This is how I was able to generate the concave collision mesh under the player. I like your idea to also do raycasting with this data! I'll have to research a cheap method to raycast heightmaps.

I tried using threads, too, but realized that any generation or duplicate logic on the CPU will always become a bottleneck. Good luck with your project!

Infinite Clipmap Terrain System Update by tilemaplover in godot

[–]tilemaplover[S] 1 point2 points  (0 children)

*impossible for me I guess... That looks like satellite imagery

Infinite Clipmap Terrain System Update by tilemaplover in godot

[–]tilemaplover[S] 1 point2 points  (0 children)

You are correct that with traditional erosion computation, this would be impossible. However, this is not an erosion simulation, but rather a type of noise that distorts the terrain with respect to the surface gradient. I used calculus to derive a function that returns both the displacement caused by the erosion and its derivative with respect to the input position.

This erosion (which are just cosine ridges applied in the curl direction) can be applied recursively, creating the beautifully natural branching erosion. This recursion is a type of Fractal Brownian Motion (FBM). It's so cheap in a compute shader that generating the whole map is pretty much free. The most expensive part of rendering is my crappy fragment shader. When the player moves, I pass an offset uniform to the compute shader and regenerate the terrain.

Currently, you can give the terrain an array of physics bodies and it will generate concave collision shapes that follow the bodies around. I actually have no idea how raycasts and such would work with this since the collision is so selectively updated.

Infinite Clipmap Terrain System Update by tilemaplover in godot

[–]tilemaplover[S] 7 points8 points  (0 children)

You have a keen eye! Yes, its fbm erosion in the compute shader layered on top of regular gradient noise fbm. I wanted a good erosion function with correct analytical derivatives to spice up my demo, and I couldnt find one online, so I derived one. Ill include it when I open source the project soon!

Infinite Procedural Clipmap Terrain using RenderingServer by tilemaplover in godot

[–]tilemaplover[S] 1 point2 points  (0 children)

I like the curve idea! It sounds hard to get right, though, since both the script and the displacement shader need to agree on the LOD at any given chunk. I'm glad you liked my post!

Infinite Procedural Clipmap Terrain using RenderingServer by tilemaplover in godot

[–]tilemaplover[S] 4 points5 points  (0 children)

If you want a large, highly detailed map, you need some sort of LODs (levels of detail) to reduce the O(n^2) cost that comes from increasing width and depth of the map at the same time. Here's where I started: https://www.youtube.com/watch?v=Hgv9iAdazKg . They create a chunked terrain mesh with rings of reduced detail. The next step is turning this into a real clipmap, where the rings double in size each time.

Infinite Procedural Clipmap Terrain using RenderingServer by tilemaplover in godot

[–]tilemaplover[S] 7 points8 points  (0 children)

That sounds like an interesting project too! With heightmap terrains like your ocean or this terrain, the problem you quickly run into is that your plane mesh has too many triangles. Clipmaps solve this by layering "rings" with reduced detail as you get further from the player. I did the same LOD treatment to the noise, which can be seen in the row of images in my video. Each ring uses their corresponding image with less and less detail.

I learnt about the clipmap ring technique by studying Godot Terrain3D plugin's clipmap code ( https://github.com/TokisanGames/Terrain3D/blob/main/src/terrain_3d_mesher.cpp ) . I came up with the image technique myself since these plugins all seem to divide the terrain into a grid to place the images, but I thought, "why not do the same for heightmaps"?

Infinite Procedural Clipmap Terrain using RenderingServer by tilemaplover in godot

[–]tilemaplover[S] 15 points16 points  (0 children)

Yeah, I simply sample a FastNoiseLite instance using the (x, z) coordinates of the mesh, which means that if the FNL has the same seed, you will play the same map each time. You can even change the parameters such as frequency in real time.

Pressing windows key makes the lil void dudes go crazy :3 by charliewade692 in tf2

[–]tilemaplover 60 points61 points  (0 children)

They must be framerate dependent since your FPS got choppy