3
\$\begingroup\$

I'm having a problem when using ambient lights in my opengl game.

When I first started with my program, i had a positioned light, and the code was this:

GLfloat AmbientColor[] = {1.0f,1.0f,1.0f,1.0f};
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT,AmbientColor);
    ////////POSITIONED LIGHT
    GLfloat LightColor0[] = {0.9f,0.9f,0.7f,1.0f};
    GLfloat LightPos0[] = {0.0f,900.0f,1000.0f,1.0f};
    glLightfv(GL_LIGHT0,GL_DIFFUSE,LightColor0);
    glLightfv(GL_LIGHT0,GL_POSITION,LightPos0);

When doing this, I had a well lit area with no problem.

Once I changed my matrix to GL_MODELVIEW, I noticed that my lights were not equal on each face.

I changed my code to look like this:

GLfloat AmbientColor[] = {1.0f,1.0f,1.0f,1.0f};
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT,AmbientColor);
    ////////POSITIONED LIGHT
    GLfloat LightColor0[] = {0.9f,0.9f,0.7f,1.0f};
    glLightfv(GL_LIGHT0,GL_AMBIENT,AmbientColor);

Once I used this code, only the mountains in my terrain were lit up, and anything perfectly flat was not lit at all(completely black...)

So my question is - How would I use my ambient light correctly?

Example code would be nice, thanks.

\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

I'm assuming you've already done: glEnable(GL_LIGHTING); glEnable(GL_LIGHT0);

After you set up your modelview matrix (a popular example is gluLookAt()), then you should call glLightfv(GL_LIGHTi, AmbientColor). You need to do this every frame, not once. The position you give is transformed by the modelview matrix and stored. Thus, if your modelview matrix changes (which it typically changes every frame), then you need to call glLightfv(GL_LIGHTi, GL_POSITION, ...) again.

Getting black patches that depend on your camera angle is a sign that the angle between the camera and the light is taking part in the lighting. If you are truly do just ambient lighting, it should NOT - that is a factor of DIFFUSE lighting. Check your diffuse color on the light/material. If you ARE use diffuse color, check the glLightfv() call (as above), make sure your projection matrix is correctly initialized, and finally, that your vertex normals make sense. Remember, scaling in the modelview (e.g. glScalef()) scales the normals as well. For a simple solution, you can try enabling autonormalization by glEnable(GL_NORMALIZE) - but generally this is frowned upon because it is usually unnecessary (see GL_RESCALE_NORMAL).

The fixed function light model is a long equation to say the least. What effect are you trying to achieve by ambient lighting? It is generally used to give a low default amount of light to a scene, and that is done with a global ambient factor. A simplified (no spot lights, specular, attenuation) equation is:

Color = Global.ambient*Material.ambient + LightFactor[0] + LightFactor[1] ... + Material.emissive

where LightFactor[i] = Light.ambient*Material.ambient + Light.diffuse*Material.diffuse*dot(Light.DirVector, Vertex.Normal)

If we apply that your example, you get:

Color = 1.0*Material.ambient + 1.0*Material.ambient + Light.diffuse*Material.diffuse*dot(Light.DirVector, Vertex.Normal)

This sums the material's ambient color twice, which almost definitely not what you want.

If you just want to apply a small uniform amount of light to everything, then set your global ambient to a small factor like {0.2, 0.2, 0.2, 1.0}, your light's ambient to {0.0, 0.0, 0.0, 0.0}, and your material's ambient to {1.0, 1.0, 1.0, 1.0}. Thus if a shape is entirely outside of a light, it gets a minimum of {0.2, 0.2, 0.2, 0.2} color (dull gray).

OpenGL fixed-function lighting confusing at first, but stick with it.

Edit: or go on to shaders.

\$\endgroup\$
2
\$\begingroup\$

I'm not really understanding what you've done. You say "change my matrix," and I assume "glMatrixMode(SOME_MATRIX)." But the current matrix mode will not have any affect on anything you do until you make some GL call that changes the "current" matrix.

So it sounds to me like somewhere you changed the current matrix and then things started going awry. So I would check for calls to glFoo() made between that call (where you change the matrix mode) and where you draw your model, where glFoo() is a method that affects the current matrix.

That said, no matrix should affect ambient light, assuming the "fixed pipeline" functionality of OpenGL (this assumes you're not writing your own shaders; in other words, that you're using the built-in functionality of OpenGL that has existed for many years).

As I understand it, in the "fixed pipeline" mode (which uses "Phong Shading"), a light has a given ambient contribution, and any material has an attribute that affects how much ambient light it receives. The result is that every fragment ("potential" pixel) in an affected primitive is drawn with the same ambient lighting. In fact, if the only lighting that was enabled was ambient, you'd be drawing primitives that had a uniform color (and intensity).

You said in your original question that one of your problems is that lights are not equal on each face. This implies that either (1) the difference in lighting is not an effect of ambient light (since any primitive drawn with the same light and material will have identical ambient lighting) or (2) that the faces have different light models or different material models (or perhaps (3) you're writing your own shaders and doing something odd).

To recap, I don't think changing any matrix has anything to do with your lighting problems unless you're making a glFoo() call that would cause a primitive to effectively be oriented differently toward a particular light, in which case the problem should have nothing to do with ambient light (and may have something to do with one of the other "types" of lighting).

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .