Skip to content

TSL: Add switch/case.#30935

Merged
sunag merged 3 commits into
mrdoob:devfrom
Mugen87:dev1
Apr 17, 2025
Merged

TSL: Add switch/case.#30935
sunag merged 3 commits into
mrdoob:devfrom
Mugen87:dev1

Conversation

@Mugen87

@Mugen87 Mugen87 commented Apr 15, 2025

Copy link
Copy Markdown
Collaborator

Related issue: #30900

Description

The PR adds switch/case syntax to TSL.

material.colorNode = Fn( () => {

	const col = color().toVar();

	Switch( 0 ).Case( 0, () => {

		col.assign( color( 1, 0, 0 ) );

	} ).Case( 1, () => {

		col.assign( color( 0, 1, 0 ) );

	} ).Case( 2, () => {

		col.assign( color( 0, 0, 1 ) );

	} ).Default( () => {

		col.assign( color( 1, 1, 1 ) );

	} );

	return col;

} )();

The values of the switch and case statements can be primitives or node objects.

@github-actions

github-actions Bot commented Apr 15, 2025

Copy link
Copy Markdown

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 336.33
78.33
336.33
78.33
+0 B
+0 B
WebGPU 544.59
150.88
545.17
151.06
+582 B
+182 B
WebGPU Nodes 543.94
150.72
544.52
150.91
+582 B
+182 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Before After Diff
WebGL 465.48
112.23
465.48
112.23
+0 B
+0 B
WebGPU 618.25
167.17
618.8
167.34
+551 B
+172 B
WebGPU Nodes 573.12
156.52
573.67
156.68
+551 B
+160 B

@sunag

sunag commented Apr 16, 2025

Copy link
Copy Markdown
Collaborator

The solution seems even more elegant than the of GLSL, but I fear it will not be compatible with all use cases, switch() works like a "cascade", sometimes we have more than one case without using break.

switch( value ) {

	case 0:
		a = 1;

	case 1:
		b = 1;
		break;

}

@Mugen87

Mugen87 commented Apr 16, 2025

Copy link
Copy Markdown
Collaborator Author

I've added support for the following use case:

switch( value ) {

	case 0:
	case 1:
		b = 1;
		break;

}

So meaning cases with the same block. However, other permutations of switch/case like the one you have shared in #30935 (comment) are more tricky to implement and we quickly reach a point where the code gets quite complex. Right now, the code in StackNode is still straightforward.

I'm not sure how common the different switch/case permutations are but I don't think we have to support all of them. It's best if you decide if Switch()/Case() in the current form is a meaningful addition or if we guide users always to If()/Else(). Both have their pros and cons.

@sunag

sunag commented Apr 16, 2025

Copy link
Copy Markdown
Collaborator

@Mugen87 What do you think we do .Case( 1, 2, () => {} ) instead of .Case( 1 ).Case( 2, () => { } )?

@Makio64

Makio64 commented Apr 17, 2025

Copy link
Copy Markdown
Contributor

@Mugen87 What do you think we do .Case( 1, 2, () => {} ) instead of .Case( 1 ).Case( 2, () => { } )?

I'm not sure to understand how can i do things in case 1 => no break => add to case 1 my stuff in case 2 ? maybe add .break() or do you guys think it's ugly ?

.Case( 1, ()=>{someStuff} ).Case( 2, () => { additional stuff } ).break().Case( 3, ()=>{ another independant task } )

@sunag

sunag commented Apr 17, 2025

Copy link
Copy Markdown
Collaborator

To be honest, I don't like the classic break syntax of switch/case, I'm even happy if we follow something more similar to WGSL and have a limitation as @Mugen87 quoted. We could even put the Break() syntax inside the Case(), but would pollute the code and would require a lot of work since the usage I mentioned are exceptions but I couldn't help but mention it.

@Mugen87

Mugen87 commented Apr 17, 2025

Copy link
Copy Markdown
Collaborator Author

What do you think we do .Case( 1, 2, () => {} ) instead of .Case( 1 ).Case( 2, () => { } )?

I've implemented this approach in the last commit. You can now assign an arbitrary number of values to a single case. I actually prefer this approach compared to the previous one 👍 .

I agree to exclude the fallthrough syntax. I was never a fan of it in any programming languages since it tends to produce hard-to-follow code, imo.

@sunag sunag added this to the r176 milestone Apr 17, 2025
@sunag sunag merged commit ec16a14 into mrdoob:dev Apr 17, 2025
@Mugen87

Mugen87 commented Apr 17, 2025

Copy link
Copy Markdown
Collaborator Author

Updated the TSL wiki page: https://github.com/mrdoob/three.js/wiki/Three.js-Shading-Language#switch-case

RuthySheffi pushed a commit to RuthySheffi/three.js that referenced this pull request Jun 5, 2025
* TSL: Add switch/case.

* StackNode: Support Case() sequence.

* StackNode: Refactor `Case()`.
RuthySheffi pushed a commit to RuthySheffi/three.js that referenced this pull request Jun 5, 2025
* TSL: Add switch/case.

* StackNode: Support Case() sequence.

* StackNode: Refactor `Case()`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants