Advertisement Jump to content
Sign in to follow this  
timothyjlaird

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.

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement

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 this post


Link to post
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 this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!