I’ve been recently playing a little bit with GLSL/Core Image shaders. One of the earliest limitations I ran into was the fact that you cannot have conditional results. In other word, if you do an if/else test, the output of your shader cannot depend on it. (Not entirely sure why you’d want to use if/else at all, then…)
That’s rather annoying. Thankfully, that’s a solved problem. Many CPUs prefer non-branching code, too, and there’s a long history of creating non-branching version of code that technically should branch. The trick here is “creative” use of math and/or bit-logic functions. As a simple example, let’s say I have a threshold shader - values below the minimum value should have a brightness of 0, and values higher than the max value should have a brightness of 1.
step() function to the rescue: step(a,b) returns 0 if a < b, 1 if a > b. So to cut off the low range, we have
Very similarly, to check against the max value, we force brightness to be greater than 1 for pixels above the maximum threshold and then clamp to 1.0
brightness = brightness + step( high, brightness );
brightness = min( 1.0, brightness );
That’s all there is to it. And in case you actually came for the filter code, here it is - with input sanitizing, nicer input values (midpoint/range), grayscale conversion, all the fun stuff.
kernel vec4 threshold(sampler image, float midPoint, float range )
{
vec4 pixel=unpremultiply( sample(image, samplerCoord(image)) );
float high = midPoint + range * 0.5;
float low = midPoint - range * 0.5;
high = min(1.0, high);
low = max(0.0, low);
float brightness = 0.3 * pixel.x + 0.59 * pixel.y+ 0.11 *pixel.z;
brightness = step( low, brightness ) * brightness;
brightness = brightness + step( high, brightness );
brightness = min( 1.0, brightness );
pixel.x = pixel.y =pixel.z = brightness;
return premultiply(pixel);
}
You can also use the ternary operator directly :
pixel.a = someValue > 4.5 ? 1.0 : 0.5; pixel.a = someValue > 4.5 ? (someValue > 6.0 ? 1.0 : 0.7) : 0.5;
Good luck with your shaders ! I’ve found the Apple Documentation to be quite lacking, I’m still looking for a list of all available functions.