0
$\begingroup$

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?

$\endgroup$

1 Answer 1

1
$\begingroup$

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.

$\endgroup$
1
  • $\begingroup$ Wow that's very creative =) $\endgroup$
    – Thomas
    Aug 26 at 18:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.