I am building a house in OpenGL. On the outside and on the inside where there are doors or windows, I use a Quad to go below and above the windows all the way around the house, and then a quad to fill in the gaps between windows. These will have the same plane value, but for some reason GL_LIGHT passes shadows onto some. Any clue why?
Quad between windows
glBegin(GL_QUADS);
glTexCoord2d(0, 0);glVertex3d(0, 1.1, 0);
glTexCoord2d(2, 0);glVertex3d(0, 1.1, 2);
glTexCoord2d(2, 1.6);glVertex3d(0, 2.7, 2);
glTexCoord2d(0, 1.6);glVertex3d(0, 2.7, 0);
glEnd();
Below windows
glBegin(GL_QUADS);
glTexCoord2d(0, 0);glVertex3d(0, 0.1, 0);
glTexCoord2d(15, 0);glVertex3d(0, 0.1, 15);
glTexCoord2d(15, 1);glVertex3d(0, 1.1, 15);
glTexCoord2d(0.0, 1);glVertex3d(0, 1.1, 0);
glEnd();
Above windows
glBegin(GL_QUADS);
glTexCoord2d(0, 2.6);glVertex3d(0, 2.7, 0);
glTexCoord2d(15, 2.6);glVertex3d(0, 2.7, 15);
glTexCoord2d(15, 3.0);glVertex3d(0, 3.1, 15);
glTexCoord2d(0.0,3.0);glVertex3d(0, 3.1, 0);
glEnd();
here is the code for the light
GLfloat light_position[] = { 50, 50, -1.0};
GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat ambient[] = { 1.0, 1.0, 1.0, 1.0 };
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
glLightfv(GL_LIGHT0, GL_POSITION , light_position );
glLightfv(GL_LIGHT0, GL_SPECULAR , specular);
glLightfv(GL_LIGHT0, GL_DIFFUSE , diffuse );
glLightfv(GL_LIGHT0, GL_AMBIENT , ambient );
Here is a screenshot of the result
http://imgur.com/WsgZWBF
Why is it doing this, and is there any way to fix it?
You need to supply (meaningful) vertex/face normals for OpenGL's lighting to work properly:
18.020 Why are my objects all one flat color and not shaded and illuminated?
This effect occurs when you fail to supply a normal at each vertex.
OpenGL needs normals to calculate lighting equations, and it won't calculate normals for you (with the exception of evaluators). If your application doesn't call glNormal*(), then it uses the default normal of (0.0, 0.0, 1.0) at every vertex. OpenGL will then compute the same, or nearly the same, lighting result at each vertex. This will cause your model to look flat and lack shading.
The solution is to simply calculate the normals that need to be specified at any given vertex. Then send them to OpenGL with a call to glNormal3f() just prior to specifying the vertex, which the normal is associated with.
Related
I have built a simple scene like the following:
The problem is, the blue shape is lower than the red one but somehow bleeds through. It looks proper when I rotate it like the following:
From what I searched this could be related to the order of vertices being sent, and here is my definition for those:
Shape* Obj1 = new Quad(Vec3(-5.0, 5.0, 0.0), Vec3(5.0, 5.0, 0.0), Vec3(5.0, 5.0, -10.0), Vec3(-5.0, 5.0, -10.0));
Shape* Obj2 = new Quad(Vec3(-5.0, 3.0, 0.0), Vec3(5.0, 3.0, 0.0), Vec3(5.0, 3.0, -10.0), Vec3(-5.0, 3.0, -10.0));
The Vec3 class just holds 3 doubles for x,y,z coordinates. I add these Vec3 classes to a vector, and iterate through them when I want to draw, as such:
glBegin(GL_QUADS);
for (auto it = vertex_list.begin(); it != vertex_list.end(); ++it)
glVertex3d(it->get_x(), it->get_y(), it->get_z());
glEnd();
Finally, my settings:
glEnable(GL_ALPHA_TEST | GL_DEPTH_TEST | GL_CULL_FACE);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glAlphaFunc(GL_GREATER, 0.0f);
glViewport(0, 0, WINDOW_X, WINDOW_Y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0f, 300.0);
// camera origin xyz, point to look at xyz, camera rot xyz
gluLookAt(10, 10, -20, 2.5, 2.5, -10, 0, 1, 0);
You should enable depth test, face culling and alpha testing separately.
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
They are not flags. You cannot use them in that way.
See glEnable:
glEnable — enable or disable server-side GL capabilities
void glEnable(GLenum cap);
cap Specifies a symbolic constant indicating a GL capability.
This means the paramter of glEnable is a constant and not a set of bits and GL_ALPHA_TEST, GL_DEPTH_TEST, GL_CULL_FACE are symbolic constats and not bits of a bit set.
Change your code like this:
glEnable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
See OpenGL Specifiction - 17.3.4 Depth Buffer Test, p. 500:
17.3.4 Depth Buffer Test
The depth buffer test discards the incoming fragment if a depth comparison fails. The comparison is enabled or disabled with the generic Enable and Disable commands using target DEPTH_TEST.
See OpenGL Specifiction - 14.6.1 Basic Polygon Rasterization, p. 473:
Culling is enabled or disabled by calling Enable or Disable with target CULL_FACE.
I am trying to create a project in OpenGL C++ that has 3 sides of a cube showing at run time. No rotation needed to see the 3 sides. I'm very new to OpenGL, my plan of attack right now has been changing the x, y, and z values. I am fine working in 2d but adding z to mix is what I think is tripping me up. I know using a negative value will bring the image closer to the camera and positive further away, but in my code below when I change the Z value it does nothing to the object.
I only have the front and right side showing(running) just to attempt to get those 2 in the right position in the window first before the whole cube is drawn. Originally I drew them out in terms of 0.5 or -0.5 but that only produces a rectangle on the screen.
So my main question is, is there an easier way to predict the behavior of each of the vertices? Yes I know i'm working in a graphical space, but why are some of my points not even moving when the value is changed?
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <stdlib.h> //For exit function
void exit(int); //To Exit Program
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 1.0);
glColor3f(1.0, 1.0, 1.0);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
}
void cube()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glColor3f( 1.0, 0.0, 0.0 ); glVertex3f( 0.2, -0.3, -0.5 ); // P1 is red lb
glColor3f( 0.0, 1.0, 0.0 ); glVertex3f( 0.3, 0.2, -0.5 ); // P2 is green lt
glColor3f( 0.0, 0.0, 1.0 ); glVertex3f( -0.2, 0.3, -0.5 ); // P3 is blue tt
glColor3f( 1.0, 0.0, 1.0 ); glVertex3f( -0.3, -0.2, -0.5 ); // P4 is purple tb
glEnd();
// Green side - LEFT
glBegin(GL_QUADS);
glColor3f( 0.0, 1.0, 0.0 );
glVertex3f( -0.2, -0.3, 0.5 );
glVertex3f( -0.3, 0.2, 0.5 );
glVertex3f( -0.2, 0.3, -0.5 );
glVertex3f( -0.3, -0.2, -0.5 );
glEnd();
glFlush();
}
void myKeyboard(unsigned char theKey, int mouseX, int mouseY)
{
switch(theKey)
{
case 'Q':
case 'q':
exit(-1); //terminate the program
default:
break; // do nothing
}
}
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(640,480);
glutInitWindowPosition(100,150);
glutCreateWindow("Shapes: Q or q to quit");
glutDisplayFunc(cube);
glutKeyboardFunc(myKeyboard);
init();
glEnable(GL_DEPTH_TEST);
glutMainLoop();
}
The problem isn't with the behavior of the vertices, but rather that you're using an orthographic projection instead of a perspective one. If you'd like to continue using ancient OpenGL, gluPerspective is what you want instead of glOrtho. If you want to move up to more modern OpenGL, all the matrix math functions are removed, so you'd have to use a library like glm to do all your math instead.
A rectangle is getting produced because in an orthographic projection, parallel lines remain parallel, so there's no horizon point or anything. If it's behind or parallel to an edge of the front face of the rectangle, you're not seeing it. A perspective projection more closely matches how a camera sees the world, with parallel points eventually converging in the distance.
A good way to think about this is to think about a really long segment of straight railroad tracks. In an orthographic projection, you would just see two rails continuing on straight forever. In a perspective projection, you would eventually see the two rails meet at a single point in the distance and would also be able to partially see the inner edge of the rail.
I want to add a Light source to my OpenGl code.
I have added following code to my init function...
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightf(GL_LIGHT0, GL_POSITION,(50.0,0.0,0.0,1.0));
Moreover I have drawn a quad:
glBegin(GL_QUADS);
glNormal3f(0.0,0.0,1.0);
glVertex3f(0.0,0.0,20.0);
glVertex3f(0.0,10.0,20.0);
glVertex3f(10.0,10.0,20.0);
glVertex3f(10.0,0.0,20.0);
glEnd();
But no matter what value I use for the Position,
the lighting doesn't change at all...
glLightf(GL_LIGHT0, GL_POSITION,(50.0,0.0,0.0,1.0));
^^^^^^^^^^^^^^^^^^
(50.0,0.0,0.0,1.0) in this context will evaluate to the last expression in the list (1.0). Probably not what you want.
You need to use a real array and glLightfv() to specify light positions:
GLfloat pos[] = { 50.0, 0.0, 0.0, 1.0 };
glLightfv( GL_LIGHT0, GL_POSITION, pos );
i want to draw a rotating cube in the middle of the screen, and i want it to be lit by a light above it (i want it to look as if the cube was being lit from a fixed screen position). my problem is that i don't know how to prevent the light from rotating with the cube.
here's the code:
(SUMMARY: initGL, paintGL, and resizeGl are the functions that you always have to implement. in paintGL i use makeCube(). in makeCube() i use glBegin(GL_QUADS) to make a cube,and i use calcNormals() to calculate the normals of the cube )
-------------initGL--------------------------
angle=0.0;
glEnable (GL_DEPTH_TEST);
glEnable (GL_LIGHTING);
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[]= { 0.0f, 1.5f,1.5f, 1.0f };
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT0, GL_POSITION,LightPosition);
glEnable (GL_LIGHT0);
--------------paintGL------------------
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -13.0);
glRotatef(angle,0.0f,1.0f,0.0f);
makeCube();
angle+=0.3;
--------------void makeCube()-------------------
float P[8][3]={ {-1,-1, 1},{1,-1, 1},{1,1, 1},{-1,1, 1},
{-1,-1,-1},{1,-1,-1},{1,1,-1},{-1,1,-1}};
float * planes[6][4] ={ {P[0],P[1],P[2],P[3]},
{P[1],P[5],P[6],P[2]},
{P[4],P[7],P[6],P[5]},
{P[0],P[3],P[7],P[4]},
{P[3],P[2],P[6],P[7]},
{P[0],P[4],P[5],P[1]}};
int i;
for(i=0;i<6;i++){
float *normal;
normal = calcNormal(planes[i][0],planes[i][1],planes[i][2]);
glBegin(GL_QUADS);
glNormal3f(normal[0], normal[1], normal[2]);
glVertex3f(planes[i][0][0],planes[i][0][1],planes[i][0][2]);
glVertex3f(planes[i][1][0],planes[i][1][1],planes[i][1][2]);
glVertex3f(planes[i][2][0],planes[i][2][1],planes[i][2][2]);
glVertex3f(planes[i][3][0],planes[i][3][1],planes[i][3][2]);
glEnd();
}
----------------float* calcNormal()----------------------
float vec1[3] = {P2[0]-P1[0],P2[1]-P1[1],P2[2]-P1[2]};
float vec2[3] = {P3[0]-P2[0],P3[1]-P2[1],P3[2]-P2[2]};
float cross[3] = {vec1[1]*vec2[2]-vec2[1]*vec1[2],
vec1[2]*vec2[0]-vec2[2]*vec1[0],
vec1[0]*vec2[1]-vec2[0]*vec1[1]};
float modCross = sqrt(cross[0]*cross[0]+cross[1]*cross[1]+cross[2]*cross[2]);
cross[0]/=modCross;
cross[1]/=modCross;
cross[2]/=modCross;
return cross;
-------------resizeGL--------------------------
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLfloat x = GLfloat(width) / height;
glFrustum(-x, +x, -1.0, +1.0, 4.0, 15.0);
glMatrixMode(GL_MODELVIEW);
It seems that you're transforming the position of the light in your paintGL section.
Looking over old code, I found an app in my code directory that loads and rotates .OBJ meshes, while allowing the light to be moved.
I think that the solution is to set the position of the light each frame. (Can't remember it's been over 18 months since I touched the project)
void idleFunc()
{
light(); /// *** I think you need to replicate this functionality ****
glPushMatrix();
myGluLookAt(0.0, -.50, -6.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 */
transformFunc();
displayFunc();
glPopMatrix();
}
void displayFunc()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (useDrawList)
glCallList(DLid);
else
drawObj(loadedObj);
drawLight0(); // *** just displays an unlit sphere at the position of the light **
glutSwapBuffers();
frameCount++;
}
/* set the poition of each of the lights */
void light()
{
glLightfv(GL_LIGHT0, GL_POSITION, lightPos1);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos2);
}
i solved this problem drawing the cube with VERTEX ARRAYS rather than DIRECT MODE, it seems that rotations or lights affect the object in a different way with each method, which is quite weird
I have a problem where the fog works like intended on a desktop program (PC) using OpenGL but the same fog doesn't work like it should on an Android device (using OpenGL ES).
The code is a exact duplicate, it looks like this:
// OpenGL ES Init
gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
float fogColor[] = {0.5, 0.5, 0.5, 1.0};
// Fog color to mFogBuffer...
gl.glEnable(GL10.GL_FOG);
gl.glFogfv(GL10.GL_FOG_COLOR, mFogBuffer);
gl.glFogf(GL10.GL_FOG_DENSITY, 0.04f);
// OpenGL Init
glClearColor(0.5, 0.5, 0.5, 1.0);
float fogColor[] = {0.5, 0.5, 0.5, 1.0};
glEnable(GL_FOG);
glFogfv(GL_FOG_COLOR, fogColor);
glFogf(GL_FOG_DENSITY, 0.04f);
But I can't get the OpenGL fog work exactly the same on my Android device. I have tested glShadeModel()'s attributes and so on.
The area that should fog is totally white and it is a basic quad (built by triangles).
I have done some gluLookAt() transformations, but it shouldn't affect this fog.
Any ideas?
Try glHint(GL_FOG_HINT, GL_NICEST).