Show HN: Make 3D art in your browser using Lisp and math

bauble.studio

252 points by ianthehenry 3 years ago

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

chaosprint 3 years ago

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.

  • ianthehenry 3 years ago

    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?

    • chaosprint 3 years ago

      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.

      • ianthehenry 3 years ago

        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.

        • chaosprint 3 years ago

          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.

          • ianthehenry 3 years ago

            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)

            • chaosprint 3 years ago

              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.

  • soulofmischief 3 years ago

    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/

xrd 3 years ago

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.

averysmallbird 3 years ago

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

  • ianthehenry 3 years ago

    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/

  • frabert 3 years ago

    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?

  • jcynix 3 years ago

    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.

    • ianthehenry 3 years ago

      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.

      • jcynix 3 years ago

        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.

tehsauce 3 years ago

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

https://shaderpark.com/

  • stasilo 3 years ago

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

    • tehsauce 3 years ago

      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.

anhner 3 years ago

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
    ...
  • ianthehenry 3 years ago

    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.

    • spapas82 3 years ago

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

      • ianthehenry 3 years ago

        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.

        • eyelidlessness 3 years ago

          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”!

fros1y 3 years ago

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.

  • ianthehenry 3 years ago

    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.

eyelidlessness 3 years ago

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 :)

billconan 3 years ago

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.

  • ianthehenry 3 years ago

    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...

icu 3 years ago

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

shadytrees 3 years ago

but what about your novel, ian