Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Make 3D art in your browser using Lisp and math (bauble.studio)
252 points by ianthehenry on Sept 6, 2022 | hide | past | favorite | 38 comments
Bauble is a toy that I've been working on for a few weeks, and I think it's reached the point where other people could have fun with it!

Bauble is based on raymarching signed distance functions, which are kind of like... 3D vector art? They're pretty common in the procedural art community and you can do some amazing things with them, but normally writing SDFs means writing low-level shader code.

I wanted to play with SDFs, but I found it very frustrating to translate "I want to rotate this" into "okay, that means I have to construct a rotation matrix, and then apply it to the current point, and then evaluate the shape...". So I made a high-level Janet DSL that compiles down to GLSL shader code so I could more easily play with mathematically defined shapes.

For more about SDFs, this mind-blowing video is what got me interested in the first place, and shows you what they're capable of in the hands of an expert: https://www.youtube.com/watch?v=8--5LwHRhjk




Wow, this is so beautiful! Your web app demo is very neat.

Do you think this can be used for live coding visuals?

I'd love to use it together with Glicol(https://glicol.org).

So far I have tested Hydra and p5.js; they can be used as CDN link or NPM packages.

Look forward to its progress.


Have you played around with Extempore? [0]

It's LISP, and has libraries and examples for live-coding + music generation + interfacing with the web, hardware, etc.

Small but passionate and helpful community. I've done some amazing stuff with it, live visuals + song generation on MIDI hardware synths using realtime web data like local weather, etc.

https://extemporelang.github.io/


Thanks! I'm not really sure how to make it work with Glicol -- I don't know anything about the livecoding world. But in theory it would be easy to add a new "magic variable" (shader uniform) for like "mean root squared audio sample amplitude over the last frame..."? You'd just need some way for Glicol to tell Bauble what the value should be. I don't know how they'd communicate or if there's some standard for integrating music and visuals...?

Apart from that big question mark I think it would be very suitable for livecoding visuals, as you can write some impressive effects with very little code. Easy CSS change to make the canvas full-screen and like overlay the code on top of it. That's a thing that livecoders do, right?


> if there's some standard for integrating music and visuals...?

In terms of translating audio to variables useful for driving visuals, ColorChord is getting some traction; it's an algorithm that powers a technology called AudioLink, which is growing beyond its origins in VRChat.

https://github.com/cnlohr/colorchord

https://www.colorchord.net/

https://github.com/llealloo/vrc-udon-audio-link

https://github.com/llealloo/vrc-udon-audio-link/blob/master/...


Something like this:

https://youtu.be/iKj7IibG0OU

I think both Hydra and p5.js render things to a <canvas>, which is probably the same as what your demo does, right?

Then we just need to set some CSS for the Canvas to make it full screen and hide behind the code editor.


Ohhh I think I misunderstood how this works. You write the visualization ahead of time, and then you livecode the music only? Bauble would work well for that -- you could just grab the compiled shader source and integrate it into your livecoding environment; wouldn't even need to integrate the Bauble runtime. All you'd need to do is set a few uniforms and issue a draw call.

I was imagining something where you switch between coding audio and visuals on the fly -- which is still totally possible, but would require a bit of work to get them talking to each other.


Well sometimes you change the visual code also in real-time. The video above was just for showing the canvas works so I did not edit the visuals code there.

I post the hydra link here. There are lots of demo there:

https://hydra.ojack.xyz/

So far I haven't tried to make them talk such as sync the beat etc. But I think with web worker it is doable.


Ohhh I totally missed that you're the author of Glicol. Okay. So you integrated Hydra as like a first-class thing -- I see I see. I thought you were plugging two 3rd party things together.

So I'm guessing that the best case scenario for you is to import Bauble as like a normal JavaScript dependency, and then use the editor built into the Glicol UI to write scripts, and then just call like Bauble.compile(canvas, script). Right?

Bauble doesn't really know how to be embedded in another page right now -- it's more like an app than a library. But it would be possible to extract the core parts. It's a little tricky because it uses WASM, so it kinda needs to load itself a little specially, but I'm sure there's some way around that.

Would be cool to sync something like this to music! https://twitter.com/ianthehenry/status/1567228698373533696 (ignore the terrible lighting. lights are coming one day)


