OpenGL best way to do branching logic in shaders?

This topic is 1793 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

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)?

Share on other sites

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.

Share on other sites

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.

Share on other sites

I would recommend reading the shader from a text file also :D

Share on other sites

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

Share on other sites

Just premultiply light color with that intensity toggle at CPU.

• What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 28
• 16
• 10
• 10
• 11
• Forum Statistics

• Total Topics
634111
• Total Posts
3015575
×