Icosphere + ROAM; test and questions

Dearest community,

First, a playground: https://playground.babylonjs.com/#2X0QTL#3 with a flycamera QWEASD

I am trying to implement something similar to the ROAM algorithm on an icosphere. First in a pure-js version (the one from the playground); the goal with this initial version would be to get the quality right. Then, once quality is ok, implement the algorithms in a little wasm using rust. Which hopefully will be faster although frankly I am not 100% convinced it will be.

About quality: obviously many things are wrong, most notably the cracks between subdivided and non subdivided triangles.

My approach has so far be very naive (including the noise implementation, the absence of neighbour tracking, no cleaning up unused vertices, etc). Any thoughts on improvements? Is this approach completely wrong?

Many thanks!

NB/edit: people who know of this will find it obvious why I am trying to come up with something like this :slight_smile:

3 Likes

Just wanted to say that this is a neat demo!! I also went to play around with your procedural galaxy app-- it’s SO stunning.

This is the first I’ve heard of ROAM, so I can’t offer much implementation advice. Have you already considered using WebGPU and compute shaders (along with something like this)? Is it possible to use them in the first place?

1 Like

Thanks!

If you have used the 3D explorer of one of the galaxies, and you got close enough: 1) to a star 2) to one of its planetary satellites, then it will become evident that such a dynamic LOD would be extremely useful for me :slight_smile:

It is only a first step, though, as each vertex then needs to be mapped to a more clever procedural bit to generate nicer surfaces :slight_smile:

and no I havent yet considered compute shaders. any feeling as to the kind of performance it might offer against pure js and/or wasm?

1 Like

Yes, when I was playing with the 3D explorer, I saw the potential with the icospheres right away :slight_smile: Will be very cool!

The compute shaders should outperform both WASM and especially pure JS. But you might hit some issues if you send the new vertex data from the GPU back to the CPU… just to send it back to the GPU for rendering. Lol. The thread I linked in my original comment indicates there’s a way to avoid this, though.

Of course, compute shaders are WebGPU-only, so you’ll probably want to provide some fallback JS or WASM version for clients to use if they’re on a browser that doesn’t support WebGPU.(Forewarning: I am not read up on what it takes to support WebGPU and WebGL in the same app, so it might be way trickier than that.)

I think it’d be worth a shot! Or a fun challenge, at least.

1 Like

I see… well maybe I shall try compute shaders. however, how easy would it be to enrich them with procedural logic (which should not be too hard to do in rust/wasm, for example).

The one drawback I see to both wasm and compute shaders is the nearly constant going to and fro between js and the “other, faster world”. It would indeed be interesting to see how both “faster” solutions compare.

One thing though - I have tried to activate webgpu on the 3d explorer, to no avail and with weird errors. But that is for the “other thread” I think, not this one :slight_smile:

Hello hello,

Well only screenshots for now, but the wasm is slowly coming along:

from far away:

closer view:

even closer view, in wireframe mode:

and an illustration of the frustum culling happening wasm-side:

This runs at around ~0.5ms to 3 4/5ms (all on main thread at the moment) for each “tick”. I’m not sure whether I should consider this as fast or slow… knowing vertex displacement via noise isn’t even in yet!

The ugly colours are linked to procedural tectonic plate assignment (in real time) for each vertex. They have certain characteristics that will have an effect on noise, base texture, … when those are in.

I will probably release something in the Tools and experiments section of the site, with the current wasm (or close).

Quite curious to see what performance would be like on various CPUs (knowing mine is not bad at all … a i9 12900HK).

Thanks for your feedback!

edit: a little video :slight_smile:

2 Likes

Awesome :ok_hand:

For the speed, 0.5ms is very good imo, on the other end 5ms starts to be quite much haha However if you run it in a worker, then it’s not really a problem anymore :thinking:

Do you use Voronoi for the tectonic plates or something fancier?

Very curious to see the results with some terrain noise!

hey Crash :slight_smile:

For the plates it’s hard to tell if it’s simpler of fancier. No voronoi for sure. It’s a custom mix of normalised surface fractions, weights, geodesic directions and sine waves, with also the ability for each vertex to “know” how close it is to each plate it does not belong to (will be useful for later elevation biases/calculations EDIT: but also for procedural resources determination: amounts, mining/gathering difficulties, etc).

