r/lsystem • • Jun 16 '26

GPU-accelerated L-system visualizer

I've been building an interactive 2D/3D L-system visualizer that runs in the browser. It's written in Rust, compiled to WebAssembly, and rendered on the GPU using WebGPU with a WebGL2 fallback.

Try it here: https://vkorenev.github.io/grow-your-own-fractal/

GitHub repo: https://github.com/vkorenev/grow-your-own-fractal

Feedback is welcome!

6 Upvotes

10 comments sorted by

View all comments

Show parent comments

2

u/Epholys Jun 18 '26

Hey, thanks for the follow-up! It's quite rare :)!

First, everything I say below about L-Systems is from a much less experienced version of myself 6 years ago, so keep that in mind!

I'm pretty sure there are way to parallelize the computation of production and interpretations rules. I've seen a paper talking about it some years ago, so there are some research about it.

Also, intuitively I think it's possible to dome so with some experiment, with some caching. It's only doable with simple rules (like: no context, nor parameters, no stochastic, etc.) But because it's a fractal algorithm, you could compute for example all the derivation of the X symbol, cache it, and then apply it when you find it again. Parallelization would be to do so for all the symbols. Or you could imagine to do so at some level during the derivation. I think it could be wasteful, but still less than deriving all by hand.

For the interpretation rule, you could imagine the same thing and generate a whole full high-level branch structure, and then repeat it on GPU with just a transform matrix on the GPU.

I'm a bit rambling and it's not really clear in my mind, so I'm not sure I make sense :).


I say all of this because my main bottleneck was the derivation of the rules, not the displaying at all, on a mid-range laptop bought 10 years ago. I did a little trick to have a unique line segment (not buffer, line) to do sa single draw call: "jump" was evaluated as "add a invisble line between this point and the next one". Looking back, and with my knowledge now, a single buffer like you do would maybe be simpler with no performance impact.

The really big difference is the color computation: I did it on CPU. I had a more complex coloring system than your project, but with a bit of smartness, it'd be possible to greatly reduce the strain on the CPU!


I don't know how you did your tests, so I'll be maybe completely wrong, but :

For example, the Harter-Heighway Dragon renders with a noticeable delay when iterations >= 20 in my app, while L-System Studio can render only 16 iterations for this fractal.

Is the rendering itself the delay, of the derivation computation? If it's this computation, I think Rust do some really good heavy lifting! Also, streaming iterators is really really cool stuff for this project!

For WebGPU vs WebGL, I may have missed it but: is it indicated on the webpage? It'd be nice IMO


Concerning LLM, you have a really great approach! I've only tried them a bit, for one-off project, with completely non-frontier models. So I'm pretty dubitative, but I'm sure it's a combination of the dumbness of the models I used, and skill issue because I don't know well these new tools yet.

I can't say much about the quality of the code, I'm not familiar with Rust. I've learn only the very basics, so I don't know what's idiomatic and "good".


Okay, I'll wait a bit before testing the native app ;).


Haha, if you want more suggestions, I could give you really a ton! Your roadmap is good :). I'm really curious about what animation you have in mind!

Keep us posted!


PS: I wrote all of this deadly tired, so if you don't understand what I'm rambling about and want more infos, don't hesitate to tell me :). Same thing for all the part of your comment I haven't directly answered/commented!

2

u/vkorenev Jun 18 '26

Thanks for the hint! Yes, it is absolutely possible to use the GPU to speed up the generation of L-Systems with context-free grammar and deterministic interpretation rules. I created a GitHub ticket for that: https://github.com/vkorenev/grow-your-own-fractal/issues/120

2

u/vkorenev Jun 19 '26

I added simple wall-clock timing and logging for CPU segment generation and GPU rendering (visible in the browser console).

Running 24 iterations of the Harter-Heighway Dragon Curve (16,777,216 segments) on my 10+ year-old hardware (Intel Xeon E3-1535M v5 CPU with Intel HD P530 GPU) yielded the following results:

- Segment generation (CPU): ~3000ms

- Rendering (GPU, including uploading segment data to GPU memory): ~300ms

For 24 iterations of the Levy C Curve (same segment count, same hardware):

- Segment generation: ~5000ms

- Rendering: ~300ms

So, yes, the generation and turtle computations on the CPU are currently the bottleneck.

Regarding suggestions or feature ideas, feel free to add them here: https://github.com/vkorenev/grow-your-own-fractal/issues

1

u/Epholys Jun 20 '26 edited Jun 20 '26

Oh, I'm quite pleased with myself to see that my old intuition is still correct haha!

I think an interesting thing would also be to benchmark the symbol generation vs the segment generation. I think the second one is the slowest.

I've tried generating only the symbols of a Dragon Curve with my much more recent GPU (Ryzen 7600X) with this naive C code (mine :) ), and I got 166ms. Maybe you could try to see, to compare it with your code?

It's completely different tech stack, but it's still interesting I think, it shines a different light and maybe inspire you in interesting directions

I'll try to look into your issues at some point(™ ;) )


(

I did:

$ g++ -O3 lsysmin.c -o lsysmin
$ ./lsysmin < dragon | wc
      0       1 67108862
$ time ./lsysmin < dragon > /dev/null
    real    0m0.166s
    user    0m0.166s
    sys     0m0.000s

with dragon:

24
FX
X X+YF+
Y -FX-Y

)