Tuesday, May 5, 2015

opengl - My Ambient lighting is not working correctly


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.




Answer



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.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...