And yeah, hopefully the overall perceived performance will be better with workers. Currently having a look at webassembly threads too, as this is all quite brute force at the moment! :stuck_out_tongue:

This – I think – will never reach an excellent graphics quality as this is not my goal. The (hopefully coming one day) game will be more focused on strategy, etc. So High LOD and ultra realism is not a high priority.

and yes I’m very curious about the noise too! xD

Thanks!

Well that counts as fancier than voronoi in my book haha. Embedding this data in the vertices sounds like a powerful tool to make the terrain interesting!

Does wasm support threads now? I am using a bunch of js workers wrapping around some wasm for my own terrain at the moment.

I think graphics quality and mesh resolution are not necessary correlated. Dave Frampton is also using an ico sphere with ROAM for his game Sapiens to my understanding and it looks really good as well as being low poly!

experimental and stuff but …

all useful stuff, although maybe for later?

looking at this sapiens thing, thank you very much :slight_smile:

Interesting read! They still use some JS glue apparently but they got some nice perf boost nonetheless ^^ There is no escaping JS yet haha

yep it’s a shame “intra-wasm threads” doesn’t seem to be supported at the moment. perhaps one day… ?
Or I understood sweet F.A about the articles/guides I’ve read :sweat_smile:

1 Like

Hello hello, good advice I think thanks :slight_smile:

the consistent metric I use is distance (amongst other things, such as the camera/triangle normal dot product versus its subdivision level).That may be a naive approach? It works by comparing the current subdivision level of a triangle versus the subdivision it should be at, based on the distance between its centroid and the camera, and act accordingly (split or merge).

Perlin/simplex/fbm I still need to implement, although the PG link above implements a quick and dirty version.

Efficient neighbour tracking is done via FxHashMaps and arenas, for almost garanteed O(1) access to anything that is needed. The downside is high(er) memory usage and the extra periodic “cleaning up/maintenance” that needs to be done. so far it seems to work not too badly but let’s see what happens once elevations are brought in!

Thank you again for your comment

Hello there!

Well, here’s a short video of an approach (scaled down to 1080p so quality might not be 100% there, sorry about this).

Grey levels are used to indicate “elevation” inside the crust’s available min/max range (helps to visualise many things). 2 sources of light are active in the scene. Obviously no texturing.

A few things:
. still struggling with cracks filling, but working on it :slight_smile: (hence the ugly blue gaps, apologies!)
. I am not fully happy with the elevation transitions are the boundaries between plates. They look very jagged and “plateau-like”; this is my priority.

The sphere starts at subdivision 4, all the way to 16 at the highest “resolution”. I haven’t tested anything deeper at the moment.

Some noise have started to be introduced, although in a very static way (ie, always a basic simplex, without variations such as ridged, fractal, mutlipeak, etc). I still need to do a lot of experimentations to get those reasonably right! :stuck_out_tongue:

and err… 2.5/3ms per tick. A few loops were tightened :facepalm:

Thanks!

1 Like

What I learned is that in those situations the solution if often “add moar noise!” to break patterns.

Can’t wait to see the results :eyes:

While browsing on shadertoy I found something that may interest you to get nice terrain Shader - Shadertoy BETA

I have yet to experiment with it myself so I don’t know if it is too expensive or not, but the eroded shape looks nice!

Haha yeah, moar noise is actually what my current tests are about. I moved from sine/weight/surface fraction to several noise fields spread over the sphere for plate selection. The result is much better so far.

Still remains the jaggedness but nothing ( I hope!!) I cannot overcome.

I will be posting some screenshots soon.

Thank you all, keep the comments coming please!

1 Like

ok so here’s few grey level shots from various seeds





still the plateau thingie.

But the noise field plate selection works really nicely I think.

Thoughts? :slight_smile:

2 Likes

The shapes look much more natural :ok_hand: (looks a bit like the moon with this grayscale)

Increasing terrain resolution and injecting high frequency noise could break the plateauing maybe :thinking: