Why is display function called twice? - c

In the OpenGL code below, used for initialization and for the main function, why is the display function getting called twice? I can't see a call that would be executed other than glutDisplayFunc(display);
void init(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClearDepth(1.0f); // Set background depth to farthest
glEnable(GL_DEPTH_TEST); // Enable depth testing for z-culling
glEnable(GL_POINT_SMOOTH);
glDepthFunc(GL_LEQUAL); // Set the type of depth-test
glShadeModel(GL_SMOOTH); // Enable smooth shading
gluLookAt(0.0, 0.0, -5.0, /* eye is at (0,0,5) */
0.0, 0.0, 0.0, /* center is at (0,0,0) */
0.0, 1.0, 0.0); /* up is in positive Y direction */
glOrtho(-5,5,-5,5,12,15);
//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Nice perspective corrections
}
int
main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow("red 3D lighted cube");
glutInitWindowSize(1280,800 ); // Set the window's initial width & height
//glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
//glutReshapeWindow(800,800);
init();
compute();
glutDisplayFunc(display);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}

Your display() callback is called whenever GLUT decides it wants the application (that's you) to redraw the contents of the window.
Perhaps there is some events happening as the window opens that causes a need to make sure the window is redrawn.
You're not supposed to "care"; just make sure you redraw the content in the display() function and never mind how many times it gets called.

Related

Infinite Loop on OpenGL

I decided that whenever the user tries to resize the screen the screen must go back to preset sizes, so it makes my life easier on graph nodes drawing. On MAC, my application is working properly but on Linux it is happening an infinte loop on the resize function, and I don't know why. After some loop calls I got a Segmentation fault (core dumped)
here's my opengl configuration(main funciton)
glutInit(&argc, argv);
glutInitDisplayMode ( GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutInitWindowPosition(100, 100);
glutCreateWindow(APP_NAME);
glClearColor(0.0, 0.0, 0.0, 0.0); // black background
glMatrixMode(GL_PROJECTION); // setup viewing projection
glLoadIdentity(); // start with identity matrix
glOrtho(0.0, 50.0, 0.0, 50.0, 0.0, 0.1); // setup a 50x50 viewing world
glutDisplayFunc(display);
glutReshapeFunc(resize);
glutMainLoop();
and here's my display and resize functions implementations
void display() {
Matrix* distanceMatrix = NULL;
PalleteNodePosition* nodesPositions = NULL;
distanceMatrix = fromFile(inputFileName);
printf("Finish input parsing...\n");
nodesPositions = calculateNodesPositions(distanceMatrix);
printf("Finish calculating nodes position on screen...\n");
glClear( GL_COLOR_BUFFER_BIT);
drawNodes(nodesPositions, distanceMatrix->width);
drawLink(10, 10, 18, 18);
glFlush();
}
void resize(int w, int h){
glutReshapeWindow(WINDOW_WIDTH, WINDOW_HEIGHT);
}
When I print the resize call, I got w equals to WINDOW_WIDTH and h equals to WINDOW_HEIGHT as expected, so why the app is resizing the screen everytime?
Your resize() callback will be indirectly called by itself even if it
is in an asynchronous way.
You ask the windowing system to resize your window, then later
you receive the event that says that your window has been resized,
then your callback is triggered, which leads to a new resize
request...
If nobody stops this loop (apparently the windowing system
does not detect that the resize is not actually needed),
it is infinite.
May be should you consider comparing w and h to the expected
values, inside your resize() callback, and only invoke glutReshapeWindow() if it is actually needed?
You should also be aware that the inner size and the outer size
of the window are probably different (border, title-bar...).

Setting transparent background color in OpenGL doesn't work

I tried setting the background color to a transparent one using the functions - glClearColor() and glClear(). But, the alpha values passed to glClearColor() simply doesn't change anything.
Here is the code I tried running:
#include<GL/glut.h>
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,(float)glutGet(GLUT_WINDOW_WIDTH),0.0,(float)glutGet(GLUT_WINDOW_HEIGHT));
glBegin(GL_LINES);
glVertex2i(200,200);
glVertex2i(300,305);
glEnd();
glFlush();
}
int main(int argc, char *argv[const])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_ALPHA);
glutInitWindowSize(1100,620);
glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH)-1100)/2,(glutGet(GLUT_SCREEN_HEIGHT)-620)/2);
glutCreateWindow("GLUT Programming");
glClearColor(0.0f,0.0f,0.0f,0.5f); // I have tried experimenting with this part, but, nothing happens
glutDisplayFunc(display);
glutMainLoop();
}
I am using freeglut and freeglut-devel on my machine running Fedora 26, if it helps.
EDIT :
Result I am getting :
Result I am trying to obtain :
If you want to enable Blending, then you have to enable blending (glEnable( GL_BLEND )) and you have to set the blend function (glBlendFunc).
Further you have to set the alpha channel of the color, which you use to draw the geometry (glColor4f)
Change your code somehow like this:
glClearColor( 0.5f, 0.5f, 0.5f, 1.0f ); // background color
glClear(GL_COLOR_BUFFER_BIT); // clear background with background color
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); // = color * alpha + background * (1-alpha)
glColor4f( 1.0f, 0.0f, 0.0f, 0.1f ); // color of the line, alpha channel 0.1 (very "transparent")
glLineWidth( 5.0 );
glBegin(GL_LINES);
.....

Make some shapes in OpenGL to be moved with arrow keys - it zooms out instead of moving

Well, I have the following C code on a GLUT Project (I use CodeBlocks).
It draw some 2D shapes (something like Robot :p ).
I want to make the whole drawing shapes to be moved with the keyboard arrow keys. I have wrote the following, but for some reason when I push the arrow keys, it seems like it zoom in/out. It does not move.
#include <GL/glut.h>
GLuint head_x1=5, head_y1=30, head_x2=15, head_y2=30, head_x3=15,head_y3=40, head_x4=5,head_y4=40;
// shape
GLuint listID;
void MrRobot(GLsizei displayListID)
{
glNewList(displayListID,GL_COMPILE);
//Save current colour state
glPushAttrib(GL_CURRENT_BIT);
// body
glColor3f(0.5,0.5,0.5);
glBegin(GL_POLYGON);
glVertex2f(0,10);
glVertex2f(20,10);
glVertex2f(20,30);
glVertex2f(0,30);
glEnd();
// head
glColor3f(0,0,1);
glBegin(GL_POLYGON);
glVertex2f(head_x1,head_y1);
glVertex2f(head_x2,head_y2);
glVertex2f(head_x3,head_y3);
glVertex2f(head_x4,head_y4);
glEnd();
// legs
glColor3f(1,0,0);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(10,10);
glVertex2f(20,0);
glVertex2f(10,-5);
glVertex2f(0,0);
glEnd();
// right hand
glColor3f(0,1,0);
glBegin(GL_TRIANGLES);
glVertex2f(20,30);
glVertex2f(30,27.5);
glVertex2f(20,25);
glEnd();
// left hand
glColor3f(0,1,0);
glBegin(GL_TRIANGLES);
glVertex2f(-10,27.5);
glVertex2f(0,30);
glVertex2f(0,25);
glEnd();
//Recall saved colour state
glPopAttrib();
glEndList();
}
void display()
{
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,0,0);
//Defining a modelview transform matrix
glScalef(0.3,0.3,0.3);
//Execute the display list (the modelview matrix will be applied)
glCallList(listID);
glFlush();
}
void keyboard(unsigned char key,int x, int y)
{
printf("\nKeyboard event detected. \nCharacter key: %c\nMouse pointer position: x=%d y=%d",key,x,y);
if (key==GLUT_KEY_UP)
{
head_y1++;
head_y2++;
head_y3++;
head_y4++;
}
if (key==GLUT_KEY_DOWN)
{
head_y1--;
head_y2--;
head_y3--;
head_y4--;
}
if (key==GLUT_KEY_LEFT)
{
head_x1--;
head_x2--;
head_x3--;
head_x4--;
}
if (key==GLUT_KEY_RIGHT)
{
head_x1++;
head_x2++;
head_x3++;
head_x4++;
}
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitWindowPosition(50,50);
glutInitWindowSize(800,600);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutCreateWindow("Mr Robot");
glMatrixMode(GL_PROJECTION);
gluOrtho2D(-5,35,-5,30);
listID=glGenLists(1);
MrRobot(listID);
glutDisplayFunc(display);
glutSpecialFunc(keyboard);
glutMainLoop();
return 0;
}
Maybe is something with the axis, but have no idea what I should change.
Any help?
Well there are a lot of problems. You seem to be writing OpenGL a little bit differently.
Anyways here is the problem.
The reason its scaling is because everytime you call display you are calling glScalef(0.3, 0.3, 0.3); without loading the identity matrix.
Also when you press a key the increment is happening but you havent even called MrRobot() in the display function. You have only called it once in the main function
Also just before you call display you must call glMatrixMode(GL_MODELVIEW); or else all transformations you do will affect the GL_PROJECTION matrix

