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.
Related
I want to construct a Orthographic projection to make my sun's shadow map look right. Unfortunately, the code is not achieving the desired results as using the regular perspective projection. Here's my code for setting up the projection matrix:
glViewport (0, 0, (GLsizei)shadowMap.x, (GLsizei)shadowMap.y);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
//suns use this
glOrtho(0, shadowMap.x, 0, shadowMap.y, 0.1,1000.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
From what I understand that should be correct. However, after a quick debug render, I noticed that the scene was rendering in a tiny portion of the screen. After some experimentation, I found changing the shadowMap values in glOrtho made it cover the whole texture, but it was really zoomed in. In my perspective projection I use 0.1 and 1000.0 for my near and far, and I've experimented with those and it does change the results, but not get the desired results still. The only time that I get the correct results is when the values are kept with shadowMap.x and shadowMap.y, but like I said, its rendering really small.
What am I doing wrong here? Everything I've read said that the initial code is correct.
EDIT:
Apparently it wasn't clear that this is for the shadow map pass, the regular pass is rendered with perspective and is fine.
Shadow mapping is multi pass algorithm.
You are reffering to the first pass (point 1).
Render scene form light source view into depth texture
Render scene from camera view with depth texture projection mapping enabled.
current fragment xy+depth is then transformed into light projection coordinates and is compared to stored depth on depth texture
if both depths are equal (or nearly equal) current fragment should be considered as lit, otherwise as shadowed.
So everything's fine with your code, store depth values from this pass to depth texture and proceed to point 2.
One thing you should think about is how wide area your light should cover (in world space). With loadidentity on modelview you are attempting to cover 1 world unit x 1 world unit area for you light only.
Consider we have a sphere at 0,0,0 with radius 5.0
We have depth texture of 256,256 dims.
We want to project it along Z onto sphere.
glVieport(0,0,256,256);
glMatrixMode(GL_PROJECTION);
glLoadidentity();
glOrtho(-2.5,2.5,-2.5,2.5,-1000,1000);
glMatrixMode(GL_MODELVIEW);
glLoadidentity();
//flip z, we cast light from obove
glRotate(1,0,0,180);
I don't see where you set the light modelview matrix. You can render a shadow map using the code below:
double* getOrthoMVPmatrix(vector3 position,vector3 lookat,
GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble nearVal, GLdouble farVal)
{
glPushMatrix();
double projection[16];
double modelView[16];
double *matrix = new double [16];
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( left, right, bottom, top, nearVal, farVal) ;
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
glLoadIdentity();
gluLookAt(position.x,position.y,position.z,lookat.x,lookat.y,lookat.z,0,1,0);
glGetDoublev(GL_MODELVIEW_MATRIX, modelView);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glPopMatrix();
matrix = projection*modelView;
return matrix ;
}
void renderShadowMap(void)
{
//"Bind your depth framebuffer"
glViewport(0,0,"Your SM SIZE","Your SM SIZE");
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
double *MVP = getOrthoMVPmatrix( "your light position","your light position" + "your light direction",
-"left","right",
"bottom","top",
"near","far"
) ;
//"call glUseProgram to bind your shader"
// set the uniform MVP we made "
//"Draw your scene "
glViewport(0,0,"screen width","screen height");
}
Your will need to make a multiplication operator for double [16] array. In my case i made a matrix class but do it your way.
Dont forget to call glCullFace(GL_BACK) before drawing your real scene and free MVP after.
I have a tile engine using orthographic projection in immediate mode and I'm just trying to draw a 3d cube on top of my tile scene, in hopes that I can eventually incorporate 3d models into my engine instead of just sprites / textured quads. I would also like to make the tiles 3d for that slight bit of extra eye candy.. Hopefully I can eventually convert this to use modern OpenGL so I can take advantage of those extra features. Not on the top of my priority list at the moment. So on to the question.
I'm initializing OpenGL with this:
void initGL()
{
glDisable(GL_DEPTH_TEST);
glViewport( 0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
//Initialize Projection Matrix
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
//Initialize Modelview Matrix
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
glOrtho(0,SCREEN_WIDTH,SCREEN_HEIGHT,0,0,1);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
//...setting some various other attributes, omitted for brevity...
glEnable(GL_TEXTURE_2D);
glClearColor( 0, 0, 0, 0 );
}
I have a function for drawing a cube that works.
void draw_cube()
{
/* position object */
glRotatef(30.0F, 1.0F, 0.0F, 0.0F);
glRotatef(30.0F, 0.0F, 1.0F, 0.0F);
/* draw six faces of a cube */
glBegin(GL_QUADS);
...vertices... (removed for brevity)
glEnd();
}
I made 2 functions for setting the 2d and 3d projection modes.
void set3d()
{
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(0,SCREEN_WIDTH,0,SCREEN_HEIGHT, 0,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void set2d()
{
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,SCREEN_WIDTH,SCREEN_HEIGHT,0,0,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
For the sake of completeness, some pseudocode of my textured quad drawing..
pushmatrix();
translate();
rotate();
-translate();
glbegin();
...vertices
glend();
popmatrix();
So far I have managed to get the cube to draw on top of the tiles, but it disappears after approximately 1 second to never be seen again until I run the program again.
Basically what I'm doing in the main loop is this:
move objects around, process collisions, etc.
set2d();
draw textured quads, lines, text, etc. in 2d mode.
set3d();
draw_cube();
My question is: Why is the cube disappearing, and are there any errors in my set2d() and set3d() functions?
You have quite a few problems in this code, too many to list in comments in fact.
Your projection matrices are changing the handedness of your post-projected coordinate space, which will affect polygon winding.
Stick to a single handedness, unless you want to reverse the direction used for front- / back-facing polygon facets (glFrontFace (...)) - it is CCW by default, but you will have to change it to CW when you use set3d (...) to maintain consistent behavior.
This problem arises because you have the Y-axis going different directions
The behavior your are describing, where the object appears briefly and then disappears is indicative of an issue with your matrix stack.
Are you calling initGL (...) more than once in your software? You will run into a stack overflow if you do this enough times since you needlessly push the current matrix onto the stack and never pop it off.
You cannot use 0.0 for zNear with a perspective projection matrix, this will result in wonky math during the perspective divide step that comes after transformation to clip-space; the depth buffer will not work correctly.
In fact, glFrustum (...) will generate a GL_INVALID_VALUE error and do exactly nothing if you pass a value ≤ 0.0 for zNear. On a related note, gluPerspective (...) will not do this since it is not actually part of OpenGL, but it is equally invalid behavior to pass such a value to gluPerspective (...).
I just started working with OpenGL, but I ran into a problem after implementing a Font system.
My plan is to simply visualize several Pathfinding Algorithms.
Currently OpenGL gets set up like this (OnSize gets called once on window creation manually):
void GLWindow::OnSize(GLsizei width, GLsizei height)
{
// set size
glViewport(0,0,width,height);
// orthographic projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,width,height,0.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
m_uiWidth = width;
m_uiHeight = height;
}
void GLWindow::InitGL()
{
// enable 2D texturing
glEnable(GL_TEXTURE_2D);
// choose a smooth shading model
glShadeModel(GL_SMOOTH);
// set the clear color to black
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);
}
In theory I don't need blending, because I will only use untextured Quads to visualize obstacles and line etc to draw paths... So everything will be untextured, except the fonts...
The Font Class has a push and pop function, that look like this (if I remember right my Font system is based on a NeHe Tutorial that I was following quite a while ago):
inline void GLFont::pushScreenMatrix()
{
glPushAttrib(GL_TRANSFORM_BIT);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(viewport[0],viewport[2],viewport[1],viewport[3], -1.0, 1.0);
glPopAttrib();
}
inline void GLFont::popProjectionMatrix()
{
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
So the Problem:
If I don't draw a Text I can see the Quads I want to draw, but they are quite dark, so there must be something wrong with my general OpenGL Matrix Properties.
If I draw Text (so the font related push and pop functions get called) I can't see any Quads.
The question:
How do I solve this problem and some background information why this happened would also be nice, because I am still a beginner/student, who just started.
If your quads are untextured, you will run into undefined behaviour. What will probably happen is that any previous texture will be used, and the colour at point (0,0) will be used, which could be what is causing them to be invisible.
Really, you need to disable texturing before trying to draw untextured quads using glDisable(GL_TEXTURE_2D). Again, if you don't, it'll just use the previous texture and texture co-ordinates, which without seeing your draw() loop, I'm assuming to be undefined.
This question already has an answer here:
Closed 12 years ago.
Possible Duplicate:
How to give a 2D structure 3D depth
Hello everyone,
I posted this same question yesterday. I would like to have uploaded images showing my program output but due to spamming protection I am informed I need 10 reputation "points". I could send images of my output under different projection matrices to anyone willing.
I am beginning to learn OpenGL as part of a molecular modeling project, and currently I am trying to render 7 helices that will be arranged spatially close to each other and will move, tilt, rotate and interact with each other in certain ways.
My question is how to give the 2D scene 3-Dimensional depth so that the geometric structures look like true helices in three dimensions?
I have tried playing around with projection matrices (gluPerspective, glFrustum) without much luck, as well as using the glDepthRange function. As I understand from textbook/website references, when rendering a 3D scene it is appropriate to use a (perspective) projection matrix that has a vanishing point (either gluPerspective or glFrustum) to create the illusion of 3 dimensions on a 2D surface (the screen)
I include my code for rendering the helices, but for simplicity I insert the code for rendering one helix (the other 6 helices are exactly the same except for their translation matrix and the color function parameters) as well as the reshape handler.
This is the output ![enter image description here][1] I get when I run my program with an orthographic projection (glOrtho) and it looks as a 2D projection of helices (curved lines drawn in three dimensions). This is my output (![enter image description here][2]) when I use a perspective projection (glFrustum in my case). It does not appear as if I am looking at my helices in 3D!!
Perhaps the glFrustum parameters are wrong?
//GLOBALS
GLfloat x, y, z;
GLfloat c = 1.5f; //helical pitch
GLfloat theta; //constant angle between tangent and x-axis
thetarad = theta/(Pi/180.0); //angle converted from degrees to radians
GLfloat r = 7.0f; //radius
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST); /* enable depth testing */
glDepthFunc(GL_LESS); /* make sure the right depth function is used */
/*CALLED TO DRAW HELICES*/
void RenderHelix() {
/**** WHITE HELIX ****/
glColor3f(1.0,1.0,1.0);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(-30.f, 100.f, 0.f); //Move Position
glRotatef(90.0, 0.0, 0.0, 0.0);
glBegin(GL_LINE_STRIP);
for(theta = 0; theta <= 360; ++theta) { /* Also can use: for(theta = 0; theta <= 2*Pi; ++rad) */
x = r*(cosf(theta));
y = r*(sinf(theta));
z = c*theta;
glVertex3f(x,y,z);
}
glEnd();
glScalef(1.0,1.0,12.0); //Stretch or contract the helix
glPopMatrix();
/* Code for Other 6 Helices */
.............
glutSwapBuffers();
}
void Reshape(GLint w, GLint h) {
if(h==0)
h=1;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLfloat aspectratio = (GLfloat)w/(GLfloat)h;
if(w<=h)
//glOrtho(-100,100,-100/aspectratio,100/aspectratio, -50.0,310.0);
//glOrtho(-100,100,-100/aspectratio,100/aspectratio, 0.0001,1000000.0); //CLIPPING FAILSAFE TEST
//gluPerspective(122.0,(GLfloat)w/(GLfloat)h,10.0,50.0);
glFrustum(-10.f,10.f, -100.f/aspectratio, 100.f/aspectratio, 1.0f, 15.0f);
else
//glOrtho(-100*aspectratio,100*aspectratio,-100,100,-50.0,310.0);
//glOrtho(-100*aspectratio,100*aspectratio,-100,100,0.0001,1000000.0); //CLIPPING FAILSAFE TEST
//gluPerspective(122.0,(GLfloat)w/(GLfloat)h,10.0,50.0);
glFrustum(-10.f*aspectratio,10.f*aspectratio,-10.f,10.f, 1.0f,15.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
The usual reason that simple 3d applications don't "look 3d" is because you need to set up a lighting system. Lighting is a major source of depth cues to your brain.
Here's a good tutorial on adding lighting to an OpenGL program:
http://www.cse.msu.edu/~cse872/tutorial3.html
EDIT: For more context, here's the relevant chapter from the classic OpenGL Red Book:
http://fly.cc.fer.hr/~unreal/theredbook/chapter06.html
Notice the screenshot near the top, showing the same sphere render both with and without lighting.
I agree it's difficult if you can't post your images (and it may not be trivial then).
If your code is open source you are likely to get help for molecular modelling from the Blue Obelisk Community (http://blueobelisk.shapado.com/ is a SE-type site for answering these questions).
There used to be a lot of GL used in our community but I'm not sure I know a good code which which you could hack to get some idea of the best things to do. The leading graphics tools are Jmol (where the gfx were largely handwritten and very good) and Avogadro which uses Qt.
But if you ask for examples of open source GL moelcular graphics you'll probably get help.
And of course you'll probably get complementary help here
I have a simple particle effect in OpenGL using GL_POINTS. The following is called, being passed particles in order from the particle furthest from the camera first to the one nearest the camera last:
void draw_particle(particle* part) {
/* The following is how the distance is calculated when ordering.
* GLfloat distance = sqrt(pow(get_camera_pos_x() - part->pos_x, 2) + pow(get_camera_pos_y() - part->pos_y, 2) + pow(get_camera_pos_z() - part->pos_z, 2));
*/
static GLfloat quadratic[] = {0.005, 0.01, 1/600.0};
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic);
glPointSize(part->size);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POINT_SPRITE_ARB);
glEnable(GL_TEXTURE_2D);
glBegin(GL_POINTS);
glColor4f(part->r, part->g, part->b, part->a);
glVertex3f(part->pos_x, part->pos_y, part->pos_z);
glEnd();
glDisable(GL_BLEND);
glDisable(GL_POINT_SPRITE_ARB);
}
However, there is some artifacting when rendering as can be seen in the following effect:artifacted image http://img199.imageshack.us/img199/9574/particleeffect.png
The problems go away if I disable depth testing, but I need the effects to be able to interact with other elements of the scene, appearing in front of and behind elements of the same GL_TRIANGLE_STRIP depending on depth.
If your particules are already sorted you can render like this :
Render particule with GL WRITE DEPTH but no depth testing (I don't remember exactly the constants)
Render the rest of the scene with depth test.
This way you are sure to get scene interaction with nice-looking particules.
Note: Please specify which OpenGL version you use when you post questions. That goes for any API.
When you want to render primitives with alpha blending, you can't have depth writes enabled. You need to draw your blended primitives sorted back-to-front. If you have opaque objects in the scene, render them first, and then draw your transparent primitives in a back-to-front sorted fashion with depth test enabled and depth writes disabled.
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POINT_SPRITE);
glEnable(GL_CULL_FACE);
while(1)
{
...
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_BLEND);
glDepthMask(1);
RenderOpaque();
SortSprites();
glEnable(GL_BLEND);
glDepthMask(0);
DrawSprites();
...
}