<p>No, but the way this is written has a min of 3 branch's and max of 4. It would be better off with the plain old (x&lt;y)&amp;&amp;(x&lt;z) return 0, y&lt;z return 1, return 2.</p>
<p>You could also do a pure logic op approach:</p>
<pre><code>int mx = (y&lt;z)&amp;&amp;(y&lt;x);
int mz = (((z&lt;y) &amp;&amp; (z&lt;x))*2;
return mx + mz; // both are false if x is min value and sum is zero
</code></pre>
<p>which would turn into this:</p>
<pre><code>uint MinIndex( float x, float y, float z )
{
   return ((y&lt;z)&amp;&amp;(y&lt;x)) + ((((z&lt;y)&amp;&amp;(z&lt;x))*2);
}
</code></pre>
<p>If y,z could be equal and less then x then an extra  <code>+ ((y==z)&amp;&amp;(x&lt;y))</code> would be needed which would return 1.</p>
<p>There may be some clever way to reduce this down to less operations but it's not popping into my head... at any rate logic operations are often fast but ugly to look at.</p>
<p>You might also try the mix function, something along the lines of...</p>
<pre><code>uint MinIndex(float x, float y, float z)
{
   float YltX = float(y &lt; x);
   float ZltX = float(z &lt; x);

   return uint(mix(YltX, 2.0 * ZltX, ZltX+float(y==z)));
}
</code></pre>
<p>I haven't checked this one for accuracy but using mix also tends to be rather speedy.</p>

CC BY-SA 4.0
2023-08-26T18:44:59.713Z
Wow that's very creative =)
Thomas
CC BY-SA 4.0
2023-08-26T11:31:47.290Z
2023-08-26T11:31:47.290Z
pmw1234
<p>Here is another approach that handles the case where multiple components may be the minimum/maximum and you want to handle that. You calculate a &quot;mask&quot; that indicates whether the component is a min/max.</p>
<pre><code>bvec3 mask = lessThanEqual(vector.xyz, min(vector.yzx, vector.zxy); // makes a &quot;one-hot&quot; bool vector, where the min component(s) is true and the others are false.
</code></pre>
<p>To use it, multiply your operation by the mask, e.g.</p>
<pre><code>vec3f colorMask = greaterThanEqual(color.rgb, min(color.gbr, color.brg));
vec3f maxColor = color * vec3f(colorMask);
</code></pre>
<p>You can also convert the vector to a scalar, like so:</p>
<pre><code>uint index = dot(ivec3(mask), ivec3(0, 1, 2));
</code></pre>
<p>But that fails if multiple components are minimum/maximum.</p>

CC BY-SA 4.0
2024-01-14T23:07:40.203Z
2024-01-14T23:07:40.203Z
Mathis Brossier
<p>I have written a function in GLSL that returns the min index (index 0 is the x component, 1 is the y component, and 2 is the z component) of a vec3 variable.</p>
<pre><code>uint getMinIndex(vec3 vector)
{
    float minValue = min(min(vector.x, vector.y), vector.z);
    if(vector.x == minValue)
        return 0;
    if(vector.y == minValue)
        return 1;
    return 2;
}
</code></pre>
<p>As you can see, this function causes branching and slows down the whole shader.... Is there already such a function in GLSL? Or is there a better way to do this without branching?</p>

<glsl>
GLSL get min/max index of vec3
Thomas
# GLSL get min/max index of vec3

(Asked by: username_0 on 2023-08-25)

I have written a function in GLSL that returns the min index (index 0 is the x component, 1 is the y component, and 2 is the z component) of a vec3 variable.

```
uint getMinIndex(vec3 vector)
{
    float minValue = min(min(vector.x, vector.y), vector.z);
    if(vector.x == minValue)
        return 0;
    if(vector.y == minValue)
        return 1;
    return 2;
}

```

As you can see, this function causes branching and slows down the whole shader.... Is there already such a function in GLSL? Or is there a better way to do this without branching?

**Tags:** glsl


---

## 2 answers

### Answer by username_1 on 2023-08-26. Score: 2 | Accepted answer

No, but the way this is written has a min of 3 branch's and max of 4. It would be better off with the plain old (x<y)&&(x<z) return 0, y<z return 1, return 2.

You could also do a pure logic op approach:

```
int mx = (y<z)&&(y<x);
int mz = (((z<y) && (z<x))*2;
return mx + mz; // both are false if x is min value and sum is zero

```

which would turn into this:

```
uint MinIndex( float x, float y, float z )
{
   return ((y<z)&&(y<x)) + ((((z<y)&&(z<x))*2);
}

```

If y,z could be equal and less then x then an extra `+ ((y==z)&&(x<y))` would be needed which would return 1.

There may be some clever way to reduce this down to less operations but it's not popping into my head... at any rate logic operations are often fast but ugly to look at.

You might also try the mix function, something along the lines of...

```
uint MinIndex(float x, float y, float z)
{
   float YltX = float(y < x);
   float ZltX = float(z < x);

   return uint(mix(YltX, 2.0 * ZltX, ZltX+float(y==z)));
}

```

I haven't checked this one for accuracy but using mix also tends to be rather speedy.

> **Comments:**
> **username_0**: Wow that's very creative =)  

---

### Answer by username_2 on 2024-01-14. Score: 1

Here is another approach that handles the case where multiple components may be the minimum/maximum and you want to handle that. You calculate a "mask" that indicates whether the component is a min/max.

```
bvec3 mask = lessThanEqual(vector.xyz, min(vector.yzx, vector.zxy); // makes a "one-hot" bool vector, where the min component(s) is true and the others are false.

```

To use it, multiply your operation by the mask, e.g.

```
vec3f colorMask = greaterThanEqual(color.rgb, min(color.gbr, color.brg));
vec3f maxColor = color * vec3f(colorMask);

```

You can also convert the vector to a scalar, like so:

```
uint index = dot(ivec3(mask), ivec3(0, 1, 2));

```

But that fails if multiple components are minimum/maximum.


---