Yeah. Glicol language and audio engine is written in Rust and compiled to WASM. I still manage to export the WASM module to an NPM package (https://glicol.js.org/). But Emscripten may be a little bit different, but there will always be some solution I guess. I've watched your repo haha.


This demo and the comments makes me wish for a button underneath the original link that says "upvote everything here." What an incredible project and what great comments. Thanks everyone.


This is beautiful. My apologies if I missed it, but is it possible to download the produced figure as an STL (or something equivalent)?


No; Bauble doesn't know how to "rasterize" SDFs into meshes; it only knows how to raymarch them. It's theoretically possible, but it's a pretty complex problem that would take me much too long to figure out and implement. So Bauble is relegated to just making pretty pictures for now. If you want to produce meshes using SDFs, check out https://libfive.com/


There's also ImplicitCAD (https://github.com/Haskell-Things/ImplicitCAD) which produces STLs, as it is designed for CAD. It uses implicit functions, which I believe are similar to SDFs (I believe the idea is not to necessarily correspond to the distance function).


Thanks!


I think that would be quite difficult, as raymarching does not produce polygons, so you'd need a way to polygonize the resulting sdf. Maybe marching cubes?


Surely not "something equivalent" that you are expecting, but my smartphone can do screen recordings, so here's a cropped version of what's displayed in its browser:

  http://www.cynix.net/2022/screenrecording-baubel.mp4
I cropped the screen recording to square format with the online service at clideo.com so they added their watermark.


STL is a format for 3D geometry, so the GP is asking if there's a way to export the 3D models themselves. Bauble will have a way to export recordings eventually! That's much easier to do than meshing surfaces.


Thanks, I did guess that it might be some specific format and not just a screen recording, but all these TLAs are hard to memorize.

BTW, it's a really nice example of the possibilities of Lisp, which reminds me to refresh my memories and start coding in Lisp again.


I've written a tool somewhat similar that can export meshes of sdf's created using a javascript api, check it out: https://github.com/stasilo/retrace.gl


Shamelessly mentioning our project shaderpark, which is also a live-coding interface for working with SDFs but using javascript!

https://shaderpark.com/


cool! never heard of your project, I've actually written something a bit similar :D https://github.com/stasilo/retrace.gl


Oh cool, that looks really nice! One of the fun things that our library does is that while it has built-in abstractions for SDFs, you can also just write pretty much whatever kind of shader (2D or anything) you want.


looks nice


Sorry for my ignorance, but what kind of lisp has piping? Or what is the vertical line operator called?

    (torus :z 60 30
    | twist :y 0.07
    | rotate-pi :y t :z 0.05
    ...


This is described later in the tutorial (ctrl-f "lisp heresy"). It's a macro that I wrote, not something built into Janet -- I'm sure I'm not the first person to do this, but I'm not aware of any lisps that have such a construct built-in.


Clojure has the thread first/last macros -> and ->> which pipes each result to the next form.


Yeah, and Janet copies Clojure's threading macros (that's how I implemented pipe syntax -- split on pipes, add some parens, and stick them into a -> form). I've just never seen it done infix like this -- it's very convenient when you don't have something like paredit to quickly wrap an expression.


And this is why Lisp is amazing. Seeing the question I immediately thought “this looks like a really nice convenience macro for the author’s preferred formatting”!


You should check out libfive! https://libfive.com/studio/. Previously discussed here: https://news.ycombinator.com/item?id=26930822. It is the child of Ao, previously discussed here: https://news.ycombinator.com/item?id=12319406.


libfive is great! And if you're into SDFs, libfive will give you something Bauble probably never will: the ability to export shapes as meshes, so you can 3D print them or import them into Blender or whatever.

libfive is only concerned with geometry, though, so you can't do any of the coloring/shading/procedural graphics stuff. And no animations. I think of Bauble as closer to Shadertoy than libfive in purpose, although they appear very similar.


This is awesome and I will avail myself of it pretty quickly. I may not use it directly for my project (I’m targeting SVG), but it already feels like I can benefit from the high level DSL as a glossary rather than the much more arduous journey of learning whole mathematical implementations of something just to find the next related term that’s closer to what I want to achieve. I’ll probably learn the maths too but it really helps not having to know the entire universe just to ask what I’m looking for :)


If you like this sort of thing then also

https://www.glslsandbox.com/?page=4

and

https://www.shadertoy.com

Unfortunately glslsanbox is not moderated very well so there's lots of spammy garbage there but also lots of really great stuff.


Is there a good framework for creating the same online ide/code demo as yours?

I want to make a live tutorial, I'm thinking about creating a static site generator to generate the same kind of demo you have here.


I'm using https://codemirror.net/ as the editor, and I'm basically just running an onchange event on every keystroke. Not very fancy or sophisticated. The details of what exactly happens in that event are very specific to WASM/Janet/Bauble, but I think you could do something similar with JavaScript code pretty trivially.

Long-term I think I'd rather break this out into a separate page with multiple canvases inline in the text -- so you can more easily scan through it/go back to previous sections -- but I was lazy and this was the easiest way to get it done.

Also, this is just a static site. With hand-written HTML because I've been too lazy to configure a static site generator yet...


This is awesome, how did you implement the live code editor?


It's CodeMirror! All I had to do was write a Janet grammar for it -- very easy to do. CodeMirror is pretty amazing -- I was able to implement the "edit values with your mouse" by just asking CodeMirror for the syntax node under the cursor, checking if it parsed as a number, and if so replacing it with a different string.

https://codemirror.net/

https://github.com/ianthehenry/codemirror-lang-janet

I went with CodeMirror after reading this post: https://blog.replit.com/codemirror and I've been super happy with it.


but what about your novel, ian


Nice!




Consider applying for YC's first-ever Fall batch! Applications are open till Aug 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: