OpenGL + GLUT Spot light - c++

I'm having a bit of trouble creating a nice spot light. So far, my lighting properties are like this :
/* Spot light */
glEnable(GL_LIGHT1);
GLfloat ambientColor[] = {0.0f, 0.0f, 0.0f, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
//Light
GLfloat lightColor0[] = {0.7f, 0.7f, 0.7f,0.0f};
GLfloat lightPos0[] = {0.0f, 3.0f, 0.8f, 0.0};
glLightfv(GL_LIGHT1, GL_SPECULAR, lightColor0);
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos0);
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 15.0);
GLfloat spot_direction[] = { 0.0, -1.0, 0.0 };
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0);
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 2.0);
I'm getting a 'spot light' of sorts... at least, its a light that sits above my scene and shines down on the objects, but its not (as far as I can tell) appearing in a conical sort of way.
This is the scene I'm trying to create
And here's what I've got so far.
I know my textures are a little buggered too, if any one could help with that as well, that'd be great!

Your solution is here
C++ Opengl - lighting using spotlight
you need the last value of the position variable to be 1.0 for the light to be a spotlight.

Related

Ghost light following main light at point of origin

I have a spotlight in my OpenGL project, the light currently shines down the -z axis like a ceiling light, towards the floor, which is just a big quad.
I currently have a cube at the origin of the light, that follows the light around, so I can see exactly where the light is at all times.
My problem is that there is another brighter spotlight that follows the main light, it starts at the origin, or the bottom left corner of the floor.
I'd like to remove this white light, as I don't know what's causing it, or how to remove it.
I have tried to play around with some of the variables and see their impact, but I've had little to no success.
Any assistance would be greatly appreciated.
The error:
//ceiling light
GLfloat Light_Ambient[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat Light_Diffuse[] = { 0.0f, 0.0f, 0.0f, 1.0f };
GLfloat Light_Position[] = { Sun.X, Sun.Y, Sun.Z, 1.0f };
GLfloat Spot_Direction[] = { 0.0f, 0.0f, -1.0f };
//ambient
GLfloat Light_Ambient1[] = { 0.4f, 0.4f, 0.4f, 1.0f };
GLfloat Light_Diffuse1[] = { 1.0f, 1.0f, 1.0f, 0.0f };
GLfloat Light_Position1[] = { Sun.X, Sun.Y, Sun.Z, 1.0f };
//ceiling light
glLightfv(GL_LIGHT0, GL_AMBIENT, Light_Ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, Light_Diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, Light_Position);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 55);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, Spot_Direction);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 5);
glEnable(GL_LIGHT0);
//ambient
glLightfv(GL_LIGHT1, GL_AMBIENT, Light_Ambient1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, Light_Diffuse1);
glLightfv(GL_LIGHT1, GL_POSITION, Light_Position1);
glEnable(GL_LIGHT1);
I changed some things around and I seem to have solved it.
//ceiling light
GLfloat Light_Ambient[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat Light_Diffuse[] = { 0.0f, 0.0f, 0.0f, 1.0f };
GLfloat Light_Position[] = { Sun.X, Sun.Y, Sun.Z, 1.0f };
GLfloat Spot_Direction[] = { 0.0f, 0.0f, -1.0f };
//ambient
GLfloat Light_Ambient1[] = { 0.6f, 0.6f, 0.6f, 1.0f };
GLfloat Light_Diffuse1[] = { 1.0f, 1.0f, 1.0f, 0.0f };
GLfloat Light_Position1[] = { 0, 0, 0, 0.0f };
//ceiling light
glLightfv(GL_LIGHT0, GL_AMBIENT, Light_Ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, Light_Diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, Light_Position);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 55);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, Spot_Direction);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 20);
glEnable(GL_LIGHT0);
//ambient
glLightfv(GL_LIGHT1, GL_AMBIENT, Light_Ambient1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, Light_Diffuse1);
glLightfv(GL_LIGHT1, GL_POSITION, Light_Position1);
glEnable(GL_LIGHT1);
UPDATE:
I'm returning to edit this months later simply because I feel that this answer may help a lot of people with OpenGL and this confusion with lights.
If your lights are broken (like mine were) there's actually a good chance there's nothing wrong with your lights at all, but how you're rendering the world. It's worthwhile to remember that opengl looks a little like this:
https://imgur.com/a/saYxy
What I was actually doing wrong, as you can see from my initial question i was convinced that the Z was the Y and the Y was the Z, and vice versa, this broke all of my lighting calculations back then. If your lights look like mine do, there's a good chance that you're confusing your axis, it isn't that hard to do this when moving from 2d to 3D opengl.

Spotlight issue OpenGL