What could cause polygons in OpenGL to be rendered out of order?

I'm trying to get some hands-on experience with OpenGL so I've been writing a few basic programs. The short program below is my first attempt at rendering a solid object --a rotating cube-- but for some reason some back polygons seem to be getting drawn over front polygons. My question is what could cause this? Does it have something to do with the depth buffer? I've found that enabling face culling will hide the effect in this case, but why should that be necessary? Shouldn't a face which is occluded by a nearer face be hidden regardless?
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
typedef struct{
int width;
int height;
char * title;
} window;
window win;
float theta = 0;
const float rotRate = 0.05;//complete rotations per second
int lastTime;
const float verts[][3] = {
{0.0,0.0,0.0},
{1.0,0.0,0.0},
{0.0,1.0,0.0},
{0.0,0.0,1.0},
{0.0,1.0,1.0},
{1.0,0.0,1.0},
{1.0,1.0,0.0},
{1.0,1.0,1.0}};
const int faceIndices[][4] = {
{3,5,7,4},//front
{1,0,2,6},//back
{4,7,6,2},//top
{0,1,5,3},//bottom
{5,1,6,7},//right
{0,3,4,2}};//left
void display(){
//timing and rotation
int currentTime = glutGet(GLUT_ELAPSED_TIME);
int dt = lastTime - currentTime;
lastTime = currentTime;
theta += (float)dt/1000.0*rotRate*360.0;
if (theta > 360.0) theta += -360.0;
//draw
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -5.0);
glRotatef(theta, 0.0, 1.0, 0.0);
glTranslatef(-1.0,-1.0,-1.0);
glScalef(2.0, 2.0, 2.0);
int f;
for(f=0; f<6;f++){
glBegin(GL_POLYGON);
int v;
for(v=0; v<4; v++){
glColor3fv(verts[faceIndices[f][v]]);
glVertex3fv(verts[faceIndices[f][v]]);
}
glEnd();
}
glutSwapBuffers();
}
void initializeGLUT(int * argc, char ** argv){
glutInit(argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(win.width, win.height);
glutCreateWindow("OpenGL Cube");
glutDisplayFunc(display);
glutIdleFunc(display);
}
void initializeGL(){
//Setup Viewport matrix
glViewport(0,0,win.width, win.height);
//Setup Projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45,(float) win.width/win.height, 0.1, 100.0);
//Initialize Modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Other
glClearColor(0.0, 0.0, 0.0, 0.0);
glClearDepth(1.0);
}
int main(int argc, char** argv){
win.width = 640;
win.height = 480;
initializeGLUT(&argc, argv);
initializeGL();
glutMainLoop();
return 0;
}
Does it have something to do with the depth buffer?
Yes, this is a depth buffer issue, you enabled depth buffer in your code, but obviously you lost some steps, to use depth buffer
Enable depth test by calling glEnable(GL_DEPTH_TEST)
Set the depth test function by glDepthFunc, GL_LEQUAL is the recommended choice for most case, glDepthFunc(GL_LEQUAL); the default value is GL_LESS.
Call glClearDepth to set the cleared value, the initial value is 1.0, this step is not mandatory if you want the default value.
Don't forgot to clear the depth bit before drawing, glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
I've found that enabling face culling will hide the effect in this
case, but why should that be necessary?
By default, OpenGL does't cull any face, the recommend option is
Define vertices in Clock Wise order as back face(this is also OpenGL's choice)
Cull back faces when necessary.
In your case, you defined the polygon vertices all in CCW order, so they are all front faces by default, you just need to cull the back-faces to prevent them from drawing, so the following code also solves your problem.
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
Shouldn't a face which is occluded by a nearer face be hidden
regardless?
Yes, that make sense as we are human being, but for the computer, it's your responsibility to tell it how to do that.
References:
Depth buffer
Face culling

opengl animations slow down when window size is increased

In many OpenGL tutorials, e.g. swiftless tutorials and many others, whenever there is an animation in the scene and the window is resized, the speed of the animation changes.
Description of strange behaviour
when the window is small, the animation speeds upwhen the window is large the animation slows downIs there an explanation for this?
#include <GL/glew.h> // Include the GLEW header file
#include <GL/glut.h> // Include the GLUT header file
bool* keyStates = new bool[256]; // Create an array of boolean values of length 256 (0-255)
bool movingUp = false; // Whether or not we are moving up or down
float yLocation = 0.0f; // Keep track of our position on the y axis.
float yRotationAngle = 0.0f; // The angle of rotation for our object
void keyOperations (void) {
if (keyStates[GLUT_KEY_LEFT]) { // If the left arrow key has been pressed
// Perform left arrow key operations
}
}
void display (void) {
keyOperations();
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our <a title="window" href="http://www.swiftless.com/tutorials/opengl/window.html">window</a> to red
glClear(GL_COLOR_BUFFER_BIT); //Clear the colour buffer (more buffers later on)
glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations
glTranslatef(0.0f, 0.0f, -5.0f); // Push eveything 5 units back into the scene, otherwise we won't see the primitive
glTranslatef(0.0f, yLocation, 0.0f); // Translate our object along the y axis
glRotatef(yRotationAngle, 0.0f, 1.0f, 0.0f); // Rotate our object around the y axis
glutWireCube(2.0f); // Render the primitive
glFlush(); // Flush the OpenGL buffers to the window
if (movingUp) // If we are moving up
yLocation -= 0.005f; // Move up along our yLocation
else // Otherwise
yLocation += 0.005f; // Move down along our yLocation
if (yLocation < -3.0f) // If we have gone up too far
movingUp = false; // Reverse our direction so we are moving down
else if (yLocation > 3.0f) // Else if we have gone down too far
movingUp = true; // Reverse our direction so we are moving up
yRotationAngle += 0.005f; // Increment our rotation value
if (yRotationAngle > 360.0f) // If we have rotated beyond 360 degrees (a full rotation)
yRotationAngle -= 360.0f; // Subtract 360 degrees off of our rotation
}
void reshape (int width, int height) {
glViewport(0, 0, (GLsizei)width, (GLsizei)height); // Set our viewport to the size of our window
glMatrixMode(GL_PROJECTION); // Switch to the projection matrix so that we can manipulate how our scene is viewed
glLoadIdentity(); // Reset the projection matrix to the identity matrix so that we don't get any artifacts (cleaning up)
gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes
glMatrixMode(GL_MODELVIEW); // Switch back to the model view matrix, so that we can start drawing shapes correctly
}
void keyPressed (unsigned char key, int x, int y) {
keyStates[key] = true; // Set the state of the current key to pressed
}
void keyUp (unsigned char key, int x, int y) {
keyStates[key] = false; // Set the state of the current key to not pressed
}
int main (int argc, char **argv) {
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode (GLUT_SINGLE); // Set up a basic display buffer (only single buffered for now)
glutInitWindowSize (500, 500); // Set the width and height of the window
glutInitWindowPosition (100, 100); // Set the position of the window
glutCreateWindow ("You’re first OpenGL Window"); // Set the title for the window
glutDisplayFunc(display); // Tell GLUT to use the method "display" for rendering
glutIdleFunc(display); // Tell GLUT to use the method "display" as our idle method as well
glutReshapeFunc(reshape); // Tell GLUT to use the method "reshape" for reshaping
glutKeyboardFunc(keyPressed); // Tell GLUT to use the method "keyPressed" for key presses
glutKeyboardUpFunc(keyUp); // Tell GLUT to use the method "keyUp" for key up events
glutMainLoop(); // Enter GLUT's main loop
}
The way this is written it uses an "as fast as possible" rendering approach. This, together with V-Sync disabled will make the animation speed depend on the time it takes to calculate the pixels of one frame. The larger the window, the more pixels there are to fill (look up the keyword fillrate).
The solution is, to measure the time between rendering frames and advance the animation by this.

Resources