I have a problem with opengl lighting, I have an object let say this one.
It's an original object without applying light effect, So the problem is when I try to add light to this object it hides the object colors and turn the object into this color
diffuse and specular component I used :
GLfloat diffu[] = {0.5f, 0.5f, 0.5f, 1.0f};
GLfloat spec[] = {0.5f, 0.5f, 0.5f, 0.5f};
GLfloat shinnes [] = {50};
glLightfv(GL_LIGHT1, GL_DIFFUSE, diffu);
glLightfv(GL_LIGHT1, GL_SPECULAR, spec);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS,shinnes);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT1);
So I need to understand what's the problem is ???
From this (http://www.glprogramming.com/red/chapter05.html) link:
Define Material Properties for the Objects in the Scene
An object's material properties determine how it reflects light and
therefore what material it seems to be made of. Because the
interaction between an object's material surface and incident light is
complex, specifying material properties so that an object has a
certain desired appearance is an art. You can specify a material's
ambient, diffuse, and specular colors and how shiny it is. In this
example, only these last two material properties - the specular
material color and shininess - are explicitly specified (with the
glMaterialfv() calls). (See "Defining Material Properties" for a
description and examples of all the material-property parameters.)
As soon as you start using lighting, the objects material properties (its color) are specified by the specular/diffuse... properties passed in by glMaterialfv(). So if you where using glColor() you now need to specify the material properties with glMaterialfv().
In your code, as well as setting the light specular and diffuse colour, you need to set the material specular and diffuse colour:
// Set light properties
GLfloat diffu[] = {0.5f, 0.5f, 0.5f, 1.0f};
GLfloat spec[] = {0.5f, 0.5f, 0.5f, 0.5f};
glLightfv(GL_LIGHT1, GL_DIFFUSE, diffu);
glLightfv(GL_LIGHT1, GL_SPECULAR, spec);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT1);
// Set material properties
GLfloat shinnes [] = {50};
GLfloat matdiffu[] = {1.0f, 0.f, 0.f, 1.0f};
GLfloat matspec[] = {1.0f, 0.f, 0.f, 1.0f};
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,matdiffu);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,matspec);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS,shinnes);
// Draw object
the diffu and spec define the color of the material as well; use {0f, 1f, 0f, 1f} and {0f, 1f, 0f, 0.5f} for a pure blue color (assuming RGBA)
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuseColor);
along with GL_SHININESS, GL_SPECULAR to set the material properties of your geometry. Then the lighting will interact with the geometry material properly.
Related
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.
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.
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.
My scene is quite simple that I have two spheres placed close to each other. I have one point light in the scene and set the position of it to be inside of one of the two spheres. However the other sphere can still get the light from that point light. What I want is the light is occluded by the sphere.
My context is the followings:
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc( GL_LEQUAL );
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_MULTISAMPLE);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_LIGHTING);
// Light's color
GLfloat ambientColor[] = { 0.3f, 0.3f, 0.3f, 1.0f };
GLfloat diffuseColor[] = { 1.0f, 0.0f, 1.0, 1.0f };
GLfloat lightPosition[] = {0, 0, 0, 1.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientColor);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseColor);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glEnable(GL_LIGHT0);
Do I miss something?
When light is blocked by an interposed object between the surface and the light, that's called a shadow. The fixed-function OpenGL lighting system doesn't do shadows. OpenGL is just a triangle renderer; it doesn't know about objects, a scene, or anything. The basic assumption with any light is that there is no occluding surface between the light and the triangle.
If you want shadows, then you're going to have to manually implement one of the various shadowing techniques.
Right now, I have more than 25 vertices that form a model. I want to interpolate color linearly between the first and last vertex. The Problem is when I write the following code
glColor3f(1.0,0.0,0.0);
vertex3f(1.0,1.0,1.0);
vertex3f(0.9,1.0,1.0);
.
.`<more vertices>;
glColor3f(0.0,0.0,1.0);
vertex3f(0.0,0.0,0.0);
All the vertices except that last one are red. Now I am wondering if there is a way to interpolate color across these vertices without me having to manually interpolate color (instead natively, like how opengl does it automatically) at each vertex since, I will be having a lot more number of colors at various vertices. Any help would be extremely appreciated.
Thank you!
OpenGL will interpolate colors of pixels between one vertex and the next, but I don't know of any way to get it to automatically interpolate the values for intermediate vertexes. Normally, that's not particularly difficult though -- you don't want to write code for each individual vertex anyway, so adding the computation is pretty trivial:
class pointf {
GLfloat x, y, z;
};
std::vector<pointf> spots;
// ...
GLfloat start_blue = 1.0f;
GLfloat end_blue = 0.0f;
GLfloat start_green = 0.0f;
GLfloat end_green = 0.0f;
GLfloat start_red = 0.0f;
GLfloat end_red = 1.0f;
GLfloat size = spots.size();
glBegin(GL_POLYGON);
for (int i=0; i<spots.size(); i++) {
GLfloat red = start_red + (end_red-start_red) * i/size;
GLfloat green = start_green + (end_green-start_green) * i/size;
GLfloat blue = start_blue + (end_blue-start_blue) * i/size;
glColor3f(red, green, blue);
glVertex3f(spots[i].x, spots[i].y, spots[i].z);
}
glEnd();
One thing though: this does purely linear interpolation per vertex. It does not, for example, attempt to take into account the distance between one vertex and the next. I'd guess questions of how to do things like this are (at least part of) why OpenGL doesn't attempt this on its own.
Edit: for a gradient across a hemisphere, I'd try something like this:
// Blue light on the left
GLfloat blue[] = {0.0f, 0.0f, 1.0f, 1.0f};
GLfloat blue_pos[] = {-1.0f, 0.0f, -0.3f, 0.0f};
// red light on the right
GLfloat red[] = {1.0f, 0.0f, 0.0f, 1.0f};
GLfloat red_pos[] = {1.0f, 0.0f, -0.3f, 0.0f};
// turn on lighting:
glEnable(GL_LIGHTING);
glShadeModel(GL_SMOOTH);
// Set up the two lights:
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, blue);
glLightfv(GL_LIGHT0, GL_POSITION, blue_pos);
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, red);
glLightfv(GL_LIGHT1, GL_POSITION, red_pos);
// set up the material for our sphere (light neutral gray):
GLfloat sph_mat[] = {0.8f, 0.8f, 0.8f, 1.0f};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, sph_mat);
// Draw a sphere:
GLUquadric *q = gluNewQuadric();
gluQuadricOrientation(q, GLU_OUTSIDE);
gluQuadricDrawStyle(q, GLU_FILL);
gluQuadricNormals(q, GLU_SMOOTH);
gluSphere(q, 1.0, 64, 64);
For the moment, I've done the outside of a sphere, but doing a hemisphere isn't drastically different.
OpenGL will interpolate color within polygons, but not across polygons.