Node based editor for TSL

Hey everyone! With Three.js moving toward WebGPU, TSL is becoming the standard. However, writing TSL by hand can feel like a step back if you’re used to visual tools like Blender Nodes or Unreal’s Material Editor. I’ve been working on TSL Graph to bridge that gap. It’s a visual graph that lets you build shaders with nodes.

It’s in public beta and I’d love for this community to try and break it. What nodes are missing? How’s the UX?

Try it here: http://tsl-graph.xyz/

6 Likes

Enjoy:

Don’t panic. It is not a bug in the editor. It is just my Firefox hates r182 (but works fine with r181).

If, Loop, Fn?

1 Like

Yeah, kinda panicked tbh when I saw the notification.

Yeah, I’m trying to figure out if and loop next. It’s kinda hard to fit them in nodes editor model (or at least I am struggling). I’d love to discuss if you have any ideas for it. Also isn’t Fn is just a function to structure or wrapper reuse logic? I use it internally for subgraphs and code nodes. Have you tried them?

1 Like

Just pinging @trusktr

1 Like

I handled the if like this

You basically plug in the value for false, true, and a Boolean for the condition. If the Boolean is true it returns the value for true if it’s false it returns the value for false.

1 Like

actually i did a “switch” and for some reason did a < = > with an if

btw what are you using to render the graph?

1 Like

I’m handling switch in same way as you. I kinda liked your approach for “if” block. I need to dig a little more though.

I’m using react flow for rendering graph.

It would be great if it were open source.

1 Like

Yeah, it will be open source for sure.

2 Likes

Great editor, there is just one bug:

the preview model doesn’t have tangents, so we can’t use the “Tangent Local” node as it throws an error (maybe just need to call geometry.computeTangents()).

Apart from that is working great, really handy.

1 Like

Hi! Very useful tool. Any timeline for how long the public beta will go and if/when open source release is planned? Would be great to be able to integrate it with other existing tools / editors / etc.

1 Like

Thanks! No timeline is planned tbh. The only reason I haven’t open sourced it yet is because I am unable to decide the direction I wanna go in with this tool. For integration we have already experimenting with iframe and post message api and integrated within three js’ insepector.

If you wanna integrate in some other application maybe we can discuss what you will need and collaborate. here is editor api example GitHub - bhushan6/editor-integration-example · GitHub

if you need anything, feel free to DM me here. :slight_smile:

1 Like

This is out of control. Really, really nice work! So many of the rough edges I expected are just absent. It’s very pretty, but also runs really nice too. Too many other awesome little details to fawn over here, but I really appreciate the level of polish you’ve put in. Congrats and keep it up!

Only missing feature I expected was drag-drop directly in from nodes menu. This was quickly replaced by dragging new nodes directly from connections, so not a biggie. Just a UX bump.

I only found a few significant bugs:

  • it can be finicky to enter a negative number. With 2, select all and type -, 3. Expected -3 but get 03.
  • post graph (!!! are you kidding me!?!!!) seems like it will be awesome but doesn’t seem to work or do anything. I assume it’s just unfinished.

Couple of other suggestions:

  • Show datatypes (connection colors) as “what they currently are” with their existing inputs, even if the node can theoretically accept “any”.
    • e.g. all the connections when adding two vec3s should be cyan.
    • this will give better feedback about what datatypes are flowing, and good visibility on behavior when there’s casting/swizzling going on (e.g. multiply a vec3 with a float)
    • line shape, color code, and gradients are all stunning
  • Lovely to be able to drag numeric fields. A common type of number is a ratio (0..1) and I find the 0.1 steps too coarse for this use.
    • A finer step (even 0.01), at least at magnitudes < 10, would be fabulous.
    • Better yet, custom settings for fields (range, step, curve/mapping, etc) although metadata may be a problem here.
    • You may also want to consider modulating mouse sensitivity with magnitude. For example, the move from 1.0 to 1.1 oughta feel similar to 100 to 110. (Just be careful to keep a minimum effect to allow crossing zero.)
  • Thumbnails for each connection, or at least a “debug peek” when you hover. This would vastly improve the debugability of graphs.
  • Multi-select to move and create groups and subgraphs.
  • Alt-drag to duplicate nodes (though copy-paste works great)
  • Insert a new or existing node “onto” a connection, “intercepting” the connection. This might be a ux challenge…
  • “Under the hood”, temporarily implement the disconnected properties of the selected node as uniforms to allow fast, smooth feedback when adjusting them (avoid recompiling shader).
    • I notice when I add a uniform, that gives much better feedback.
    • Obviously adding secret uniforms for all disconnected nodes could be a performance disaster. Not sure.

This is all probably on your list, so I’ll stop here. Let me know if you want me to submit any/all of this with your feedback form.

Amazing stuff. Very impressive

1 Like

