OpenGL: Multiple Overlapping Viewports Flickering - c++

I am trying to create two viewports in my window: a main, full screen view and a smaller view in the upper left corner. I've looked the issue up and looked at the solutions: I am using glScissor() and glViewport(), clearing my depth buffer bit, enabling my depth buffer bit, and rendering only once (after a for loop). But clearly, I am missing something. Here is my code. Thank you in advance.
Edit:
link to screenshots: http://imgur[dot]com/a/sdoUy
Basically, the upper left mini viewport flickers, disappearing and reappearing very quickly.
void viewports() {
float width = wWidth;
float height = wHeight;
for (int i = 0; i < 2; i++) {
glClearColor(.392,.584,.929,0.0f);
if (i == 0) {
//main view
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0,0,(GLsizei)width,(GLsizei)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(GLfloat)width/(GLfloat)height,1.0,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
keyOp();
camera();
} else if (i == 1) {
glScissor(0,height - height/3,(GLsizei)height/3,(GLsizei)height/3);
glEnable(GL_SCISSOR_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glViewport(0,height - height/3,(GLsizei)height/3,(GLsizei)height/3);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,1,1.0,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,40,-15,0,-1,-15,1,0,0);
glDisable(GL_SCISSOR_TEST);
}
renderScene();
}
}

Don't call glutSwapBuffers in renderscene. You call renderscene twice per frame (for i==0 and i==1), so you're drawing main screen, swap, draw minimap, swap, repeat.
You need to draw both main and minimap, and then swap.
Also don't bother calling glClearColor so many times, you only need to call it once at init.

Not sure if it will help with your flickering problem but I notice you have written:
glClearColor(.392,.584,929,0.0f);
With the third parameter being 929 instead of what I assume you wanted, .929

Related

Line get duplicated instead of moved

