PDA

View Full Version : Depth and Lighting problem



openglbeginner123
07-27-2014, 11:26 AM
Hello again!,

I just want to first say that I greatly appreciate the feedback I have been getting on this forum, and I hope you guys could help me out on this new issue I keep running into.

What I am struggling with, is lighting and depth. I want to draw a sort of a double side arrow on the screen and then have a loop run that will rotate it in x , y , and z axis. The rotation I have working, and so the loop. But the problem is that even though I am drawing everything in 3D and my calculations are right, something is off when I rotate the whole object. The negative effect that I am getting is basically that the object doesn't seem to look like its in proper 3D. The effect of "depth" is not there because the different parts of the object overlap, cross each other when I want them to be behind each other etc. and it is just confusing. There is no sense of a certain reference position in space if that makes any sense, because everything just rotates without the proper light change and the depth I am looking for.

I really do realize my explanation might be confusing but perhaps the key problem that I have is that my objects do not look to behave realistically.

I am therefore wondering if someone may know how to get the light functioning properly or the depth or how to fix whatever I am doing wrong.

As a side note, I posted all of my code and tried to give the best explanation I could. Drawing-wise, what I am doing to simulate the "arrow",is I loop through 360 degrees and draw a bunch of lines with points on the circle (the bottom of the cone) and one point at the "top". This creates the cone.
The set up that I have is for the light. Again, I don't know if I am setting it up right.. Also, I am quite sure I need normals for my object to get the light working so that might be the issue, however I have no idea how to set up the normals for a cone that I want to draw. I work in Xcode and writing an OSX application so the code is Objective - C, but the openGL is obviously the same. The drawRect method I have is the method that gets called very frame to update the drawing.


It would be awesome if someone could contribute and give some feedback. Please ask to clarify anything if something I wrote is confusing.

As always, thanks in advance for any feedback. :)








-(void) drawRect: (NSRect) bounds
{
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH);
glDepthFunc(GL_ALWAYS);
glEnable(GL_CULL_FACE);


glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);


GLfloat global_ambient[] = { 1, 1, 0, 1.0f };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);

glShadeModel(GL_SMOOTH);

GLfloat specular[] = {1.0f, 1.0f, 1.0f , 1.0f};
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);

GLfloat ambient[] = { 1.0f, 1.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);

GLfloat position[] = { -1.0f, 1.0f, 0, 1.0f };
glLightfv(GL_LIGHT0, GL_POSITION, position);



glLoadIdentity();

glScalef(0.5, 0.5, 0.5);


glRotatef(rotation,1,0,0);
glRotatef(rotation,0,1,0);
glRotatef(rotation,0,0,1);


// After all of transformations - draw the graphics

double pi = 3.14159265359;



glColor3f(1, 0.12, 0.42);

glBegin(GL_LINES);

glVertex3f(0, 0, 0);
glVertex3f(0, 1, 0);

for(double theta = 0; theta < 360; theta++){
double x = 0.015 * cosf(theta * pi / 180);
double y = 0.015 * sinf(theta * pi / 180);
glVertex3f(x, 0, y);
glVertex3f(x, 1, y);

}

glEnd();



glBegin(GL_LINES);

for(double theta = 0; theta < 360; theta++){
double x = 0.1 * cosf(theta * pi / 180);
double y = 0.1 * sinf(theta * pi / 180);
glVertex3f(x, 1, y);
glVertex3f(0, 1.3, 0);

}
glEnd();


glColor3f(0.5, 0.5, 0.5);

glBegin(GL_POINTS);

for(double theta = 0; theta < 360; theta++){
double x = 0.3 * cosf(theta * pi / 180);
double y = 0.3 * sinf(theta * pi / 180);
glVertex3f(x, 0, y);

}
glEnd();


glColor3f(0.4, 0.2, 0.2);

glBegin(GL_LINES);

for(double theta = 0; theta < 360; theta++){
double x = 0.025 * cosf(theta * pi / 180);
double y = 0.025 * sinf(theta * pi / 180);
glVertex3f(x, 1, y);
}
glEnd();



// bottom arrow


glColor3f(1, 0.12, 0.42);

glBegin(GL_LINES);

glVertex3f(0, 0, 0);
glVertex3f(0, -1, 0);

for(double theta = 0; theta < 360; theta++){
double x = 0.015 * cosf(theta * pi / 180);
double y = 0.015 * sinf(theta * pi / 180);
glVertex3f(x, 0, y);
glVertex3f(x, -1, y);

}

glEnd();



glBegin(GL_LINES);

for(double theta = 0; theta < 360; theta++){
double x = 0.1 * cosf(theta * pi / 180);
double y = 0.1 * sinf(theta * pi / 180);
glVertex3f(x, -1, y);
glVertex3f(0, -1.3, 0);

}
glEnd();


glColor3f(0.5, 0.5, 0.5);

glBegin(GL_POINTS);

for(double theta = 0; theta < 360; theta++){
double x = 0.3 * cosf(theta * pi / 180);
double y = 0.3 * sinf(theta * pi / 180);
glVertex3f(x, -1, y);
}

glEnd();

glColor3f(0.4, 0.2, 0.2);

glBegin(GL_LINES);

for(double theta = 0; theta < 360; theta++){
double x = 0.025 * cosf(theta * pi / 180);
double y = 0.025 * sinf(theta * pi / 180);
glVertex3f(x, -1, y);
}
glEnd();


glFlush();

rotation++;
}

carsten neumann
07-27-2014, 01:12 PM
Admittedly I haven't quite understood what you want to achieve, but I notice all you are drawing are lines and points and you are not specifying any normals. For lighting to work you must have normals, those are used to calculate the amount of light reflected from a surface. You also need to specify materials for what you are drawing, at least you'll have to glEnable(GL_COLOR_MATERIAL) and use glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE) so that your vertex color is used as diffuse material component.

IIRC you can have OpenGL calculate lighting for lines and points but the effect will be somewhat difficult to see since these primitives do not exactly produce large surfaces ;)

Dan Bartlett
07-27-2014, 01:24 PM
You probably want GL_LESS (default) or GL_LEQUAL for the glDepthFunc (https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glDepthFunc.xml) parameter rather than GL_ALWAYS, so that only fragments that are nearer than the current depth value are drawn.

openglbeginner123
07-27-2014, 11:33 PM
Yep, I realize normals are key for lighting. The problem though, is that because everything I draw comes from just lines, I don't know how to compute the normals and how many of them I need.(for example its kind of easier for cubes) Do I need a normal for every line? If normals is what I need for this to work properly, some help on normals specifically for lighting wold help. :) Thanks

carsten neumann
07-28-2014, 03:20 AM
Well, I don't think there is an obviously correct answer (what's the surface of a line?), you'll have to make something up. Mathematically there is a plane that is orthogonal to a line, so any vector in that plane is (in a sense) a normal to the line. You could come up with some rule to consistently pick vectors from the plane, e.g. use the vector with the largest z component, if it is not unique use the one with the largest y component - or maybe for your case there is some better way you can define what you want to consider the front surface of a line.

openglbeginner123
07-28-2014, 09:27 AM
Got it. Thanks again. Yeah, I mean I realize that if I have a plane orthogonal to a line I can choose any vector on that plane. But what I still don't know as kind of an OpenGL thing here, do I need to define a normal for every line I draw? (Again, I am drawing a cone so technically do I need 360 normals for the sides and one for the bottom? or one for the top) So basically I think I am getting that I need a unique vector every time I need a normal, but I am still confused as to how many normals I need to have... (cause technically I could calculate a normal to any line I am drawing but do I need to?) Thanks for your responses a lot

Carmine
07-28-2014, 10:45 AM
... to draw a sort of a double side arrow ... Not sure what you mean by 'double side'. Why are you generating the coordinates yourself? gluCylinder will do all of this for you. It calculates normals too. A solid arrow consisting of a cone at the end of a cylinder can be made with two calls to gluCylinder. If you must have wireframe instead of surfaces, call glPolygonMode before the call to gluCylinder. If you want vertices and wireframe, draw the arrow twice with PolygonMode set to lines the first time and points the second time. Since the points and lines are considered parts of polygons by gluCylinder, they will be assigned the normals of those polys, and should be illuminated properly.

Also, if you want to see lighting effects more clearly, set ambient color values for lights and materials very low, like (0.1, 0.1, 0.1).

openglbeginner123
07-28-2014, 08:20 PM
Not sure what you mean by 'double side'. Why are you generating the coordinates yourself? gluCylinder will do all of this for you. It calculates normals too. A solid arrow consisting of a cone at the end of a cylinder can be made with two calls to gluCylinder. If you must have wireframe instead of surfaces, call glPolygonMode before the call to gluCylinder. If you want vertices and wireframe, draw the arrow twice with PolygonMode set to lines the first time and points the second time. Since the points and lines are considered parts of polygons by gluCylinder, they will be assigned the normals of those polys, and should be illuminated properly.

Also, if you want to see lighting effects more clearly, set ambient color values for lights and materials very low, like (0.1, 0.1, 0.1).


Thank you for the feedback. Yeah, using gluCylinder makes much more sense, and it calculates normals which is even easier and better for me to use so thanks for that suggestion.
There is a problem though and I don't expect you to know the answer to this cause I searched around and didn't find anything. Because I am developing in Xcode and I am writing Mac OS X applications, gluCylinder is deprecated (like a lot of other cool stuff) in the OpenGL version that is present in this IDE I am using. This is really annoying cause I can't use this function which makes a lot of sense to use in what I am doing.

If you or anyone else here knows something about this and/or has some experience writing programs in Xcode and using OpenGL in Xcode I would greatly appreciate some help and feedback

Thanks in advance guys :)