I'm trying to setup lighting in my scene
but for some reason it doesn't work, i'm trying to figure out why
here's how I initialize OpenGL:
glClearColor(0.0, 0.0, 0.0, 0.0);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_NORMALIZE);
glEnable(GL_LIGHT0);
and here is how I try to draw with lighting on:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
GLfloat diffuse0[]={1.0, 1.0, 1.0, 1.0};
GLfloat ambient0[]={1.0, 1.0, 1.0, 1.0};
GLfloat specular0[]={1.0, 1.0, 1.0, 1.0};
GLfloat light0_pos[]={1.0, 1.0, 1,0, 1.0};
glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular0);
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 2.0);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 1.0);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 2.0);
object->draw();
the object is not affected by the lighting at all
all normals are set and all the information that opengl require for lighting a scene
is there... what am I missing?
EDIT:
OK! I finally found a solution to the problem.
my opengl init function was misplaced in the code
I had to call it after showing the window and not before
and that's what caused the problem...
Probably you should tell us the position of the object.
Suspect 1: The position of the object and the light are too far
Suspect 2: Hide all ATTENUATION settings or make LINEARATTENUATION to 0.0
Related
I can't change any object color when lighting is enabled.
This is my init function (the part of the light and material):
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
GLfloat light_ambient[] = {0.5, 0.5, 0.5, 1.0};
GLfloat light_diffuse[] = {0.0, 0.5, 0.5, 1.0};
GLfloat light_specular[] = {0.0, 0.0, 0.5, 1.0};
GLfloat light_position[]={0, -1.0, 0, 0.0};
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
Each object has a vector of colors. This is how I draw my objects:
float mat_a[] = {0.0, 0.0, 0.0, 1.0};
float mat_d[] = {0.0, 0.0, 0.0, 1.0};
float mat_s[] = {0.0, 0.0, 0.0, 1.0};
...
colors_vect = some_object->getColor();
glDisable(GL_COLOR_MATERIAL);
mat_a[0] = colors_vect.at(0);
mat_a[1] = colors_vect.at(1);
mat_a[2] = colors_vect.at(2);
mat_d[0] = colors_vect.at(3); //The values are correct.
mat_d[1] = colors_vect.at(4);
mat_d[2] = colors_vect.at(5);
mat_s[0] = colors_vect.at(6);
mat_s[1] = colors_vect.at(7);
mat_s[2] = colors_vect.at(8);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_a);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_d);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_s);
glEnable(GL_COLOR_MATERIAL);
glBegin(GL_POLYGON);
...
This code doesn't work. I tried to give the mat some random values and still nothing changes.
What am I doing wrong? Any help would be appreciated!
Your problem is caused by this line:
glEnable(GL_COLOR_MATERIAL);
This enables functionality that allows material properties to track the current color, which is the color set with regular glColor() calls. If this is enabled, glColorMaterial() controls which parts of the material parameters track the current color. The default is GL_AMBIENT_AND_DIFFUSE, which means that the current color is used for the ambient and diffuse material parameters.
You need to make a choice about how you want to update your material properties:
If you need to change colors very frequently, it can be most efficient to enable GL_COLOR_MATERIAL, and use glColor() to update the material properties.
You can use glColorMaterialfv(), which gives you more control, and e.g. allows you to set different colors for ambient and diffuse. For this approach, you need to keep GL_COLOR_MATERIAL disabled.
You used a mix of these two, where you set the material properties with glColorMaterialfv(), but then also enabled GL_COLOR_MATERIAL. This means that the ambient and diffuse material properties you set are not used. Instead the current color is used for those two properties. These properties would then change any time you call glColor(). If you never call glColor(), they would use the default value for the current color, which is white (1.0, 1.0, 1.0, 1.0).
Why the shadows are gone from unlighted faces of my cube shape when I am using arrays of:
vertices[]
indices[]
colors[]
normals[]
texcoords[]
// and draw them by
glDrawElements();
But when I use:
glBegin(...);
glVertex3f(...);
glEnd(...);
The shadows are ok.
Here you got an image of what is happening:
My light is set as below:
glShadeModel (GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
GLfloat AmbientLight[] = {0.0, 0.0, 0,0, 1.0};
GLfloat DiffuseLight[] = {1.0, 1.0, 1,0, 1.0};
GLfloat SpecularLight[] = {1.0, 1.0, 1.0, 1.0};
GLfloat Shininess[] = { 90.0 };
GLfloat Emission[] = {0.0, 0.0, 0.0, 1.0};
glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularLight);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, AmbientLight);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, DiffuseLight);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, SpecularLight);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, Shininess);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Emission);
You are probably missing a call to
glEnableClientState( GL_NORMAL_ARRAY );
The lighting doesn't work, the object appears with solid color. The color itself changes with the material or lighting parameters but no shadow or anything just solid grey.
Here's part of the code:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glFrontFace(GL_CCW);
glShadeModel(GL_FLAT);
glEnable(GL_LIGHTING);
GLfloat amb[] = {0.6, 0.6, 0.6, 1.0};
GLfloat dif[] = {0.8, 0.8, 0.8, 1.0};
GLfloat spec[] = {0.5, 0.5, 0.5, 1.0};
GLfloat pos[] = {0.0, 0.0, 30.0};
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
glLightfv(GL_LIGHT0, GL_SPECULAR, spec);
glLightfv(GL_LIGHT0, GL_POSITION, pos);
GLfloat co[4]={0.5, 0.5, 0.5, 0.5};
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 1.0 };
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, co);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
for(int i=0; i < numofTr; i++)
{
glBegin(GL_TRIANGLES);
glNormal3f(tr[i].v1->n.x, tr[i].v1->n.y, tr[i].v1->n.z);
glVertex3f(tr[i].v1->x, tr[i].v1->y, tr[i].v1->z);
glNormal3f(tr[i].v2->n.x, tr[i].v2->n.y, tr[i].v2->n.z);
glVertex3f(tr[i].v2->x, tr[i].v2->y, tr[i].v2->z);
glNormal3f(tr[i].v3->n.x, tr[i].v3->n.y, tr[i].v3->n.z);
glVertex3f(tr[i].v3->x, tr[i].v3->y, tr[i].v3->z);
glEnd();
}
I don't know what I'm missing, the normals look good when displayed along with the object.
You are using dim light on a gray object. Obviously the result is gray.
If you mean that faces are flat shaded, that's because of glShadeModel(GL_FLAT);. Change it to GL_SMOOTH to enable interpolation.
If the object is in 3D, I think that the fact you are only passing 3 floats as position might be relevant; default value is [0,0,1,0], and the function expects four floats (4th being the W coordinate, which should in most cases be equal to 1, or 0 for lights in infinite distance).
Also double check that the data you give to glVertex and glNormal is correct. When rendering a sphere at 0,0,0, the normal of every vertex is the normalized position of such vertex (only holds for spheres, obviously).
As a side note, this code is obviously outdated, and as a disclaimer I would ditch it alltoghether, if you are only learning, and switch to something that's relatively modern and uses programmable pipeline.
I'm using the marching cubes algorithm described here http://paulbourke.net/geometry/polygonise/ to turn a scalar field into a triangle mesh, and then displaying the mesh using OpenGL's GL_TRIANGLES mode. However, I'm having trouble with the lighting.
It seems like half the triangles are not being lit at all, and it's occurring in a distinct pattern.
In the program depicted below I've set the background to red, the front face color to green, and the back face color to blue. There is one light source with position (1.0, 1.0, 1.0, 0.0) and a sphere included for reference.
http://i.imgur.com/JutXhbb.png
And here it is with the triangles flipped, as in the drawing order of the last two vertices are switched:
http://i.imgur.com/iUgqm3N.png (back face color is blue)
Whats really confusing me is why the flipped version has color everywhere whereas the normal version doesn't. I figured that even if I drew stuff wrong, at least the flipped version should reflect the same error. Any idea what's happening?
Here is the complete lighting initialization code:
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
GLfloat mat_color1[] = { 0.0, 0.0, 1.0, 1.0 };
GLfloat mat_color2[] = { 0.0, 1.0, 0.0, 1.0 };
glMaterialfv(GL_BACK, GL_DIFFUSE, mat_color1);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_color2);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glMaterialfv(GL_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_BACK, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
Using OpenGL I am trying to render a simple line between the points p1 and p2, but it doesnt work.
However, I am able to render cubes at these positions.
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
GLfloat mat_ambient[] = {0.0, 0.0, 1.0, 1.0};
GLfloat mat_flash[] = {0.0, 0.0, 1.0, 1.0};
GLfloat mat_flash_shiny[] = {50.0};
GLfloat light_position[] = {100.0,-200.0,200.0,0.0};
GLfloat ambi[] = {0.1, 0.1, 0.1, 0.1};
GLfloat lightZeroColor[] = {0.9, 0.9, 0.9, 0.1};
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambi);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(p1.x, p1.y, p1.z);
glutSolidCube(20);
glLoadIdentity();
glTranslatef(p2.x, p2.y, p2.z);
glutSolidCube(20);
glDisable( GL_LIGHTING );
glDisable( GL_DEPTH_TEST );
I am using the following code for rendering the line. But I cant find the problem why it doesnt get rendered:
glDisable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glLoadIdentity();
glColor3f(1,0,0);
glLineWidth(10.0);
glBegin(GL_LINES); //doesnt work with GL_LINE either
glVertex3f(p1.x, p1.y, p1.z);
glVertex3f(p2.x, p2.y, p2.z);
glEnd();
I assume what happens is that the lines are actually rendered, but there's still a vertex normal set, pointing away from the light source, or being 0. Easy fix: Disable lighting when drawing lines.
While it is possible to "illuminate" lines, the whole operation makes no sense if one assumes the "regular" normal based illumination models. Lines don't have a normal direction, they have a normal plane (or in other words, a line it it's tangent itself).
So the proper way to illuminate a line is by tangent based shading. Fixed function OpenGL can't do it, but it is trivial to implement with a shader.
A couple of suggestions for you, w.r.t your second code snippet:
1) You probably don't need the 'glEnable(GL_COLOR_MATERIAL)', try commenting out that line.
2) You're passing int's to glColor3f(). Try using glColor3f(1.0f, 0.0f, 0.0f); instead.
Also, did you check the line drawing without the cube at the same position? (ie., is it being occluded or not)