Skip to content

TSL: Add switch/case. #30935

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 17, 2025
Merged

TSL: Add switch/case. #30935

merged 3 commits into from
Apr 17, 2025

Conversation

Mugen87
Copy link
Collaborator

@Mugen87 Mugen87 commented Apr 15, 2025

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.

Copy link

github-actions bot commented Apr 15, 2025

📦 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
Copy link
Collaborator

sunag commented Apr 16, 2025

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
Copy link
Collaborator Author

Mugen87 commented Apr 16, 2025

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
Copy link
Collaborator

sunag commented Apr 16, 2025

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

@Makio64
Copy link
Contributor

Makio64 commented Apr 17, 2025

@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
Copy link
Collaborator

sunag commented Apr 17, 2025

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
Copy link
Collaborator Author

Mugen87 commented Apr 17, 2025

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
12 checks passed
@Mugen87
Copy link
Collaborator Author

Mugen87 commented Apr 17, 2025

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