I'm using qWidget which inherits QGLWidget and below the widget I have 2 buttons.
button1: +
button2: -
this is my code:
void GLWidget::paintGL() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,_w,0,_h,-1,1);
glViewport(_camera_pos_x,0,_w,_h);
glBegin(GL_LINES);
glVertex2i(50,50);
glVertex2i(200,200);
glEnd();
update();
}
I want each time I'm pressing the + button, the screen will move 10 pixels to the right which means the line should move to the left by 10 pixels.
This is the code when im pressing the button:
void right() {_camera_pos_x += 10;}
_camera_pos_X is just a member int which is initialized to 0.
When I'm pressing the button another line is rendered 10 pixels to the right and I see 2 lines
What's wrong with my code?
By the way, I think im using old code of OpenGL, is there a better way to render a line?
First of all note, that drawing with glBegin/glEnd sequences is deprecated since more than 10 years.
Read about Fixed Function Pipeline and see Vertex Specification for a state of the art way of rendering.
glViewport specifies the transformation from normalized device coordinates to window coordinates. If you want to change the position of the line, then you have to draw the line at a different position, but that doesn't change the size of the viewport. Keep your viewport as large as the window:
glViewport(0, 0, _w, _h);
The default frame buffer is never cleared, so the rendering is always drawn on the rendering of the previous frames. Because of that, you can "see 2 lines". Use glClear to clear the framebuffer at the begine of the rendering:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Change the model view matrix to set the positon of the line:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,_w,0,_h,-1,1);
glViewport(0, 0, _w, _h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(_camera_pos_x, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_LINES);
glVertex2i(50,50);
glVertex2i(200,200);
glEnd();
You must clear the old contents of the framebuffer, before drawing the new image. Put a glClear(GL_COLOR_BUFFER_BIT) at the beginning of paintGL().

OpenGL Triangle rotation

I drew a triangle and i want to rotate it on X-Axis continuously. Below code is rotating it for couple of times.
//Paints the GL scene
void GLobj::paintGL(void)
{
static int angle;
for (angle = 1; angle<=360; angle += 1)
{
glClear (GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glRotatef(angle, 1, 0 , 0);
glBegin(GL_TRIANGLES);
glColor3f (1.0, 0.0,1.0);
glVertex2f(-0.45,0.0);
glVertex2f(-0.65,0.5);
glVertex2f(-0.25,0.5);
glEnd();
usleep(1000);
glFlush ();
}
If i change the above code as below, output is just busy in executing and not displaying anything.
//Paints the GL scene
void GLobj::paintGL(void)
{
static int angle;
for (angle = 1; angle<=360; angle += 1)
{
glClear (GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glRotatef(angle, 1, 0 , 0);
glBegin(GL_TRIANGLES);
glColor3f (1.0, 0.0,1.0);
glVertex2f(-0.45,0.0);
glVertex2f(-0.65,0.5);
glVertex2f(-0.25,0.5);
glEnd();
usleep(1000);
if (angle == 360)
{angle = 1;}
}
glFlush ();
}
Is there any other better way of implementing continuous rotation?
Most graphic APIs like OpenGL and DirectX write all changes into something called back buffer: The operations are only displayed once you have rendered your complete scene. If each rotation step or glEnd() rendered immediately, you would always see your scene building up each time. The result would be flickering which is not nice to see.
You can tell OpenGL when you have finished drawing your scene, so that everything can be displayed at once. You do this with glFlush.
In your second example, you conduct a rotation and another one and yet another one... at the very end you display your final scene once. The nice transition of your triangle through the rotation phases is not rendered.

Drawing hour marks of a clock using OpenGL

here is my code:
void drawClock(void)
{
glClearColor(1.0,1.0,1.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0,0.0,0.0);
for(int i=0; i<12; i++){
glRotatef(30,0,0,1);
glTranslatef(5.2,0.0,0.0);
glutWireCube(2.0);
}
glFlush();
}
Here is my reshape function (without it I don't see anything, although I'm not sure how it really works)
void changeSize(int w, int h) {
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0) h = 1;
float ratio = 1.0* w / h;
// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set the viewport to be the entire window
glViewport(0, 0, w, h);
// Set the correct perspective.
gluPerspective(45,ratio,1,1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,70.0,
0.0,0.0,-1.0,
0.0f,1.0f,0.0f);
}
So I am trying to draw the hour marks of a clock using wire cubes of size 2.0, and each of these cubes must be 5.2 units away from the center. This is for an assignment, I know it is probably very simple but I just can't manage to make it work properly. My problem is that the cubes appear in 3D, but I want them to appear in 2D, as in I would only see one face. Also, the circle is not centered, I do not understand why. I know I am supposed to use pushMatrix and popMatrix but no matter how I use it it doesn't work.
3d Problem
gluPerspective makes a perspective projection. To accomplish what you need you should apply an orthographic projection instead.
The best way to do this with your current code is to us glOrtho to provide a left, right, bottom, top, far,near box within which everything will 'appear' 2D. Try the code below in place of gluPerspective.
glOrtho(10.0f,-10.0f,10.0f,-10.0f,10.0f,-10.0f,10.0f);
Position problem
I'm not so sure about the transformation as I've not used immediate mode for a while. Note the order of operations makes a difference.
As for the push/pop of matrices, it is basically a stack of 4x4 matrices detailing the transformations. I'm sure it works along the lines of
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslate(x,y,z);// Where x,y,z is the starting point of your clock
for(int i=0; i<12; i++){
glPushMatrix();
glRotatef(i * 30,0,0,1);
glTranslatef(5.2,0.0,0.0);
glutWireCube(2.0);
glPopMatrix();
}

OpenGL does not update the drawview

I have the following drawScene function which draws a sphere. The coords of X,Y are being updated all the time. As far as I can see from the printf the values changed for sure.
The problem is that the sphere does not change position according to the coords but is always drawn at the same place...
void drawScene(void){
//Clear information from last draw
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective
glColor3d(1,0,0);
//glPushMatrix();///
glTranslated(X,Y,-7);//xyz//(X%5)-2.5,Y%5//(((X%6)-3),0,-7)
printf("\n\n\nCOORDS(X)%d (Y):%d\n\n\n\n",X,Y);
glutSolidSphere(0.3, 25, 20);//3,20,20
//glPopMatrix();///
glutSwapBuffers(); //Send the 3D scene to the screen
}
PS. I am not sure if this is right but every time I want my openGL window to be updated I call the drawScene() or else it is drawn only once.
Either call glutPostRedisplay() when you update the X and Y or enable the idleFunc like this:
void idle()
{
glutPostRedisplay();
}
and add this in your main:
glutIdleFunc(idle);

Display object in just a certain viewport

Hi I got 4 viewports and one large that I can switch between now I got an object namely the camera and the cameras target position that I show with rendering a sphere at those locations. I want to show the cameras position in 3 of my viewports but not in the last which is the camera display but at the moment I got an all or nothing scenario.
void display(int what)
{
if(what==5){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camControll();}
if(what==1){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(75,15,-5,0,5,-5,0,1,0);}
if(what==2){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,110,0,0,0,0,1,0,0);}
if(what==3){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, float(320) / float(240), 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camControll();}
if(what==4){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(185,75,25,0,28,0,0,1,0);}
//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();
////gluLookAt(cos(shared.time) * shared.distance, 10, sin(shared.time) * shared.distance, 0, 0, 0, 0, 1, 0);
////ca.orbitYaw(0.05);
//ca.lookAt();
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
drawScene(); // scene that all views should render
drawCamera(); / camera position that only certain views should render
glutSwapBuffers();
}
I'm thinking that perhaps I could do one sweep for first the 3 viewports and then call glutSwapBuffers() and then do the other viewport without the camera position but some stuttering I previously had was traced to glutSwapBuffers() being called for each viewport so I guess there has to be another way only that I cant figure it out.
You have to render everything before swapping buffers.
As you do it - it is not going to work. Actually, it will work, but not you want.
EDIT
To render to a texture take a look into one of the links here.
After changing a view, render the image for the specific view to a texture. Then for the final image, set the final view and render all 3 textures. Only when the final image is rendered, swap buffers.
On the 2nd thought, it would be much better if you could set the vertices of all objects to render and render whole image in one pass.