Thank you so much!! This means a lot tbh. : )

  • Yeah, I agree number inputs are not great at current state, but I haven’t able to figure out the solution.

  • Post graph is in working condition, can you please explain what exactly didn’t work for you? here are some examples with post graphs:
    https://www.tsl-graph.xyz/share/jn7bqazjr7zpt52qjgkr5ssdhx81e6hr
    https://www.tsl-graph.xyz/share/jn7brq0t708avnhned8rwxbt3s81fpyx
    https://www.tsl-graph.xyz/share/jn7ex3vawq4ggbmrptzhc09bc180hd94

  • Yeah, I wanna add type inference for node ports, I was just not sure if it was worth it. Actually I had also done some small POC for it but at that time didn’t get time to create a full fledge feature and then I kinda forgot about it. But yeah surely will look into it

  • Numeric scrubber can be improved, I agree.

  • Thumbnail, as in debug view of each node? If thats what you mean, it exists. Just go to bottom toolbar and look for debug mode (third from right side) and turn it on and you should be able to see debug view of selected node in properties panel on right side.

  • Multi select does exists, use ctrl + click or go to select mode (second option from left side in toolbar) to drag and select multiple nodes. And then you can move, delete, copy, create group and subgraph for your selection.

  • Yeah, I also wanted to implement this, all the other shader graphs has this, but couldn’t figure out how they do it. Only creating hidden uniform seems like possible solution. Also I am not sure about performance implication tbh, need to try it.

    Thanks for trying the tool and giving such detailed feedback!!

1 Like

Glad to provide feedback, a delight to use. Great tool.

I’ll let you marinate on the numeric text input problem. In general, you probably want to start by avoid modifying the input value while it’s focused. (If you’re using React, this means switching to an “uncontrolled” input paradigm). This will probably mean you will keep a separate (“last good”) value for each field to allow the user to faff around with possibly-invalid inputs until blur, when you can sync the field string to the internal value.

Regarding post graph, I was just unlucky. :sob: On my first exploration I immediately ran into a bug that disables the whole post process until you reload. If you add two gaussian blurs in series, it triggers this condition. (Whether that’s a reasonable thing to do, is up for grabs… haha)

But now that I know to avoid this I see that the post graph is really wonderful. Already super useful and very promising.

A few things I miss (or wonder) in post graph:

  • Can we access viewport width/height (especially useful for calculating aspect ratio, for adjusting noise UV to stay “square”)
  • Is there a way to invoke ThreeJS’s tonemapping code?
  • What about sRGB encode/decode? (Maybe should we just use exponent.)
  • Screen UV → Texture → Output seems to disable output (goes black while connected).
  • What is the difference between depth and depth texture? If “color” and “depth” are convenience samplers, why is there “normal texture” but no “normal”. It’s good to be “batteries included” (sensible defaults) but maybe you could make the advanced/optional outputs opt-in via a properties checkbox (like how the texture node exposes colorspace, etc).
  • Is it possible to mix data from more than one render (e.g. via a rendertarget texture)?
  • Wondering if you would implement a way to detect specific objects from the scene, either via a stencil read node, or a “cryptomatte” texture. Maybe there are other ways, too. This would allow implementing effects like “selected object” highlights and outlines, as well as object-specific post processing.

Type feedback (inference) would be very welcome. I don’t think it’s urgent or high priority, but it’s super useful “system feedback”. Would provide small, but constant “course-corrections”.

Debug view is a great feature, but doesn’t seem to be working consistently for me. With the Noise Gradient template, just pulling the color property into a vec4 and selecting that shows a bright pink sphere. I wondered if this was because the render is HDR, but multiplying but 0.1 has no effect. Any ideas?

Separately, while “select to inspect” is perfectly reasonable and useful, I’d personally love to be able to see a preview of the “texture value” at each node. This is relatively uncommon in node editors, but Godot seems to have this feature (see screenshot below). This might be a little tricky to implement, but seems plausible: either with multiple render outputs, or by compiling an “early exit” shader for each node preview.

Re: multi-select, glad this works, thanks!

I think cmd-click is unlikely to be discovered by most users (even though it is conventional for toggling selection of single items). In this context, shift click is probably the expected action for multi-select.

I noticed box select is bound to shift-drag, which is also a delightful discovery! But similarly, I think this feature will probably not be easily discovered with this binding.

So, I guess this is why you chose to use cmd-click for multi-select picking. Perhaps both actions can use shift? (Seems like it should be able to work.)

I think you probably just need time and space to continue to work your magic, so I’ll back off now. Sing out when you next want me to take it for a spin. Have a think about where you’d like to collaborate in the future.

Yeah, had similar thing in my mind for number inputs. I will just try that and push it.

Post graph is not that mature tbh, I have put out as basic version as possible at that time, since I thought it will be interesting and then didn’t really get any feedback from others as well as I didn’t try it a lot myself, so never iterated on it ever.

  • Yes, viewport size is available today via the Resolution node. It maps to screen/render resolution, so x / y gives you aspect ratio for keeping UV-driven noise square.

  • tonemapping is not exposed in any way rn.

  • sRGB encode/decode is also not exposed as dedicated nodes yet. For imported textures, the Texture node already has a color-space setting

  • Screen UV → Texture → Output going black is not intended behavior. If you mean sampling the scene, the supported path is Post Input.sceneTexture → Sample Texture Node, and UV even defaults to screen UV there. If that graph is black, then its a bug for sure.

  • Yeah, “color” and “depth” are convenience samplers. Agreed that normal should be there as well.

  • No, graph only gets one scene render, plus its depth/normal attachments by default.

  • Maybe, once the post graph is mature enough. It would be great feature but does not seem like feasible or useful in current state of app.

Well, I have added type inference for Math nodes, you should be able to see derived type of output now for math nodes.

Yeah, totally agreed with debug view per node base is much more better UX than what I have added rn, But initially I was just concerned about perf tbh, but Ig I will just add per node debug view and lets see how that works out.

Oh, initially it was “shift” to select multiple but I was personally used to using cmd for that action so later I changed it lol. If shift is standard then I will add that back. Shouldn’t be an issue.

I kinda haven’t worked on this for a couple of months now (except for two days back when I added type inference), ig its time to make it open source considering I am unable to give time for its development.

2 Likes