Lighting issues in OpenGL - opengl

I have a triangle mesh that has no texture, but a set color (sort of blue) and alpha (0.7f). This mesh is run time generated and the normals are correct. I find that with lighting on, the color of my object changes as it moves around the level. Also, the lighting doesn't look right. When I draw this object, this is the code:
glEnable( GL_COLOR_MATERIAL );
float matColor[] = { cur->GetRed(), cur->GetGreen(), cur->GetBlue(), cur->GetAlpha() };
float white[] = { 0.3f, 0.3f, 0.3f, 1.0f };
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matColor);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
Another odd thing I noticed is that the lighting fails, when I disable GL_FRONT_AND_BACK and use just GL_FRONT or GL_BACK.
Here is my lighting setup (done once at beginning of renderer):
m_lightAmbient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
m_lightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
m_lightPosition[] = { 0.0f, 1200.0f, 0.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, m_lightAmbient);
glLightfv(GL_LIGHT0, GL_SPECULAR, m_lightSpecular);
glLightfv(GL_LIGHT0, GL_POSITION, m_lightPosition);
EDIT: I've done a lot to make the normals "more" correct (since I am generating the surface myself), but the objects color still changes depending where it is. Why is this? Does openGL have some special environment blending I don't know about?
EDIT: Turns out the color changing was because a previous texture was on the texture stack, and even though it wasn't being drawn, glMaterialfv was blending with it.

If your lighting fails when GL_FRONT_AND_BACK is disabled it's possible that your normals are flipped.

Could you post the code that initializes OpenGL? You're saying that all other meshes are drawn perfectly? Are you rendering them simultanously?

#response to stusmith:
Z-testing won't help you with transparent triangles, you'll need per-triangle alpha sorting too. If you have an object that at any time could have overlapping triangles facing the camera (a concave object) you must draw the farthest triangles first to ensure blending is performed correctly, since Z-testing doesn't take transparency into account.
Consider these two overlapping (and transparent) triangles and think about what happens when that little overlapped region is drawn, with or without Z-testing. You'll probably reach the conclusion that the drawing order does, in fact, matter. Transparency sucks :P
/\ /\
/ \ / \
/ \/ \
/ /\ \
/_____/__\_____\
I'm not convinced that this is your problem, but alpha sorting is something you need to take into account when dealing with partly transparent objects.

Turns out the color changing was because a previous texture was on the texture stack, and even though it wasn't being drawn, glMaterialfv was blending with it.

If your triangles are alpha-blended, won't you have to sort your faces by z-order from the camera? Otherwise you could be rendering a face at the back of the object on top of a face at the front.

#sebastion:
multiple draw calls, each object gets a glDrawArrays. some are textured, some colored, all with normals. gl init code is:
glMatrixMode(GL_MODELVIEW);
// Vertices!
glEnableClientState(GL_VERTEX_ARRAY);
// Depth func
glEnable(GL_DEPTH_TEST);
glDepthFunc( GL_LESS );
// Enable alpha blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Lighting
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, m_lightAmbient);
glLightfv(GL_LIGHT0, GL_SPECULAR, m_lightSpecular);
glLightfv(GL_LIGHT0, GL_POSITION, m_lightPosition);
// Culling
glDisable( GL_CULL_FACE );
// Smooth Shading
glShadeModel(GL_SMOOTH);
m_glSetupDone = true;
after this i have some camera set up, but thats completely standard, projection mode, frustum, modelview, look at, translate.

Are you sure your normals are normalized?
If not and you are specifying normals via glNormal calls, you could try to let OpenGL do the normalization for you, keep in mind that this should be avoided, but you can test it out:
glEnable(GL_NORMALIZE);
This way you are telling OpenGL to rescale all the normal vectors supplied via glNormal.

I had a transparency issue on my terrain display, slopes would seem transparent when looked from a certain angle. It only happened when lighting was enabled in the shader. Turns out that I had not turned on depth testing, and from a certain angle the terrain was overwritten by other terrain and displaying semi-transparent.
TLDR; check if you have depth testing enabled, having it off may give transparency-like effects when lighting is involved.
https://learnopengl.com/Advanced-OpenGL/Depth-testing

Related

Minimum openGL initializations

