can't see lighting in openGL - opengl

I'm new to openGL and I drew a cube, then I place a camera inside the cube.
What I'm trying to achieve now is lighting the cube.
This is how I tried:
void draw(GLFWwindow* window)
{
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
// Create light components
GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8, 1.0f };
GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat position[] = { -1.5f, 1.0f, -1.0f, 1.0f };
// Assign created components to GL_LIGHT0
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
glLightfv(GL_LIGHT0, GL_POSITION, position);
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 projection = glm::perspective(PI / 4, 1.f / 1.f, 1.0f, 10.0f);
glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, -1.3f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 model = glm::rotate(glm::mat4(1.f), PI, glm::vec3(0.0f, 1.0f, 0.0f));
....
....
}
But I don't see any lightings

But I don't see any lightings
Welcome to the world of the old-and-busted fixed function pipeline. You're using OpenGL as it was done 20 years ago. The mode of illumination you're using is doing the lighting calculations only at the vertex locations and then simply blends the resulting color over the triangles (or quads). Obviously that won't work if there's a lot of change in illumination over the span of a single triangle.
In your case the light source is very close to your cube, so that's not going to work. You should address this by ditching the fixed function pipeline (FFP) and use shaders. Seriously, the FFP has been out of fashion for some 13 years (first GLSL capable GPUs arrived on the market in 2003). FFP has been emulated with shaders created in-situ ever since.
Also (judging from your other questions related to drawing a cube) you don't supply face normals. Normals are essential to doing illumination calculations, so you'll have to supply those as well.

Related

Specular lighting not working [duplicate]

This question already has an answer here:
No spot of light on cube
(1 answer)
Closed 5 years ago.
I created a 3D scene where I added a light source and a 3D box, which should be illuminated by the light source. Both Ambient and Diffuse colors seem to work properly, but the specular color does not seem to be calculated correctly. When moving the camera in front of the side with the light source, no specular 'dot' can be seen. But when i move the camera towards the top of the cube and look at the origin (0, 0, 0), a faint specular 'dot' can be seen on the illuminated side of the cube.
My question is the following: what am I doing wrong?
Everything in the code below happens in the modelMatrix, and the _nav member manages the camera movement.
Here's the code:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(_nav->getCamPosx(), _nav->getCamPosy(), _nav->getCamPosz(),
_nav->getCamViewx(), _nav->getCamViewy(), _nav->getCamViewz(),
_nav->getCamUpx(), _nav->getCamUpy(), _nav->getCamUpz());
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
GLfloat qaAmbientLight[] = {0.2f, 0.2f, 0.2f, 1.0f};
GLfloat qaDiffuseLight[] = {0.8f, 0.8f, 0.8f, 1.0f};
GLfloat qaSpecularLight[] = {1.0f, 0.0f, 0.0f, 1.0f}; //red for testing
glLightfv(GL_LIGHT0, GL_AMBIENT, qaAmbientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, qaDiffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, qaSpecularLight);
// Set the light position
GLfloat qaLightPosition[] = {0.5f, 0.5f, 1.2f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, qaLightPosition);
GLfloat cyan[] = {0.f, .8f, .8f, 1.f};
GLfloat white[] = {0.8f, 0.8f, 0.8f, 1.0f};
//GLfloat dark[] = {0.0, 0.0, 0.0, 1.0};
glMaterialfv(GL_FRONT, GL_AMBIENT, cyan);
glMaterialfv(GL_FRONT, GL_DIFFUSE, cyan);
glMaterialfv(GL_FRONT, GL_SPECULAR, white);
GLfloat shininess[] = {80};
glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
glBegin(GL_QUADS);
glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f(0.1f, 0.0f, 0.1f);
glVertex3f(1.0f, 0.0f, 0.1f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.1f, 0.0f, 1.0f);
glNormal3f(0.0f, 0.0f, -1.0f);
glVertex3f(0.1f, 0.0f, 0.1f);
glVertex3f(1.0f, 0.0f, 0.1f);
glVertex3f(1.0f, 1.0f, 0.1f);
glVertex3f(0.1f, 1.0f, 0.1f);
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(0.1f, 0.0f, 0.1f);
glVertex3f(0.1f, 0.0f, 1.0f);
glVertex3f(0.1f, 1.0f, 1.0f);
glVertex3f(0.1f, 1.0f, 0.1f);
//face that gets illuminated
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.1f, 0.0f, 1.0f);
glVertex3f(0.1f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glNormal3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.1f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.1f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.1f, 1.0f, 0.1f);
glVertex3f(1.0f, 1.0f, 0.1f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.1f, 1.0f, 1.0f);
glEnd();
Facing cube side with light source:
Top view of the cube, the faint red is the specular 'dot':
In fixed function OpenGL illumination is calculated only at the vertices and the resulting colour then interpolated across the faces. For specular reflexes to show up then you need sufficiently many vertices so that there's actually enough spatial sampling.
Obviously it's not very efficient to subdivide meshes, just to provide enough sampling points for illumination purposes. So over the years a number of per-pixel-illumination techniques were developed. It's pretty straightforward to implement using shaders ( https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php ).

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.

