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.
Related
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!
I have created a helicopter that moves around a track, now where I'm having trouble is that we're supposed to have 2 light sources in the game, one that replicates the sun ( which i've done it wasnt too hard) and the second is a spotlight located on the actual helicopter itself. This is essentially what i have so far:
GLfloat specular2[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat position2[] = { vx, vy, vz, 1.0 };
glLightfv(GL_LIGHT2, GL_DIFFUSE, ambientLight);
glLightfv(GL_LIGHT2, GL_SPECULAR, specular2);
glLightfv(GL_LIGHT2, GL_POSITION, position2);
glLightf(GL_LIGHT2, GL_SPOT_CUTOFF, 60.0f);
glLightf(GL_LIGHT2, GL_SPOT_EXPONENT, 100.0f);
glEnable(GL_LIGHT2);
But, it doesn't do anything that I notice. I've done a great deal of research on lights and i just cant seem to figure it out. By the way ( vx,vy,vz) is the current position i want the light to be in infront of the helicopter.
The value you use for GL_SPOT_EXPONENT is very large:
glLightf(GL_LIGHT2, GL_SPOT_EXPONENT, 100.0f);
This controls how quickly the intensity drops off from the center of the cone. For example, with this value of 100.0, the intensity would be down to about 20% at angle of just 10 degrees off the cone center. You may want to try a much smaller value to see if it gives you a better result.
While the vales are not shown, this call looks suspicious just from the naming. It's using a variable named ambientLight to set the diffuse component of the light source:
glLightfv(GL_LIGHT2, GL_DIFFUSE, ambientLight);
Also, you do not specify a direction for the spot light. The default is (0.0, 0.0, -1.0). Unless there is anything in the negative z-direction from the helicopter, the spot light will not illuminate anything. You will need to specify GL_SPOT_DIRECTION if the default is not what you want.
It's also important to be aware that the current modelview transformation is applied when a light source position and direction are specified. So if your helicopter is transformed, it's easiest to specify the position/direction of the spotlight while the transformation is already set up, and before making the draw calls.
This program currently loads .obj files and has a small collision system. I also went about testing some seamless ground. Now to the issue as depicted here.
There is one spot on the "ground" that just reflects the light I have above it. I don't know if this is an issue with the light or the material loaded via the .obj file. The code for the light is:
float col[]={1.0,1.0,1.0,1.0};
float col1[]={0.3,0.3,0.3,1.0};
float col2[]={0.8,0.8,0.8,1.0};
float pos[]={0.0,10.0,0.0, 1.0};
float spotDir[] ={0.0, -1.0, 0.0};
glLightfv(GL_LIGHT0,GL_DIFFUSE,col2);
glLightfv(GL_LIGHT0, GL_AMBIENT, col1);
glLightfv(GL_LIGHT0, GL_SPECULAR, col);
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spotDir);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 90.0);
The one lit spot also moves with the camera depending which angle you look at it from. The other issue is the edges of the cube on unlit sides show what looks like tearing but I have no idea what causes it, again I think it is a lighting issue.
Any ideas on how to get rid of this?
That looks like a specular highlight. Just zero your specular color and you're done.
And that's how light works in the real world, by the way.
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.
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