• Create Account

## best way to do branching logic in shaders?

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

5 replies to this topic

### #1timothyjlaird  Members

598
Like
0Likes
Like

Posted 22 February 2014 - 02:06 PM

I am using WebGL...OpenGL ES2. This is my vertex shader. Question...

When I have branching in my shader like turning a 'directional light' or 'ambient light' on/off (in my case) by passing an argument to the shader (1.0 to turn it on or 0.0 to turn it off) am I better off using IF/THEN or math? What is the performance hit (if any) when using IF statements in a shader verus handling it with math? Like this...

var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec4 a_Color;\n' +
'attribute vec4 a_Normal;\n' +
'uniform mat4 u_ProjMatrix;\n' +
'uniform mat4 u_ViewMatrix;\n' +
'uniform mat4 u_ModelMatrix;\n' +
'uniform mat4 u_NormalMatrix;\n' +
'uniform vec3 u_DirectionalLightColor;\n' +
'uniform vec3 u_AmbientLightColor;\n' +
'uniform vec3 u_DirectionalLightDirection;\n' +
'uniform vec3 u_GlobalColor;\n' +
'uniform float u_UseGlobalColor;\n' +
'uniform float u_UseDirectionalLight;\n' +
'uniform float u_UseAmbientLight;\n' +
'varying vec4 v_Color;\n' +
'void main() {\n' +
'	gl_Position = u_ProjMatrix * u_ViewMatrix * u_ModelMatrix * a_Position;\n' +
'	vec3 normal = normalize(vec3(u_NormalMatrix * a_Normal));\n' +
'	float nDotL = max(dot(u_DirectionalLightDirection, normal), 0.0);\n' +
'	vec3 colorToUse = u_GlobalColor + (vec3(a_Color) * u_UseGlobalColor) + (-u_GlobalColor * u_UseGlobalColor);\n' +
'	vec3 diffuse = colorToUse + (u_DirectionalLightColor * nDotL * colorToUse * u_UseDirectionalLight) + (-colorToUse * u_UseDirectionalLight);\n' +
'	vec3 ambient = u_UseAmbientLight * u_AmbientLightColor * colorToUse;\n' +
'	v_Color = vec4(diffuse + ambient, a_Color.a);\n' +
'}\n';


The end result is that setting u_UseAmbientLight or u_UseDirectionalLight to 1.0 turns them on...setting them to 0.0 turns them off.

Am I needlessly making my code harder to read or would there be an increase in performance by doing it this way (as opposed to an IF/THEN)?

### #2C0lumbo  Members

4064
Like
0Likes
Like

Posted 22 February 2014 - 02:17 PM

As your conditionals are based on uniforms (i.e. they're not per vertex/per pixel), I believe* you're better off just using if statements. All your fragments will take the same path so the cost of the conditional will be very cheap, and the driver may even decide to eliminate the branch altogether by creating a separate shader program for you.

* although as with all things like this YMMV, and you should probably measure to be sure.

### #3Martins Mozeiko  Members

1428
Like
0Likes
Like

Posted 22 February 2014 - 03:50 PM

Modern OpenGL implementations compile following :

if (cond) { x = A; } else { x = B; }

to something like this:

x = cond * A + (1 - cond) * B;

(actually they have much better opcodes to express this kind of code to hardware)

So I would recommend you to use actual if conditionals - GLSL compiler in some cases could optimize code much better than you manually introducing additional multiply operations.

### #4TheChubu  Members

8950
Like
0Likes
Like

Posted 22 February 2014 - 04:08 PM

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

### #5timothyjlaird  Members

598
Like
0Likes
Like

Posted 22 February 2014 - 04:50 PM

Thanks for the information everyone! Will make the code a lot more readable.

### #6kalle_h  Members

2402
Like
0Likes
Like

Posted 23 February 2014 - 07:14 AM

Just premultiply light color with that intensity toggle at CPU.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.