Lighting observation when moving to Core profile.

Hi everyone. I’ve ported my rendering engine from a fixed function pipeline to the Core (OpenGL 3.2>) profile. My engine now has 2 code paths - legacy and modern. The performance increase is nice (from 570fps (legacy) to 730fps (modern) on my test scene), and the codepaths are nicely abstracted away from the client code. Yay!!!

However, I’ve noticed a striking difference in lighting quality. I’ve used the fixed function lighting equations in the past, and have never been impressed by them. I’ve had fireballs lighting a hallway and such, and the quality was ‘meh’. You can see the lighting effects in action, but they were nothing spectacular. I figured that was normal and never gave it a second thought.

After transitioning the code path to use shader based lighting, I am genuinely suprised at how much better lighting appears in my test scene. Even the most simple shading technique (Lambert colour = max(L.n, 0)*diffuse) gives a greatly superior contrast between surfaces facing the light and surfaces facing away from the light. Eg. my test scene has a cylinder in the world, and as the light rotates around the scene, you can clearly tell where the light position is based on cylinder shading. With the fixed function pipeline, I have a general idea of light position, but you couldn’t tell if the light was behind and to slightly to the left, or behind and slightly to the right (obviously, for other light positions you could roughly estimate the position). For shader based lighting, the cylinder clearly shows which triangles are not facing the light. The contrast between shader based lighting and fixed function lighting is striking.

Typically, when I encounter weird behavior like this, my first instinct is to question my methods. I am obviously missing a configuration parameter in the fixed function pipeline which is causing my lights to not appear as “vivid” as when doing the math myself. I’ve gone through the RedBook with a comb, looked at tutorials on the net, and cannot see anything which I might have missed. My shader based lighting codepath is using the Redbook lighting equations, so I should be doing the exact same thing as fixed function. I’m using the same data sets. I must stress that lighting with fixed function pipeline works, you can clearly see the triangle shading as the light moves around the scene. However, with shader based lighting (also per vertex), the contrast between shaded and unshaded areas is really vivid.

Both codepaths use the same light/material properties. For the FF codepath, I also need to toggle the following (which are different from the default settings).
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, {0,0,0,1});

Has anyone encountered anything similar with fixed function lighting? Is there something I might have missed? Again, I must stress that lighting works with FF codepath, it just isn’t as vivid.

Try glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

“Color Material” settings ( glColorMaterial(…, GL_AMBIENT_AND_DIFFUSE)/glEnable(GL_COLOR_MATERIAL) ) can also make a huge difference. Be aware that these settings will be ignored when a vertex shader is active.

Also be aware that the FF defines clamping values to [0…1] at various stages. Additonally, be sure to use glMaterialfv() to fill in the various Material attributes (emissive and ambient attributes can quickly make everything look washed out). Light attenuation is also something to not forget about! Try to disable attenuation (set constant att. factor to 1 and all others to 0) and see, how the FF lighting looks.

Last but not least, you should read about “gamma correct” rendering, which when properly done can also enhance the crispness of lighting shades.

I think I’ve actually tried all the light/material functions/combinations specified in the RedBook, including GL_LIGHT_MODEL_LOCAL_VIEWER. Thanks for the suggestion, but no dice.

“Color Material” settings ( glColorMaterial(…, GL_AMBIENT_AND_DIFFUSE)/glEnable(GL_COLOR_MATERIAL) ) can also make a huge difference. Be aware that these settings will be ignored when a vertex shader is active.

Color material allows glColor to override glMaterialfv(mat) settings. I’ve got it disabled. As I’ve already pointed out, I’ve already tried various combinations, including enabling color material and linking it to ambient and diffuse. Again, thanks for the suggestion, but no dice. Both pipelines are using the exact same material properties.

Light attenuation is also something to not forget about! Try to disable attenuation (set constant att. factor to 1 and all others to 0) and see, how the FF lighting looks.
.
Again, no dice. My default attenuation values match default OpenGL. My FF light does work, but the edges look too washed out.

Last but not least, you should read about “gamma correct” rendering, which when properly done can also enhance the crispness of lighting shades.

This sounds interesting, and can actually explain the washed out colours I seem to be getting. However, I’ve checked the RedBook, but cannot find a way to alter gamma settings. It might very well be a 0.3/0.59/0.11 issue, but for the life of me I cannot figure out a way to fix it.

Thanks again for a prompt (and informative reply). As I’ve already mentioned, lighting does work, just the the colours are not as vivid, ie. non lit areas appear softer, washed out. The cylinder test scene when using shaders has a nice contrast between lit and unlit areas, while FF has it washed out.

My fixed function code path will be deprecated once Apple move their butt and actually support OpenGL 3.2+, so I’m not too stressed about the visual quality at this point in time. This is the only reason why I’m still keeping the fixed function code path (that, and OpenGL ES1.1, but I was planning on deprecating that codepath in 12 months anyway).

On gamma-correct(ed) rendering see here:
http://filmicgames.com/archives/category/gamma

It was a true eye-opener for me :slight_smile:

The cylinder test scene when using shaders has a nice contrast between lit and unlit areas, while FF has it washed out.

We’d be much more likely to diagnose what’s happening here if you posted images of these.

Roger. I’ll do just that the first chance I get, but probably wont happen until the weekend since I’ve got a 3 month old baby in the house who is requesting all my free time :slight_smile:

Edit: I’ve just looked at the link skynet posted (http://filmicgames.com/archives/299), and the images there explain exactly what is going on. THIS is what I’m experiencing. The picture http://filmicgames.com/Images/GammaIntro/800/page0030.jpg shows what I’m talking about. It looks as if nVidia driver adjusts gamma in fixed function pipeline, while my shader based code doesn’t (it’s in linear space).

Well linear/gamma switched on or off by the driver alone is quite unlikely.

You missed a very important clue IMHO :

Also be aware that the FF defines clamping values to [0…1] at various stages.

That plus per-vertex lighting (instead of per-pixel) are the biggest motivators to use GLSL instead of fixed function lighting.

But as said alfonse, unless you show your ff and glsl pics, there is not much to be sure.
And your code, too.

Hi,

What about separate specular color?
If you apply textures to your geometry, then without separate specular color the specular highlights get clamped to 1.0 before the texture is applied, while if you enable separate specular color then the issue is nonexistent.
Most probably you did not have this issue with your shader based implementation because there the varyings do not get clamped to 1.0.

skynet mentioned most of the things I’d suggest. But one thing that fixed-function GL doesn’t do that some shader lighting implementations I’ve seen do do is prevent distance anti-attenuation. That is, don’t let distance attenuation parameters “amplify” the brightness of the light source.

GL says do this:

atten = 1.0 / ( constant + linear * d + quadratic * d * d );

but for better results, you probably want to clamp this term to 0…1 to prevent amplification.

But yeah, we probably need some pics and code to be able to help you. We’re just taking pot shots now.

Has anyone encountered anything similar with fixed function lighting?

No. When I first did this, it matched up almost exactly. Just to reempasize one thing skynet threw out: make sure you have 0…1 color clamps on your color varyings. And you’re of course using an RGB8 or RGBA8 render target, right?

The performance increase is nice (from 570fps (legacy) to 730fps (modern) on my test scene)

Until you get the same resulting output, assume you are comparing apples and oranges. And even then, fps isn’t that meaningful for comparison. Converting to something useful (ms/frame), we get 1.75 ms and 1.37 ms, which suggests perhaps 20% faster (depending on the accuracy of your timers).