Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Sorry if this question has been asked in the past, but searching Google and here didn't yield relevant results, so here goes.

I'm working on a fragment shader that implements both conditional/boolean diffuse and bump mapping (that is to say, you don't need a diffuse texture or a normals texture, and if they're not present, they're simply changed to default values).

My current solution is to use a uniform float to say "mix amount". For example, computing the diffuse texel works as:

// Compute diffuse amount scaled by vCol
// If no texture is present (mDif = 0.0), then DiffuseTexel = vCol
// kT[0] is the diffuse texture
// vTex is the texture co-ordinates
// mDif is the uniform float containing the mix amount (either 0.0 or 1.0)
vec4 DiffuseTexel = vCol*mix(vec4(1.0), texture2D(kT[0], vTex), mDif);

While that works great and all, I was wondering if there's a better way of doing this, as I will never have any use for in-between values for funky effects. I know that perhaps the best solution is to simply write separate shaders for mDif=0.0 and mDif=1.0, but I'd like a more elegant solution than splicing shaders before compiling or writing multiple shader files and keeping each one updated.

Any ideas are greatly appreciated. =)

share|improve this question
    
I don't see anything wrong with this, it's probably way better than any branching, but I'm no shader expert so I'll let the professionals talk. –  Laurent Couvidou Jun 27 '13 at 22:45
    
@LaurentCouvidou: Branches will be compiled into conditional operations so should be as fast or faster than multiplying by 1 or 0... on some hardware with some drivers at some optimization levels. :) –  Sean Middleditch Jun 27 '13 at 23:50
add comment

1 Answer 1

up vote 3 down vote accepted

Branching should be sufficiently fast on modern cards that you don't need to worry about it, and you can always profile it if you think there's a bottleneck. Branching will also make for somewhat more readable code, since your intent is much clearer, and the code you're currently using does imply the possibility of a "25% mix" between the two, for example.

Your current example also causes the texture to be sampled, even if it would be the "default" value, which you could avoid with an actual branch, potentially.

But there's really nothing horrible with your current solution, and if you have a need to support cards/versions that are old enough that branching isn't very fast, it's probably better.

share|improve this answer
    
Oh, I see. I thought that branches/conditionals in general were still pretty slow. Since that isn't the case, though, I may as well write the two versions into the shader and have the one I'll use enabled with a boolean #define during compilation. Thanks a lot for this information. =) –  Ruben Nunez Jun 28 '13 at 0:02
2  
@RubenNunez: non-uniform branches are a problem but uniform ones should be fine. Uniform branches are, essentially, those that only depend on constant and uniform variables and not on per-vertex/per-fragment data. That is, all shader executions follow a uniform code flow. The slowness of branching on GPUs is that in the non-uniform case, every shader ends up executing both branches but throwing away the unused case. When it's uniform, or the branched-to code is very short/cheap, things work much better. –  Sean Middleditch Jun 28 '13 at 0:08
    
Oh, right. I remember reading something like that. I guess I must've forgotten it x_x. Thanks for the reminder, though. =D –  Ruben Nunez Jun 28 '13 at 0:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.