4
\$\begingroup\$

I have normal mapping working in my game, but I want to only use normal mapping for some surfaces, and not others.

Right now, as far as I can tell, my shader is applying an incorrect normal of (0, 0, 0) in tangent space to my non normal mapped surfaces, since no textures are bound to the sampler.

Is there a suitable way of detecting that nothing is bound to a sampler in GLSL and then using a flat normal instead? I've also found old posts around the web recommending the following:

  1. Using a dummy 1x1 texture with the color (128, 128, 255) - this will lose Phong interpolation.
  2. Switching shader programs for normal mapped and non-normal mapped surfaces - I get the feeling that I'd end up duplicating a lot of code this way, especially when I start implementing specular maps, parallax displacement maps, etc.

Are either of these still recommended or is there a new feature to query the sampler that I could make use of? Should I be doing it one way over another for performance reasons?

Here is my fragment shader:

#version 330 core

in vec2 UV;
in vec3 tangentSpaceLightDir;
out vec4 outColor;
uniform sampler2D diffuseMap, normalMap;

void main (void)
{
    vec4 texel = texture(diffuseMap, UV);
    vec4 ntexel = texture(normalMap, UV);

    // I want to use vertex normal here, if nothing is bound.
    vec3 N = normalize(ntexel.xyz * 2.0 - 1.0);

    vec3 L = normalize(tangentSpaceLightDir);

    float lambertTerm = dot(N, -L);

    vec4 finalColor = vec4(0.0);
    if (lambertTerm > 0.0)
    {
         finalColor += vec4(lambertTerm, 1.0);
    }

    outColor = finalColor * texel;
}
\$\endgroup\$
9
\$\begingroup\$

You already know what you have to do, I'll just summarize it. There are three ways to solve your problem:

  • Go ahead and make a conditional like you're saying, either by sampling the texture or by creating a separate uniform for this purpose. As you probably know, adding branching on a shader is almost never a good idea, and much less so in the fragment shader: You usually don't want to do this

  • Add a uniform float that determines whether or not you use normals. Set it to 0 to disable and to 1 to enable. After calculating the normals, multiply the result by this value. If you set it to 0, the result will be 0. However, the program won't be faster when you want to disable normals. You would usually prefer this approach

  • But, if you can afford to switch shaders, I really recommend you do so. The shader will be a bit faster when normals are disabled. If you're worried about duplicating code, you can make your shader be procedurally generated, by assembling different parts, and creating different sets of shaders for each different necessity you have. Having lots of shaders, even hundreds of different shaders is not uncommon in modern games. If possible, you may want to do this

\$\endgroup\$
  • 1
    \$\begingroup\$ Yeah, I had a couple of ideas, but my knowledge is actually several years out of date so I guess I really wanted to know what the 'recommended' option is. Passing in a uniform and using that as a multiplier (your 2nd suggestion) didn't cross my mind, I'll probably do that. \$\endgroup\$ – usm Nov 19 '14 at 0:15
  • \$\begingroup\$ Why is branching not a good idea? I assumed it was a performance issue due to an instruction pipeline on the GPU, but if you could clarify, that would be great. \$\endgroup\$ – hexafraction Nov 19 '14 at 11:17
  • \$\begingroup\$ You could simply pass in a flat normal texture and keep the same shader code for all the objects. No need for another uniform or branching. \$\endgroup\$ – sharvey Nov 19 '14 at 20:28
  • \$\begingroup\$ @hexafraction: This question discusses the topic in greater detail. \$\endgroup\$ – Panda Pajama Nov 20 '14 at 6:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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