TSL considered harmful

Not a THRE.js user myself, but I’ll pitch in my 2 cents anyway:
The 2 main objections here are relatively easy to resolve within TSL.

  1. For streight-up math expressions, just have some API function that takes in a templated string of a single-line math expressions, and it should be able to be substituted directly to code that both WGSL and GLSL should be able to ingest as-is, because they both support the same basic operators and parenthesis rules. Whenever any expression-node is passed into the templated string, it would automatically be converted into a variable which would be reused as-needed in the expression conversion and in any other place, which leads me to…
  2. In any case where the same expression object is being passed into multiple places, instead of letting it get evaluated multiple times, just convert it to a variable at the outset, and memoise that to the object-id of that expression. Pretty sure js supports checking object identity, not just equality, so that should be trivial to memoise into some semi-global map. As long as expression objects are immutable, this should work.
3 Likes

If you put your systems design hat on, would you do this in a “renderer” or some kind of a “compiler” considering how web apps work and where webgpu rendering actually takes place?

When you load your web app and say “kick of a game loop” do you want the first frame to take forever because it’s doing all this stuff that could have been done already?

1 Like

This is not my opinion, but rather the experience of the maintainers. Examples: Add TSL VFX Tornado by brunosimon · Pull Request #29020 · mrdoob/three.js · GitHub

This is quite interesting, i don’t know if three ever linked to paid courses before. Is there room for more? If someone else makes a paid TSL course, would it be included in the examples with a link to the course? I’m not saying this in jest, it would be a huge motivator for someone to write a bunch of stuff.

2 Likes

I do not see where the problem is. The following two situations look conceptually equivalent to me and Three.js do not forbid any of them.

Situation 1: real-time shadows (or lights) make rendering too slow, so you bake them into textures and apply them directly. Extra off-line efforts, but fast real-time rendering.

Situation 2: translation from TSL into shader source takes a lot of time on first render, so you baked them offline, get the strings and inject them directly. Extra off-line efforts, but fast real-time first frame rendering.

If anyone know others attempt/libraries to compile WGSL shaders on webGPU without learning it, I’m interested. As far I know, TSL is the only solid one (most operations/functions are now abstracted).

Sooo, by lack of better options (or any options at all). It’s the winner for me :rofl:

1 Like

Consider this:

  1. TSL is no simpler than WGSL as a language. It may offer a bit of automation, but at the cost of clarity and readability.
  2. The number of projects supporting TSL language is exactly 1: three.js. The number of projects that support WGSL is probably in tens of thousands at this point and keeps on growing day by day
  3. TSL is a drastically different language from popular modern graphics languages like: WGSL, HLSL, GLSL and Metal. This means that learning TSL is less valuable as the knowledge is less transferrable to these other languages/platforms.

There’s this head-trick with node-based languages. Because you can have a graphics wrapper on it, or because the code looks like JS - one can easily be convinced that it’s a “simpler” and “easier” language. That is simply not the case.

Something like Unreal’s blueprints language is not simpler than C++, it’s easier to use. Why is it easier to use? - because the tooling is excellent, not because of the language itself. You don’t have to wait for compilation, you have excellent built-in debugger, the validation and autocompletion facilities are excellent etc.

If you like TSL - more power to you. Use whatever you like, or don’t - I’m not the boss of you :sweat_smile:

But at that point isn’t it a ShaderMaterial?

1 Like

Absolutely, ShaderMaterial (or even RawShaderMaterial).

1 Like

Don’t you have this in glsl and wgsl though? Not sure why you would need in JS

That would be ideal, my understanding is that it won’t exist.

As a programmer, I have found TSL to be extremely useful in certain situations.

For example, I have written a few particle generators over the years, and I find that the TSL version in this program is preferable to anything I have written. I have used modified versions of this program in many settings.

The advantages are that it does not require a lot of math and works through the nodes.

I would not use TSL to write a math-intensive shader (I actually tried doing that), but it can work on the fringes, simplifying a lot of the organizational tasks.

Perhaps TSL will become more useful as more operations (math or otherwise) are converted to nodes?

1 Like

This is the first time I hear a shading language does not require a lot of math :slight_smile:

Isn’t it almost all math? Linear algebra, trigonometry?

1 Like

Thank you, @Usnul for starting this discussion. The same thing was going through my head for a long time.

For me, it’s straightforward; TSL is good. But, I don’t like it :sweat_smile:.

It’s good because it’s doing the job, and working with TSL requires less setup (compared to the old way), and there are a bunch of other reasons, like.

  • It supports WebGPU (the main reason for me to switch to TSL)
  • I don’t have to think much about browser support
  • We have a lot of examples available
  • The Three.js team is actively working on it

So from a technical and future-facing standpoint, it makes sense.

The reason I don’t like it is that the developer experience is not great.
At least, that’s not the case with me, and after this discussion, seems like it’s not only my problem.

The biggest issue is developer experience. If I run into a bug, it’s extremely hard to understand what’s going wrong. Ideally, if you understand what you wrote, you should be able to debug it yourself.

That becomes very difficult when:

  • Error messages aren’t clear

  • The abstraction hides too much

  • You don’t really see what the final shader code is doing

Better error feedback alone would improve things massively.

One more thing I would like to add is, how do you optimize code when you don’t really know what the generated code looks like?

At that point:

  • Performance becomes the responsibility of the maintainers

  • Developers are just “hoping” the system outputs something efficient

That feels uncomfortable when working on performance-heavy graphics.

If the solution to edge cases is:

“Just write custom code”

Then we’re back to writing separate logic for WebGPU and WebGL. Which kind of defeats the promise of abstraction.

I’m not saying TSL is bad.
TSL is new.
WebGPU is new.
3D graphics are already hard.

So this phase is kind of expected.
But the only way tools improve is through discussions like this.

1 Like

It doesn’t seem possible if some of the nodes generate inefficient code. However, that might be at this moment, there’s no reason why you wouldn’t be able to optimize this?

Even GLSL you wrote you could run through some optimizer? Why wouldn’t it be possible here? Getting there is a different question, what if it takes a few minutes to run those optimizations?

I couldn’t agree with this more, but I don’t feel like I’ve seen much discussion around this. My impression is that three is possibly prioritizing creative coding. If so, then there’s probably no discussion to be had, this is the way.

1 Like

There is not a lot of math in that specific program. You merely use tsl to input/compute a few values which are fed into nodes, some of which are fed into other nodes.(see lines 70-104).

In my infinite ignorace why threejs don’t offer a equivalent of rawShaderMaterial but with WGSL? @sunag so the people can still use TSL but if you want you can use WGSL

2 Likes

I have used a RawSahderMaterial from what I remember, but I am not sure if it is supported in TSL.

Not sure you are going to get an answer

:smiling_face_with_tear:

1 Like

Would wgslFn resolve some WGSL needs?

Where do you plug it in?

Aren’t shaders just a function? It’s “void main()”. So in that sense a wgsl function would be a shader. But without some kind of shader material, where do you put it?

I haven’t worked with it but my guess is that a mesh basic material would work, just feels kinda awkward.

That seems like the closest thing to an actual shader function since you only have one input (output) similar to gl_FragColor.