I am trying to learn OpenGL and currently trying to use it with Qt. The thing I am trying to do is to load frames from a video file into a texture and then display it on the screen. The only thing I might try and do later is to enable zoom functionality on this. Keeping that in mind, what is the minimum OpenGL initializations that I need to use to maximize performance. More specifically, do I need to diasable certain features, so that I can maximize performance for my very limited needs at the moment.
For example, the Qt tutorial on OpenGL initializes it as:
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_MULTISAMPLE);
static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
I think I should safely be able to disable most of these but am not sure as I am still trying to figure out what most of these things will actually do.
glEnable(GL_DEPTH_TEST);
Enables depth testing which prevents triangles from overwriting others when they should be hidden behind others. Leave enabled to avoid the artifacts.
glEnable(GL_CULL_FACE);
Prevents triangles from being drawn when they are facing away from you. Leave enabled for better performance.
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
All these are part of the deprecated fixed function pipeline and can be removed and emulated with shaders.
If you're just starting to learn, here's additional info:
glEnable(GL_DEPTH_TEST)
Leave it only if you're planning to draw 3D shapes
glEnable(GL_CULL_FACE)
Remove it until you get used to the concept of clockwise, and counter-clockwise importance of drawing the points. otherwise you might fail to see your first rendered shapes, because they could be culled. First draw them without this, then enable it and experiment with clockwise and counter-clockwise drawing.
glShadeModel(GL_SMOOTH)
Leave that. It simply instructs the renderer to mix different colors and smooth them along the shapes. If you put different colors to different points, they'll get interpolated smoothly.
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_MULTISAMPLE);
static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
If you're past the point of rendering simple shapes, use these to experiment with lighting. You should also provide normals to your geometry, in order to see the effects. If you're really in the beginning, comment those out until you're more familiar with drawing shapes.
Good luck!

Drawing a primitive ( GL_QUADS ) on top of a 2D texture - no quad rendered, texture colour changed

I am trying to draw a 2D scene with a texture as background and then ( as the program flows and does computations ) draw different primitives on the "canvas". As a test case I wanted to draw a blue quad on the background image.
I have looked at several resources and SO questions to try get the information I need to accomplish the task ( e.g. this tutorial for first primitive rendering, SOIL "example" for texture loading ).
My understanding was that the texture will be drawn on Z=0, and quad as well. Quad would thus "cover" a portion of texture - be drawn on it, which is what I want. Instead the result of my display function is my initial texture in black/blue colour, and not my texture ( in original colour ) with a blue quad drawn on it. This is the display function code :
void display (void) {
glClearColor (0.0,0.0,0.0,1.0);
glClear (GL_COLOR_BUFFER_BIT);
// background render
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, 1024.0, 512.0, 0.0, 0.0, 1.f); // window size is 1024x512
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, texture );
glBegin (GL_QUADS);
glTexCoord2d(0.0,0.0); glVertex2d(0.0,0.0);
glTexCoord2d(1.0,0.0); glVertex2d(1024.0,0.0);
glTexCoord2d(1.0,1.0); glVertex2d(1024.0,512.0);
glTexCoord2d(0.0,1.0); glVertex2d(0.0,512.0);
glEnd(); // here I get the texture properly displayed in window
glDisable(GL_TEXTURE_2D);
// foreground render
glLoadIdentity();
gluPerspective (60, (GLfloat)winWidth / (GLfloat)winHeight, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glColor3f(0.0, 0.0, 1.0);
glBegin (GL_QUADS);
glVertex2d(400.0,100.0);
glVertex2d(400.0,500.0);
glVertex2d(700.0,100.0);
glVertex2d(700.0,500.0);
glEnd(); // now instead of a rendered blue quad I get my texture coloured in blue
glutSwapBuffers(); }
I have already tried with many modifications, but since I am just beginning with OpenGL and don't yet understand a lot of it, my attempts failed. For example, I tried with pushing and popping matrices before and after drawing the quad, clearing the depth buffer, changing parameters in gluPerspective etc.
How do I have to modify my code so it will render the quad properly on top of the background texture image of my 2D scene ? Being a beginner, extra explanations of the modifications ( as well as mistakes in the present code ) and principles in general will be greatly appreciated.
EDIT - after answer by Reto Koradi :
I have tried to follow the instructions, and the modified code now looks like :
// foreground render
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glOrtho(0.0f, 1024.0, 512.0, 0.0, 0.0, 1.f);
glColor3f(0.0, 0.0, 1.0);
glBegin (GL_QUADS); // same from here on
Now I can see the blue "quad", but it is not displayed properly, it looks something like this .
Beside that, the whole scene is flashing really quickly.
What do I have to change in my code so that quad will get displayed properly and screen won't be flashing ?
You are setting up a perspective transformation before rendering the blue quad:
glLoadIdentity();
gluPerspective (60, (GLfloat)winWidth / (GLfloat)winHeight, 1.0, 100.0);
The way gluPerspective() is defined, it sets up a transformation that looks from the origin down the negative z-axis, with the near and far values specifying the distance range that will be visible. With this transformation, z-values from -1.0 to -100.0 will be visible. Which does not include your quad at z = 0.0.
If you want to draw your quad in 2D coordinate space, the easiest solution is to not use gluPerspective() at all. Just use a glOrtho() type transformation like you did for your initial drawing.
If you want perspective, you will need a GL_MODELVIEW transformation as well. You can start with a translation in the negative z-direction, within a range of 1.0 to 100.0. You may have to adjust your coordinates for the different coordinate system as well, or use additional transformations that also translate in xy-direction, and possibly scale.
The code also has the coordinates in the wrong order for drawing the blue quad. You either have to change the draw call to GL_TRIANGLE_STRIP (recommended because it at least gets you one step closer to using features that are not deprecated), or swap the order of the last two vertices:
glBegin (GL_QUADS);
glVertex2d(400.0,100.0);
glVertex2d(400.0,500.0);
glVertex2d(700.0,500.0);
glVertex2d(700.0,100.0);
glEnd(GL_QUADS);

