In my code, I cannot set cordinate the lighting according to the object so I cannot with fixed my lighting on the object which moves. How can i move the light with the objects
I have an objet that is in the 0,0,-15 position and When I press the up down right left buttons , this object moving with the light which is lamb object. Yet, although I put the light(lamb object) 0,0,-15 position and give move_x and move_z cordinates as a position of light , the light is appeared in the different place and it is moving unlinked with my object. this is my code :
glTranslatef(move_x,0,move_y);
float l0_pos_temp[] = {move_x ,-3, move_y ,1} ;
glLightfv( GL_LIGHT0, GL_POSITION, l0_pos_temp ) ;
glTranslatef(0,-3,0);
Light();
glPopMatrix();
An important thing to note, is that glLightfv() is affected by the current state of the modelview matrix. That is
calling glTranslatef(move_x,0,move_y), before setting the light position will translate the light by (move_x,0,move_y).
Perhaps you want:
glTranslatef(move_x,0,move_y);
float l0_pos_temp[] = {0.0f, -3.0f, -15.0f, 1.0f};
glLightfv( GL_LIGHT0, GL_POSITION, l0_pos_temp );
glPopMatrix();
Related
I need to draw an object with triangles and a sphere. My object has its own material properties that I define them with glMaterialfv. Sphere is just a sphere with a color. However, some part of my object(it is one of its polygons) is colored with sphere's color. How can I solve this problem?
my object function
void drawObject()
{glDisable(GL_COLOR_MATERIAL);
for(int i=0;i<j;i++)
{ glBegin(GL_TRIANGLES);
glNormal3f(..);
glVertex3f(..);
glNormal3f(..);
glVertex3f(..);
glNormal3f(..);
glVertex3f(..);
GLfloat ambientValues[]={..};
GLfloat specularValues[]={..};
GLfloat diffuseValuse[]={..};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,ambientValues);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,diffuseValues);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,specularValues);
glEnd();
}
}
Two mistakes here: Materials muse be set before the drawing operation. And glMaterialfv is not valid within a glBegin/glEnd block. BTW, you shouldn't use immediate mode (glBegin/glEnd) in the first place. Its use has been discouraged for well over 15 years now.
I draw a glutSolidCube and a glutSolidTeapot on the screen.
Whenever I activate glEnable(GL_CULL_FACE) I get different results for each object. I can either get the cube to be shown properly (glCullFace(GL_BACK)), or the teapot (glCullFace(GL_FRONT)), but never both of them.
If I disable culling, then both of them are shown properly, but I would like to be able to activate it.
Other objects defined by me are not being shown properly either.
Since these objets are defined in GLUT I can guess it's not a problem of their normals, or is it?
I show an image of the effect:
Light definition:
void setLighting(void) {
//setMaterial();
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
//ambient light color variables
GLfloat alr = 0.0;
GLfloat alg = 0.0;
GLfloat alb = 0.0;
//diffuse light color variables
GLfloat dlr = 1.0;
GLfloat dlg = 1.0;
GLfloat dlb = 1.0;
//specular light color variables
GLfloat slr = 1.0;
GLfloat slg = 1.0;
GLfloat slb = 1.0;
//light position variables
GLfloat lx = 0.0;
GLfloat ly = 100.0;
GLfloat lz = 100.0;
GLfloat lw = 0.0;
GLfloat DiffuseLight[] = {dlr, dlg, dlb}; //set DiffuseLight[] to the specified values
GLfloat AmbientLight[] = {alr, alg, alb}; //set AmbientLight[] to the specified values
GLfloat SpecularLight[] = {slr, slg, slb}; //set AmbientLight[] to the specified values
GLfloat LightPosition[] = {lx, ly, lz, lw}; //set the LightPosition to the specified values
GLfloat global_ambient[] = { 0.1f, 0.1f, 0.1f, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glEnable(GL_LIGHTING);
glLightfv (GL_LIGHT0, GL_DIFFUSE, DiffuseLight); //change the light accordingly
glLightfv (GL_LIGHT0, GL_AMBIENT, AmbientLight); //change the light accordingly
glLightfv (GL_LIGHT0, GL_SPECULAR, SpecularLight); //change the light accordingly
glLightfv (GL_LIGHT0, GL_POSITION, LightPosition); //change the light accordingly
}
Depth test and culling enabling:
glEnable(GL_DEPTH_TEST); // Enable the depth buffer
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Ask for nicest perspective correction
glEnable(GL_CULL_FACE); // Cull back facing polygons
glCullFace(GL_BACK);
Your depth buffering looks bad.
Do you,
ask for a depth buffer of adequate resolution? (something like 32 bits)
pass in GL_DEPTH_BUFFER_BIT to gl_clear
tried making the distance between your near and far clipping planes to get better resolution?
I know the part you posted about your defined object vs the glut teapot, but the glut teapot is for sure has a CCW vertex winding, so the fact that it doesn't show up when you turn on culling makes me think depth buffer.
Simple face culling is based on the order of the vertices - whether they end up clockwise in screen space or anti-clockwise. So, the problem could be in the definition order of the vertices, or you might be applying some kind of transform, which flips the order (eg. negative scaling). The normals only play a role in lighting.
This statement seems odd:
Whenever I activate glEnable(GL_CULL_FACE) I get different results for each object. I can either get the cube to be shown properly (glCullFace(GL_BACK)), or the teapot (glCullFace(GL_FRONT)), but never both of them.
There are two possible explanations for this:
Either your GLUT is buggy, or you've (accidently?) swapped the Z axis (for example by using all negative distances for near and far clipping plane).
You switched the front face winding direction (call to glFrontFace)
Other objects defined by me are not being shown properly either.
The front face is determined by screen space vertex winding. The vertices order on screen in either clockwise or counterclockwise. By default OpenGL assumes faces which are drawn with their vertices in counterclockwise order as front face. Normals are not took into account for this.
I think the easiest way for you to fix this is by swapping the order in which you submit the vertices.
I think the GLUT teapot only renders correctly without CULL_FACE enabled, which would indicate that the normals that are generated don't correspond to the vertex order. The visual effect of this is that the teapot seems to rotate in the opposite direction as other objects. This is the well-known effect of rotating a hollow mask. The brain tries to make sense of the scene taking its cues from the lighting. If I invert the space by a glScalef(-1,-1,-1) before drawing, it looks like a normal teapot, even when culling.
Also note the teapot is not a closed surface, and that culling allows you to see through it along the gap around the lid.
If you want to combine 'cullable' objects next to this uncullable teapot, you can switch off culling just when rendering the teapot.
OMG, I have been working for the last days on this and just find that solution.
Obviously!, you have to set :
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE); // Don't waste energy trying the glCullFace(GL_BACK);
// thing since its set at GL_BACK by default.
// Yes, it does cuts triangle NOT facing you.
Also, make sure your camera is not at crazy distances like 0.0000001f to 1 Billions.
Then, I didnt find it anywhere except into an obscur tutorial, but you have to set you depthframebuffer (yep, another 5 lines right there).
Shuve these 5 lines anywhere after you generate a framebuffername ( glGenFramebuffers(1, &FramebufferName);) and before your display/loop and that WILL do the trick. I tried it before the FramebufferName generation and it didnt work. But before or after textures generation and it still does work.
// The depth buffer
GLuint depthrenderbuffer = 0;
glGenRenderbuffers(1, &depthrenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, windowWidth, windowHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer);
This openGL really did drive me crazy with years and I still cant find a complete higher c++ library that englobes every opengl calls. But im building one right now and if anyone is interrested, I might publish it one of these days.
For the lighting portion of an OpenGL project I'm doing this part for my team at the moment:
Define material properties for the models in Part 1. Make your material definitions easily
replaceable. Specifically, robot components and the remote control unit should be "shiny";
rubble piles should be defuse if various color shades; main platform tiles should be diffuse
gray. Select your own material properties and properly document them for the blocks, bases, factories, etc.
I've only been trying to apply the "shiny" effect on the control unit and it hasn't worked well. I tried putting in some sample lighting since we haven't put in any yet (or at least it's not in the repository) to test it out. The result is that the cube portions of the controller reflected (though way too white, no matter what I tried, the color of the cubes is grey) but not the cylinder antenna. (None of those tests are in the repository since I couldn't commit something that won't work.)
Basically I need help with material properties and setting up some basic lighting to test them (the test lighting is temporary since one of my teammates is working on lighting).
I would really appreciate if someone could help me out with doing this part.
Project info:
Repository for our project (a Visual Studio 2010 Project)
The map/grid lies along the xz plane with y being the height
Everything is done using either glCubes or glut shapes so no normals need to be defined for those, only some of the tiles and the numbers 4 everywhere are done using gl_quads
If I missed anything or if you need more info please ask!
I'll help you with the basics on lightning in OpenGL... first you need to enable and set your lights, so, here is some example:
void setlight(){
//here you set the lights and parameters, example with one light
float LightAmbient[] = { 0.1f, 0.1f, 0.05f, 1.0f };
float LightEmission[] = { 1.0f, 1.0f, 0.8f, 1.0f };
float LightDiffuse[] = { 1.0f, 1.0f, 0.8f, 1.0f };
float LightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
float LightDirection[]={-0.5f, -0.5f, -0.5f};
glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpecular);
glLightfv(GL_LIGHT0, GL_POSITION, LightDirection);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
void setmaterial(){
//here you set materials, you must declare each one of the colors global or locally like this:
float MatAmbient[] = { 0.1f, 0.1f, 0.1f, 1.0f };
float MatDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
float MatSpecular[] = { 0.1f, 0.1f, 0.0f, 0.1f };
float MatShininess = 60;
float black[] = {0.0f,0.0f,0.0f,1.0f};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, MatAmbient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MatDiffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MatSpecular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, MatShininess);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
}
void render(){
//your render function
//clean buffers, set viewport, projection, lookat, etc...
. . .
//set light and materials
setlight();
setmaterial();
//draw your stuff
. . .
glutSwapBuffers();
}
Now, if you need to set different materials for differents object to draw you must set the materials for each object before you draw them... example:
for(int i=0; i<num_objetcs; i++){
setmaterial(i);
drawobject(i);
}
Of course, you have to modify what I wrote before... You just have to set the light and then for each object you set their material and then draw, one by one. You must modify the "setmaterial" function to take the material parameter and I suppose you know what to do for the rest... good luck!
I'm writing an engine and using Light 0 as the "sun" for the scene. The sun is a directional light.
I setup the scene's Ortho viewpoint, then setup the light to be on the "East" side of the screen (and to the character) (x/y are coordinates of the plane terrain, with a positive z facing the camera and indicating "height" on the terrain -- the scene is also rotated for an isometric view on the x axis).
The light seems to be shining fine "East" of 0,0,0, but as the character moves it does not shift (CenterCamera does a glTranslate3f on the negative of the values provided, such that they can be mapped specifying world coordinates). Meaning, the further I move to the west, it's ALWAYS dark, with no light.
Graphics.BeginRenderingLayer();
{
Video.MapRenderingMode();
Graphics.BeginLightingLayer( Graphics.AmbientR, Graphics.AmbientG, Graphics.AmbientB, Graphics.DiffuseR, Graphics.DiffuseG, Graphics.DiffuseB, pCenter.X, pCenter.Y, pCenter.Z );
{
Graphics.BeginRenderingLayer();
{
Graphics.CenterCamera( pCenter.X, pCenter.Y, pCenter.Z );
RenderMap( pWorld, pCenter, pCoordinate );
}
Graphics.EndRenderingLayer();
Graphics.BeginRenderingLayer();
{
Graphics.DrawMan( pCenter );
}
Graphics.EndRenderingLayer();
}
Graphics.EndLightingLayer();
}
Graphics.EndRenderingLayer();
Graphics.BeginRenderingLayer = PushMatrix, EndRenderingLayer = PopMatrix Video.MapRenderingMode = Ortho Projection and Scene Rotation/Zoom CenterCamera does a translate to the opposite of the X/Y/Z, such that the character is now centered at X/Y/Z in the middle of the screen.
Any thoughts? Maybe I've confused some of my code here a little?
The lighting code is as follows:
public static void BeginLightingLayer( float pAmbientRed, float pAmbientGreen, float pAmbientBlue, float pDiffuseRed, float pDiffuseGreen, float pDiffuseBlue, float pX, float pY, float pZ )
{
Gl.glEnable( Gl.GL_LIGHTING );
Gl.glEnable( Gl.GL_NORMALIZE );
Gl.glEnable( Gl.GL_RESCALE_NORMAL );
Gl.glEnable( Gl.GL_LIGHT0 );
Gl.glShadeModel( Gl.GL_SMOOTH );
float[] AmbientLight = new float[4] { pAmbientRed, pAmbientGreen, pAmbientBlue, 1.0f };
float[] DiffuseLight = new float[4] { pDiffuseRed, pDiffuseGreen, pDiffuseBlue, 1.0f };
float[] PositionLight = new float[4] { pX + 10.0f, pY, 0, 0.0f };
//Light position of Direction is 5 to the east of the player.
Gl.glLightfv( Gl.GL_LIGHT0, Gl.GL_AMBIENT, AmbientLight );
Gl.glLightfv( Gl.GL_LIGHT0, Gl.GL_DIFFUSE, DiffuseLight );
Gl.glLightfv( Gl.GL_LIGHT0, Gl.GL_POSITION, PositionLight );
Gl.glEnable( Gl.GL_COLOR_MATERIAL );
Gl.glColorMaterial( Gl.GL_FRONT_AND_BACK, Gl.GL_AMBIENT_AND_DIFFUSE );
}
You will need to provide normals for each surface. What is happening (without normals) is the directional light is essentially shining on everything east of zero, positionally, while everything there has a normal of 0,0,1 (it faces west.)
You do not need to send normals with each vertex as far as I can tell, but rather because GL is a state machine, you need to make sure that whenever the normal changes you change it. So if you're rendering a face on a cube, the 'west' face should have a single call
glNormal3i(0,0,1);
glTexCoord..
glVertex3f...
glTexCoord..
etc.
In the case of x-y-z aligned rectangular prisms, 'integers' are sufficient. For faces that do not face one of the six cardinal directions, you will need to normalize them. In my experience you only need to normalize the first three points unless the quad is not flat. This is done by finding the normal of the triangle formed by the first three sides in the quad.
There are a few simple tuts on 'Calculating Normals' that I found enlightening.
The second part of this is that since it is a directional light, (W=0) repositioning it with the player position doesn't make sense. Unless the light itself is being emitted from behind the camera and you are rotating an object in front of you (like a model) that you wish to always be front-lit, its position should probably be something like
float[] PositionLight = new float[4] { 0.0f, 0.0f, 1.0f, 0.0f };
Or, if the GLx direction is being interpreted as the East-West direction (i.e. you initially are facing north/south)
float[] PositionLight = new float[4] { 1.0f, 0.0f, 0.0f, 0.0f };
The concept is that you are calculating the light per-face, and if the light doesn't move and the scene itself is not moving (just the camera moving around the scene) the directional calculation will always remain correct. Provided the normals are accurate, GL can figure out the intensity of light showing on a particular face.
The final thing here is that GL will not automatically handle shadows for you. Basic GL_Light is sufficient for a controlled lighting of a series of convex shapes, so you will have to figure out whether or not a light (such as the sun) should be applied to a face. In some cases this is just taking the solid the face belongs to and seeing if the vector of the sun's light intersects with another solid before reaching the 'sky'.
Look for stuff on lightmaps as well as shadowmapping for this.
One thing that can trip up many people is that the position sent to glLightFv is translated by the current matrix stack. Thus if you want to have your light set to a specific position in world coordinates, your camera and projection matrices must be set and active on the matrix stack at the time of the glLightFv call.
I have to put illumination in a OpenGL picture but i don't know how to put a correct point light illumination like in the following picture:
For now i had tried different mode of illumination, but the result is the following :(
I attach you the code that I used for my result. What is wrong?
float specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
// 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_LIGHTING ) ;
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);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,specref);
glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,128);
glEnable ( GL_COLOR_MATERIAL ) ;
glClearColor (1.0, 1.0, 1.0, 1.0);
glColor3f(0.0,0.0,0.0);
Edit 04/11/2011 0.39 CET
I attach also my display() function called by glutDisplayFunc(display);
void display(void)
{
[...]
//Draw polygons in 3d
glColor3f(0.0,1.0,1.0);
glBegin(GL_QUADS);
for(i=0;i<NVERT-1;i++) {
for (j=0;j<NVERT-1;j++) {
glVertex3f( (GLfloat)((sb[i*NVERT+j]).x()),
(GLfloat)((sb[i*NVERT+j]).y()),
(GLfloat)((sb[i*NVERT+j]).z()));
glVertex3f( (GLfloat)((sb[i*NVERT+j+1]).x()),
(GLfloat)((sb[i*NVERT+j+1]).y()),
(GLfloat)((sb[i*NVERT+j+1]).z()));
glVertex3f( (GLfloat)((sb[(i+1)*NVERT+j+1]).x()),
(GLfloat)((sb[(i+1)*NVERT+j+1]).y()),
(GLfloat)((sb[(i+1)*NVERT+j+1]).z()));
glVertex3f( (GLfloat)((sb[(i+1)*NVERT+j]).x()),
(GLfloat)((sb[(i+1)*NVERT+j]).y()),
(GLfloat)((sb[(i+1)*NVERT+j]).z()));
}
}
glEnd();
glFlush();
}
In practice with display I write the small areas that compose the 2° figure that i represented (I omitted the algorithm for the calculation of the points of each area because is it working).
My goal is to have a result similar to figure 1 for the lightning and rendering of the figure but I only obtained the result in figure 2.
I don't know how to put correctly the light and how to setup my figure in order to have this render (like mirror).
You're missing normals. You either need to provide one normal per vertex (glNormal) or you could enable GL_AUTO_NORMALS if you use glMap2 (which you are not). There's an article on how to compute normals for a triangle or polygons on opengl.org that you probably will find useful.
Begin Function CalculateSurfaceNormal (Input Polygon) Returns Vector
Set Vertex Normal to (0, 0, 0)
Begin Cycle for Index in [0, Polygon.vertexNumber)
Set Vertex Current to Polygon.verts[Index]
Set Vertex Next to Polygon.verts[(Index plus 1) mod Polygon.vertexNumber]
Set Normal.x to Sum of Normal.x and (multiply (Current.y minus Next.y) by (Current.z plus Next.z))
Set Normal.y to Sum of Normal.y and (multiply (Current.z minus Next.z) by (Current.x plus Next.x))
Set Normal.z to Sum of Normal.z and (multiply (Current.x minus Next.x) by (Current.y plus Next.y))
End Cycle
Returning Normalize(Normal)
End Function
From the image you posted of the results it seems you are calculating and drawing the normals (red arrows), just not applying them.
Can't really figure out what's happening with your code. I hope your cordinates are between -1 to +1. I'd suggest you to work with lighting with simple primitives. the work on with your surface generation. The lighting source's position and calculating normals are the most important points.
http://www.falloutsoftware.com/tutorials/gl/gl8.htm
http://glprogramming.com/red/chapter05.html