4 ms·
https://bauble.studio/ https://bauble.studio/ is a lisp-based procedural 3D art playground that I hacked together a while ago. It's fun to play with, but it's a
by ianthehenry 2y ago
https://bauble.studio/ https://bauble.studio/ is a lisp-based procedural 3D art playground that I hacked together a while ago. It's fun to play with, but it's a very limiting tool: you can do a lot to compose signed distance functions, but there's no way to control the rendering or do anything "custom" that the tool doesn't explicitly allow.
So lately I've been working on a "v2" that exposes a full superset of GLSL, so you can write arbitrary shaders -- even foregoing SDFs altogether -- in a high-level lisp language. The core "default" raymarcher is still there, but you can choose to ignore it and implement, say, volumetric rendering, while still using the provided SDF combinators if you want.
The new implementation is much more general and flexible, and it now supports things like 2D extrusions, mesh export for 3D printing, user-defined procedural noise functions... anything you can do in Shadertoy, you can now do in Bauble. One upcoming feature that I'm very excited about is custom uniforms and embedding in other webpages -- so you can write a blog post with interactive 3D visualizations, for example.
(Also as a fun coincidence: my first cast bronze Bauble arrived today! https://x.com/ianthehenry/status/1827461714524434883 https://x.com/ianthehenry/status/1827461714524434883)
- techno_tsar 2y agoThis is completely nuts. Well done.
- samstave 2y agoStunning. That site needs to be seen. Thats great.
- holden_nelson 2y agoThis is phenomenal. Thanks for sharing.
- turtledragonfly 2y agoAm I right that the output of the lisp code is ultimately a plain GLSL shader (like one might find on shadertoy.com)? I built a SDF-based rendering system (2D) for my game, and one of the big hurdles was how to have them be data-driven, rather than needing a new shader for each scene or object. Would be curious if/how you tackled that problem (:
- ianthehenry 2y agoYep! It just outputs GLSL. It doesn't do anything smart -- it's a single giant shader that gets recompiled whenever you change anything, so it wouldn't really work for something like a game. I mean, it could handle like basic instancing of the form "union these N models, where N<256" but there's no way to change the scene graph dynamically.
- jkcxn 2y agoI've done this for a project where the SDF functions are basically instructions, and you can build up instrictions on the CPU to send to the shader. and then the fragment shader runs them like a mini bytecode interpreter. You can tile up the screen to avoid having too many instructions per fragment. Kinda wild idea and performance may vary depend on what you're doing
- turtledragonfly 2y agoThat's pretty similar to what I'm doing! The CPU builds an RPN expression (like "circle, square, union, triangle, subtract"), and the shader evaluates that in a loop. I wasn't able to find examples of other people doing similar, but it seemed too useful to not be invented yet (: Do you have any links to your work? I'm writing some blog posts for my approach, but haven't finished them yet. > You can tile up the screen to avoid having too many instructions per fragment. I don't quite understand this part... If a given SDF needs N instructions to be evaluated, then how does tiling reduce N? > performance may vary depend on what you're doing Yeah, fill rate was not good enough with a straightforward approach, so I had to cache the evaluated distance values to a (float) texture atlas, then use those to render to screen. Luckily, standard bilinear filtering on distance values produces pretty decent results.
- jkcxn 2y agoYes sounds like the same thing! I also couldn't find anyone else doing it. Sounds super interesting what you're doing so I'd love to read your blog post when it's done if you want to drop me a message/email. My project was using 2D SDFs for UI which meant you could use a bunch of primitive shapes and union/difference between them, and also add outlines, shadows, glows etc. This means that if you tile up the screen and use a union between two rectangles, only the tile with the overlap needs to calculate the union. It's a little more complicated in 3D with frustum culling. I was doing it in webgl which doesn't have storage buffers and so I had to use uniforms to pass the data which is a huge limitation. Apparently webgpu could be better so I will try to figure that out one day. But it is early prototype so no links or anything yet.
- juhanakristian 2y agoThis is amazing! Thanks for sharing
- kinow 2y agoLooks amazing, I was having fun with cssdoodle, and now I have two cool sites to do some programming+arts.
- avghaloplayer 2y agoThats kinda cool ngl!
- fuzzythinker 2y agoHe made quite a few useful videos demoing it. @ian Adding this to your help page would be helpful. https://www.youtube.com/@ianthehenry/search?query=livecoding https://www.youtube.com/@ianthehenry/search?query=livecoding