Multiple Light Sources with GL

I am trying to do something basic with GL. However I got a problem with the lights. I have a cube in the viewport and when I put GL_LIGHT0 at some point, it shades the cube without any problem. But GL_LIGHT1 does not act normally. When I disable light0 and put GL_LIGHT1 at the same location of light0, it just gives a different color to the shape. No shading, no lighting.
What is the problem here?
The default values for GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR with GL_LIGHT0 is (1,1,1), while it is (0,0,0) for GL_LIGHT1 to GL_LIGHT6.
If you set these values using glLight*, you should see consistent behaviour.

creating street lights in opengl

I am trying to create street lights in my environment box in opengl using c++. I need to create spot lights for this, I have written the code below but it does not work as a spot light. What am I doing wrong, or do you have any other solution for my problem?
GLfloat ambientLight[] = {0.7f, 0.2f, 0.2f, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);
GLfloat directedLight[] = {0.7f, 0.7f, 0.7f, 1.0f};
GLfloat directedLightPos[] = {-10.0f, 15.0f, 20.0f, 0.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, directedLight);
glLightfv(GL_LIGHT0, GL_POSITION, directedLightPos);
Thanks.
If this is all of your light code you are missing some important lines. You only define ambient/diffuse light colors and a light position.
You need to enable lighting with: glEnable(GL_LIGHTING)
You need to enable the light you are using: eg: glEnable(GL_LIGHT0)
I am not sure but i think you also need to define a material (glMaterial).
You need to define the direction of your light: glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction);
Two other notes:
Make sure your normal vectors are set correct or you won't see a result
If i remember correctly fixed function lighting only works for vertices and not for pixels. So if you have a light source above a single quad you won't see any light spot.
Please note that in "new" opengl (core 3.+) there is no "lighting" support. All of those enums and functions are deprecated.
So you may want to look for some other solutions:
modern opengl tutorial
opengl book
Also it is worth saying that those "old" lighting functions were very ease to use and they have a lot of didactic advantages.

OpenGL lighting with glOrtho

So I have a 3D object that I'm drawing with the following light:
GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 0.9}; /* White light. */
GLfloat light_position[] = {300.0, 300.0, 300.0, 0.0};
glShadeModel(GL_SMOOTH);
glEnable(GL_COLOR_MATERIAL);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
My object is illuminated as I expect when I draw it in a "normal" context (i.e. no glOrtho).
However, I'm working on the orthogonal projections of the object and use glOrtho for that purpose (on the ModelView matrix). I initialize the light after the glOrtho call, then draw the object in the exact same way as I did in the case that worked (the 3D case). But for some reason, the lighting does not work on the orthogonal projections, i.e. once I did the glOrtho call.
This is not a problem with normals since it works in the 3D case. I'm guessing that with the glOrtho call, everything gets pressed together on a thin layer, which explains why the light doesn't behave as expected... but honestly, I have not experience with lighting so this might be wrong.
Anyone knows what's going on?
Lighting happens in eye space, i.e. before the projection is applied at all. You probably use the transformations matrices in a wrong way. glOrtho, glFrustung or gluPerspective go into GL_PROJECTION matrix, gluLookAt and other camera placement stuff go into GL_MODELVIEW.