I have a problem with spotlight in OpenGL library. A scene is black, light is unseen if the GL_SPOT_CUTOFF is less than 125. I supposed that issue concerns direction of the light source but I have tried plenty of options both for position and direction of spotlight. Here is my code:
const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glPushMatrix();
glLoadIdentity();
GLfloat spot_direction[] = { 0.0, -1.0, 0.0 ,0.0};
GLfloat spot_position[] = { 1.0,1.0,0.0,1.0 };
glLightfv(GL_LIGHT1, GL_POSITION, spot_position);
glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 60);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction);
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 100);
glPopMatrix();
glEnable(GL_LIGHT1);
Solved. Problem was with too high GL_SPOT_EXPONENT factor (light was too much focused) and with direction of the light stream.

Color changes when scaling a gluQuadric

I have a problem when I draw a scaled (with glScale) gluSphere.
The Color changes after Scaling and the darker faces are not as dark as they should be...
This is how I set up the light:
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
GLfloat LAmbient[4] = {0.2f, 0.2f, 0.2f, 1.0};
GLfloat LDiffuse[4] = {1.0f, 1.0f, 1.0f, 1.f};
GLfloat LSpecular[4] = {1.0f, 1.0f, 1.0f, 0.0f};
GLfloat LPosition[4] = {100.0f, -200.0f, -50.0f, 0.0f};
GLfloat LSpotDirec[3] = {0.0,0.0,0.0};
GLfloat LSpotCutOff = 180.0f;
GLfloat LSpotExponent = 0.0f;
GLfloat LAttenuationConst = 1.0f;
GLfloat LAttenuationLinear = 0.0f;
GLfloat LAttenuationQuadrat = 0.0f;
glLightfv(GL_LIGHT0, GL_AMBIENT, LAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, LDiffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, LSpecular);
glLightfv(GL_LIGHT0, GL_POSITION, LPosition);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, LSpotDirec);
glLightfv(GL_LIGHT0, GL_SPOT_CUTOFF, &LSpotCutOff);
glLightfv(GL_LIGHT0, GL_SPOT_EXPONENT, &LSpotExponent);
glLightfv(GL_LIGHT0, GL_CONSTANT_ATTENUATION, &LAttenuationConst);
glLightfv(GL_LIGHT0, GL_LINEAR_ATTENUATION, &LAttenuationLinear);
glLightfv(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, &LAttenuationQuadrat);
Here is my code, that sets up a new glList, where the glu Sphere is drawn:
//Sphere
GLUquadric * pSphere = gluNewQuadric();
glNewList(LIST_SPHERE, GL_COMPILE);//'LIST_SPHERE' is defined above
gluQuadricTexture(pSphere, GL_FALSE);
gluQuadricOrientation(pSphere, GLU_OUTSIDE);
gluQuadricDrawStyle(pSphere, GLU_FILL);
gluQuadricNormals(pSphere, GLU_SMOOTH);
gluQuadricCallback(pSphere, GLU_ERROR, NULL);
gluSphere(pSphere, 1.0f, 20, 10);
glEndList();
and here is the code, where the List is called:
glPushMatrix();
//drawing a white Sphere with a radius of 6
glColor3f(1.0f, 1.0f, 1.0f);
glScalef(6.f,6.f,6.f);
glCallList(LIST_SPHERE);
glPopMatrix();
Sphere drawn with 'glScalef(1.0f, 1.0f, 1.0f)' (no scale)
Sphere drawn with 'glScalef(6.0f, 6.0f, 6.0f)'
I hope you have any Idea, why things are not working probably.
The normals are not being scaled correctly (they are non-unit length after scaling).
You have two options to solve this:
GL_NORMALIZE -- This will renormalize your normals, which is costly.
GL_RESCALE_NORMAL -- This will simply rescale them.
Option #2 is what you want here, since you applied a uniform scale (6.0x in every direction). If you had applied a non-uniform scale (e.g. glScalef (1.0f, 6.0f, 3.0f)) then this would not be a valid option and you would have to resort to option #1.
In either case, all you need to do is enable GL_NORMALIZE or GL_RESCALE_NORMAL to solve this problem.

How to make the lighting in OpenGL more visually pleasant?

I need a rendering platform to show the result of my mesh processing algorithm, it's quite basic and easy, I've had it done, except that the default lighting from OpenGL is a little weird.
My rendering result is like:
And the lighting parameter in OpenGL is like:
// Lights properties
float ambientProperties[] = {0.4f, 0.4f, 0.4f, 1.0f};
float diffuseProperties[] = {0.8f, 0.8f, 0.8f, 1.0f};
float specularProperties[] = {1.0f, 1.0f, 1.0f, 1.0f};
float lightPosition[] = {0.2f, -0.3f, -0.3f, 0.0f};
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientProperties);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseProperties);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularProperties);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
// Material Properties
float MatAmbient[] = {0.3f, 0.3f, 0.3f, 1.0f};
float MatDiffuse[] = {0.7f, 0.7f, 0.7f, 1.0f};
float MatSpecular[] = {0.8f, 0.8f, 0.8, 1.0f};
float MatShininess[] = { 64 };
float MatEmission[] = {0.0f, 0.0f, 0.0f, 1.0f};
glMaterialfv(GL_FRONT, GL_AMBIENT, MatAmbient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDiffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpecular);
glMaterialfv(GL_FRONT, GL_SHININESS, MatShininess);
glMaterialfv(GL_FRONT, GL_EMISSION, MatEmission);
What I want is something like this:
hand http://iparla.inria.fr/publications/2007/BS07b/sketch_teaser.jpg
I've changed the full resolution version of mine rendering results to vertex normal and added a simplified version, to make the comparison more convincing. We can see that the latter ones are apparently more vividly lighted, ignoring the color.
Can the default OpenGL lighting be parameter-tuned like the results that I want?? Or how can I retrieve codes for some high-quality GLSL shaders for lighting?? I'm only new to graphics rendering, and I think such a lighting routines is not rare.

OpenGL alpha blending issue with back face visible

I'm trying to display "transparent" surfaces (not closed volumes) with both the front face and back face are visible (not culled).
For example displaying a cone or cylinder where the transparency is applied on both sides.
There are some visible artifacts where some part of the surface does not seems to be handling the alpha values correctly.
The issue it seems is when I (opengl) is trying to apply the alpha from the front side of the surface to the backside of the surface. (when both the inside/outside of the surface is visible).
void init()
{
glMatrixMode(GL_PROJECTION);
gluPerspective( /* field of view in degree */ 40.0,
/* aspect ratio */ 1.0,
/* Z near */ 1.0, /* Z far */ 10.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, 0.0, 5.0, /* eye is at (0,0,5) */
0.0, 0.0, 0.0, /* center is at (0,0,0) */
0.0, 1.0, 0.); /* up is in positive Y direction */
glTranslatef(0.0, 0.6, -1.0);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_diffuse);
glLightfv(GL_LIGHT2, GL_POSITION, light2_position);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
//glEnable(GL_CULL_FACE);
glFrontFace( GL_CW );
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void draw ()
{
static GLfloat amb[] = {0.4f, 0.4f, 0.4f, 0.0f};
static GLfloat dif[] = {1.0f, 1.0f, 1.0f, 0.0f};
static GLfloat back_amb[] = {0.4f, 0.4f, 0.4f, 1.0f};
static GLfloat back_dif[] = {1.0f, 1.0f, 1.0f, 1.0f};
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_LIGHT1);
glDisable(GL_LIGHT2);
amb[3] = dif[3] = 0.5f;// cos(s) / 2.0f + 0.5f;
glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
glMaterialfv(GL_FRONT, GL_DIFFUSE, dif);
glMaterialfv(GL_BACK, GL_AMBIENT, back_amb);
glMaterialfv(GL_BACK, GL_DIFFUSE, back_dif);
glPushMatrix();
glTranslatef(-0.3f, -0.3f, 0.0f);
glRotatef(angle1, 1.0f, 5.0f, 0.0f);
glutSolidCone(1.0, 1.0, 50, 2 );
glPopMatrix();
///...
SwapBuffers(wglGetCurrentDC()); // glutSwapBuffers();
}
The code is based on : http://www.sgi.com/products/software/opengl/examples/glut/examples/source/blender.c
tinyurled links to 2 images on flickr showing the issue (but from out production code, not the above code, but both have the same kind of problems):
http://flic.kr/p/99soxy and http://flic.kr/p/99pg18
Thanks.
Max.
Your problem is probably a mix of two problems.
as your depth test is enabled, and all polygons write to depth buffer, the polygons that are further away cannot contribute to the pixel color if they are drawn after the nearest polygons. You should try to disable your depth test.
alphablending is a non-commutative operation, so the order is which the triangles are drawn is important and changes the result. To have a consistent result, you'd have to draw the triangles in consistent order. In your code, this order may vary, depending on the viewpoint for instance. As your objects are convex, you could draw your object in two passes, both with culling enabled, the first pass drawing the backfacing triangles (that are the most distant to the camera), then the frontfacing triangles (that are nearest)
More generally, correct blending for arbitrary geometry is a hard problem, you may want to look at Order Independent Transparency algorithms (depth peeling, ...) if you want to go further.