Invisible Terrain

I am using GL_TRIANGLE_STRIP to draw my terrain to the screen, however when I compile and run the program I get nothing. When I change GL_TRIANGLE_STRIP to GL_LINES it shows up and works. What can I do to get it working with GL_TRIANGLE_STRIP?
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -10.0f);
glRotatef(30.0f, 1.0f, 0.0f, 0.0f);
glRotatef(-_angle, 0.0f, 1.0f, 0.0f);
GLfloat ambientColor[] = {.5, .5, .5, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
float scale = 5.0f / max(63.0,63.0);
glScalef(scale, scale*10, scale);
glTranslatef(-(float)(63.0) / 2, 0.0f, -(float)(63.0) / 2);
/*GLfloat lightColor0[] = {0.6f, 0.6f, 0.6f, 1.0f};
GLfloat lightPos0[] = {-0.5f, 4, 32, 0.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);*/
glColor3f(0.3f, 0.9f, 0.0f);
for(int x = 0;x<64;x++){
glBegin(GL_LINES);
for(int z = 0;z<63;z++){
glNormal3f(0,1,0);
Vertex(x,map[x][z],z);
Vertex(x,map[x][z+1],z+1);
}
glEnd();
}
for(int z = 0;z<64;z++){
glBegin(GL_LINES);
for(int x = 0;x<63;x++){
Vertex(x,map[x][z],z);
Vertex(x+1,map[x+1][z],z);
}
glEnd();
}
I'm not sure this is important but for my terrain I have code that makes it a 3d Gaussian distribution.
An explanation of TRIANGLE_STRIP is found by a Google search. There is an illustration on Wikipedia.
My advice is to print out the first five vertices of your vertex data, and draw it by hand on paper. The fact that GL_LINES work suggest that the right vertices are there, you might just drawing them in the wrong order.
Another piece of advice is to disable backface culling.
glDisable(GL_CULL_FACE);
As a random stab in the dark, do you have culling turned on? It may be that it's not drawing any triangles because the back of the triangles are invisible. Try adding:
glDisable(GL_CULL_FACE);
To you init code, or simply removing:
glEnable(GL_CULL_FACE);
From your init code.

Can I use fixed glEnable(GL_LIGHTING) alongside fragment/vertex shaders?

I have browsed many online articles and adding lighting seems very straight forward but I'm not able to get a result. I'm using OpenGL 3.0 and I use a vertex and fragment shaders for my animating model. Btw, I'm new to OpenGL.
Disregarding the lighting I have everything working fine with the 3D char running around the environment.
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
*snip*
glEnable(GL_LIGHTING);
glEnable (GL_LIGHT0);
float ambientLight0[] = { 0.2f, 0.2f, 0.2f, 1.0f };
float diffuseLight0[] = { 0.8f, 0.8f, 0.8f, 1.0f };
float specularLight0[] = { 0.5f, 0.5f, 0.5f, 1.0f };
float position0[] = { -2.5f, 1.0f, -1.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight0);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight0);
glLightfv(GL_LIGHT0, GL_POSITION, position0);
//glEnable(GL_COLOR_MATERIAL);
//float mcolor[] = { 1.0f, 0.0f, 0.0f, 1.0f };
//glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mcolor);
m_Beast.onRender();
Here's how m_Beast.onRender() looks:
glPushMatrix();
Vector3 pos = getPosition();
glTranslatef(pos.x, pos.y, pos.z);
glBindTexture(GL_TEXTURE_2D, m_beastTextureID);
static float modelviewMatrix[16];
static float projectionMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, modelviewMatrix);
glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);
m_shaderProgram->bindShader();
m_shaderProgram->sendUniform4x4("modelview_matrix", modelviewMatrix);
m_shaderProgram->sendUniform4x4("projection_matrix", projectionMatrix);
m_shaderProgram->sendUniformTexture("texture0", 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
glVertexAttribPointer((GLint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, m_texCoordBuffer);
glVertexAttribPointer((GLint)1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, m_interpolatedFrame.vertices.size());
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
glPopMatrix();
I just want a quick way to get some directional lighting on my model. I'm really not interesting in writing a lighting shader at this point.
As soon as you use vertex shaders, you must implement the lighting calculations yourself. In older OpenGL one could still use the fixed function vertex pipeline and program only the fragment stage. But with OpenGL-3 and onwards you're required to do it all.
However you shouldn't feel too bad about this. In the end you'll write less, because the huge plethora of function calls required to configure fixed function, can be replaced by much shorter and concise shader code.

Problem with light and depth in OpenGL

glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
ifstream myFile("Coordinates.txt");
if (!myFile.is_open())
{
cout << "Unable to open file";
exit(1); // terminate with error
}
// Light values and coordinates
float ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };
float diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };
float specular[] = { 1.0f, 1.0f, 1.0f, 1.0f};
float lightPos[] = { 0.0f, -150.0f, -150.0f, 1.0f };
glEnable(GL_CULL_FACE); // Do not calculate inside of jet
glFrontFace(GL_CCW); // Co unter clock-wise polygons face
// Enable lighting
glEnable(GL_LIGHTING);
// Setup and enable light 0
glLightfv(GL_LIGHT0,GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);
// Light values and coordinates
float specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
// Enable color tracking
glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// All materials hereafter have full specular reflectivity
// with a high shine
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,specref);
glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,128);
while (! myFile.eof())
{
glPushMatrix();
myFile>>plot[0];
myFile>>plot[1];
myFile>>plot[2];
myFile>>plot[3]; //this data will not be used
glColor3f(0.60f/1.5,0.80f/1.5,0.90f/1.5);
glTranslatef((plot[0]-1.15)*26, (plot[2]-0.51)*45, (plot[1]-1)*30);
glutSolidSphere(2, 12, 12);
glLoadIdentity();
glPopMatrix();
axes += 0.00005f;
}
glRotatef(axes, 0.0f, 1.0f, 0.0f);
myFile.close();
glFlush();
glutSwapBuffers();
This is my 1st time playing with lighting.
My problem is that after i place all the light effect code from a tutorial the objects seem only exist in one plane which is the xy-plane thought my data have coordinated in all xyz and the reflection seems a bit off..
can anyone tell me why and how to fix it?
Have a look-see here: Avoiding 16 Common OpenGL Pitfalls
You haven't given enough information. What values are in your file? Why are you loading plot[3] when it goes unused? Do you mean that the glutSphere is rendering as a flat 2d object in the xy plane?
I'd recommend you familiarise yourself with the core OpenGL functionality before using the in-built lighting, this problem probably has nothing to do with lighting. I also wouldn't recommend using GL's inbuilt lighting for any thing other than testing and tiny projects anyway... its not very flexible and has lots of limitations too.