Skip to content

Instantly share code, notes, and snippets.

@shole
Created October 8, 2019 13:18
Show Gist options
  • Save shole/8deb7cb79d0b014de4c08836bbf0a89c to your computer and use it in GitHub Desktop.
Save shole/8deb7cb79d0b014de4c08836bbf0a89c to your computer and use it in GitHub Desktop.
shader branchless conditionals
/*
Branchless shader logic made sane with macros;
usage;
if (depth>pointdepth){
col=tex2D(_CameraColorTextureP,o.uv);
}else{
col=tex2D(_MainTex,o.uv);
}
col=_IF(_GT(depth,pointdepth),
tex2D(_CameraColorTextureP,o.uv),
tex2D(_MainTex,o.uv)
);
or more complex;
if ( depth>pointdepth && depth!=1 ){
col=tex2D(_CameraColorTextureP,o.uv);
}else{
col=tex2D(_MainTex,o.uv);
}
col=_IF( _AND( _GT(depth,pointdepth), _NEQ(depth,1) ),
tex2D(_CameraColorTextureP,o.uv),
tex2D(_MainTex,o.uv)
);
*/
#define _IF(x,a,b) lerp(b,a,x)
/*
Originally from:
http://theorangeduck.com/page/avoiding-shader-conditionals
Avoiding Shader Conditionals
Created on March 29, 2013, 2:09 p.m.
Having conditionals in shaders can often have a serious performance impact on the code.
Compilers can sometimes find clever ways to optimize them away, but if your shader code
really does have to branch and perform comparisons the speed can drop off significantly.
To avoid these situations I designed a number of functions which allow you to do things
often done using conditionals. They perform some comparison and then return 1.0 on true
and 0.0 on false. This can be useful, for example, if you want to add a number to another
number, but only when some condition is true.
if (x == 0) {
y += 5;
}
This can be transformed to the following.
y += 5 * when_eq(x, 0)
It doesn't cover all cases but most of the time some clever thinking can transform the
comparison into this kind of operation. The full set of functions are defined here:
*/
// ----- removed functions
/*
These are defined in GLSL, and used on the vec4 types. Using vec4 the comparison is done
component-wise, which means you can do four comparisons at once! Similar logic can also be
used for any other shading language or vector/float type. The logic behind the functions
is fairly simple, and underlies the actual maths behind comparison which computers use.
This is exactly the kind of transformation a smart compiler would do to optimize
conditionals away from your code naturally.
As a bonus here are a set of logical operators you can use together with
the outputs from these comparisons.
*/
// ----- removed functions
/*
Macro versions;
*/
// ----- Comparators
#define _EQ(x,y) (1.0 - abs(sign(x - y)))
#define _NEQ(x,y) abs(sign(x - y))
#define _GT(x,y) max(sign(x - y), 0.0)
#define _LT(x,y) max(sign(y - x), 0.0)
#define _GE(x,y) (1.0 - _LT(x, y))
#define _LE(x,y) (1.0 - _GT(x, y))
// ----- Logic
#define _AND(a,b) (a*b)
#define _OR(a,b) min(a + b, 1.0)
#define _XOR(a,b) ((a + b) % 2.0)
#define _NOT(a) (1.0 - a)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment