# Does TSL Switch works?

**URL:** <https://discourse.threejs.org/t/does-tsl-switch-works/90157>\
**Category:** Questions\
**Tags:** tsl, shaders\
**Created:** [March 3, 2026, 10:31am UTC](https://discourse.threejs.org/t/does-tsl-switch-works/90157 "2026-03-03T10:31:01Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![serk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/serk/32/49879_2.png) [@serk](https://discourse.threejs.org/u/serk)\
**Post date:** [March 3, 2026, 10:31am UTC](https://discourse.threejs.org/t/does-tsl-switch-works/90157/1 "2026-03-03T10:31:01Z")

</div>

I’m migrating a GLSL shader to TSL where I need a Switch statement to select a texture from an array. Playing around I think the Switch function is broken.  
This is the code:

```javascript
// Simple uv.x animation

const {vec4, Switch, uv, int, min } = await import( ‘three/tsl’ );

const uv0 = uv();
const index = min(uv0.x.mul(5).toInt(), 5);
const result = Switch(index)
.Default(() => { return vec4(0, 1, 1, 1); })
.Case(int(0), () => { return vec4(1, 0, 0, 1); })
.Case(int(1), () => { return vec4(0, 0, 1, 1); })
.Case(int(2), () => { return vec4(0, 1, 0, 1); })
.Case(int(3), () => { return vec4(1, 0, 1, 1); })
.Case(int(4), () => { return vec4(1, 1, 0, 1); })

output = result;

```

and you can test it here:

> **[three.js examples](https://threejs.org/examples/?q=tsl#webgpu_tsl_editor)**

The resulting shader is obviously wrong.

---

<div class="post-metadata">

**Author:** ![Umbawa\_Sarosong](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/umbawa_sarosong/32/30107_2.png) [@Umbawa\_Sarosong](https://discourse.threejs.org/u/Umbawa_Sarosong)\
**Post date:** [March 3, 2026, 10:36am UTC](https://discourse.threejs.org/t/does-tsl-switch-works/90157/2 "2026-03-03T10:36:06Z")

</div>

Looks like it might be related to how the **`index`** is computed. Since **`min(uv0.x.mul(5).toInt(), 5)`** can return **`5`** , but you only define cases **`0–4`** , the switch might be hitting the default path or generating odd code in the transpiled shader.

You could try clamping it to **`4`** instead:

**`const index = min(uv0.x.mul(5).toInt(), 4);`**

Also worth checking the generated shader code to see how TSL expands the **`Switch`**. Sometimes these constructs end up being translated into chained conditionals rather than an actual switch, which can expose edge cases.

If the goal is selecting a texture from an array, another workaround might be using chained **`select`** or **`mix`** operations based on comparisons, since those tend to compile more predictably in node systems.

---

<div class="post-metadata">

**Author:** ![serk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/serk/32/49879_2.png) [@serk](https://discourse.threejs.org/u/serk)\
**Post date:** [March 3, 2026, 12:27pm UTC](https://discourse.threejs.org/t/does-tsl-switch-works/90157/3 "2026-03-03T12:27:01Z")

</div>

Not only the Switch doesn’t work but also the If. This is the r183

```javascript
const {vec4, If, uv, int, min } = await import( ‘three/tsl’ );

const uv0 = uv();
const index = min(uv0.x.mul(5).toInt(), 5);
const result = vec4(0,0,0,1);
If(index.equal(0), () => result.assign(vec4(0, 1, 0, 1)))
.ElseIf(index.equal(1), () => result.assign(vec4(1, 0, 0, 1)))
.ElseIf(index.equal(2), () => result.assign(vec4(0, 0, 1, 1)))
.ElseIf(index.equal(3), () => result.assign(vec4(0, 1, 0, 1)))
.ElseIf(index.equal(4), () => result.assign(vec4(1, 0, 1, 1)))
.Else(() => result.assign(vec4(1, 1, 0, 1)))

output = result;

```

I don’t know how but sometimes I got an output where there are way too many if else in the shader.

---

<div class="post-metadata">

**Author:** ![serk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/serk/32/49879_2.png) [@serk](https://discourse.threejs.org/u/serk)\
**Post date:** [March 3, 2026, 12:35pm UTC](https://discourse.threejs.org/t/does-tsl-switch-works/90157/4 "2026-03-03T12:35:27Z")

</div>

but ternary does work.

```javascript
const {vec4, select, uv, int, min } = await import( ‘three/tsl’ );

const uv0 = uv();
const index = min(uv0.x.mul(5).toInt(), 5);
const result = select(index.equal(0), vec4(0, 1, 0, 1),
select(index.equal(1), vec4(1,0,0,1),
select(index.equal(2), vec4(0,0,1,1),
select(index.equal(3), vec4(0,1,0,1),
select(index.equal(4), vec4(1,0,1,1),
vec4(1,1,0,1)
)))));

output = result;

```

---

<div class="post-metadata">

**Author:** ![PavelBoytchev](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/pavelboytchev/32/38639_2.png) [@PavelBoytchev](https://discourse.threejs.org/u/PavelBoytchev)\
**Post date:** [March 3, 2026, 12:41pm UTC](https://discourse.threejs.org/t/does-tsl-switch-works/90157/5 "2026-03-03T12:41:12Z")

</div>

> [@serk](#):
>
> Not only the Switch doesn’t work but also the If. This is the r183

`Switch` works fine. Try in a standalone file, not in the TSL editor.

[https://codepen.io/boytchev/pen/WbGrbvp?editors=0010](https://codepen.io/boytchev/pen/WbGrbvp?editors=0010)

[![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/c/5/c557eee09358aae7fb7221a14a7ae628f6ae53b5.png)](https://codepen.io/boytchev/pen/WbGrbvp?editors=0010)

---

<div class="post-metadata">

**Author:** ![serk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/serk/32/49879_2.png) [@serk](https://discourse.threejs.org/u/serk)\
**Post date:** [March 4, 2026, 11:16am UTC](https://discourse.threejs.org/t/does-tsl-switch-works/90157/6 "2026-03-04T11:16:42Z")

</div>

Thanks, that gives something to look at. And… okey looking more comments and debugging the example, as you mention, they works fine, but only if they are inside a Fn. Not sure if this is a mandatory constraint but okey.
