SDL2 + OpenGL colored geometry - c++

I want to use OpenGL to draw on top of a webcam stream. I'm using an SDL_Surface named screen_surface_ containing webcam data, that I'm rendering to the screen using (1):
SDL_UpdateTexture(screen_texture_, NULL, screen_surface_->pixels, screen_surface_->pitch);
SDL_RenderClear(renderer_);
SDL_RenderCopy(renderer_, screen_texture_, NULL, NULL);
Then I try to draw some geometry on top:
glLoadIdentity();
glColor3f(1.0, 0.0, 1.0);
glBegin( GL_QUADS );
glVertex3f( 10.0f, 50.0f, 0.0f ); /* Top Left */
glVertex3f( 50.0f, 50.0f, 0.0f ); /* Top Right */
glVertex3f( 50.0f, 10.0f, 0.0f ); /* Bottom Right */
glVertex3f( 10.0f, 10.0f, 0.0f ); /* Bottom Left */
glEnd( );
glColor3f(1.0, 1.0, 1.0); //<- I need this to make sure the webcam stream isn't pink?
SDL_RenderPresent(renderer_);
I have initialized OpenGL using (excerpt):
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glViewport( 0, 0, res_width_, res_height_ );
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho(0.0f, res_width_, res_height_, 0.0f, -1.0f, 1.0f);
Subquestion: If I don't reset the glColor to white the whole webcam stream is colored pink. I find this odd, because I thought that SDl_RenderCopy had already rendered that texture before the first call to glColor. So how does SDL_RenderCopy actually work?
Main question: I get a neat 40x40 square in the top left of the screen on top of my webcam feed (good!). However, in stead of pink, it is a kind of flickering dark purple color; seemingly dependent on the camera feed in the background. Could you please tell me what I'm overlooking?
Edit:
As per #rodrigo's comment, these are some images with the color set to R, G, B and white, respectively:
Red Square
Green Square
Blue Square
White Square
Looking at these, it seems that the underlying texture has some effect on the color. Could it be that OpenGL is still applying (some part of) the texture to the quad?
Edit:
I suspect now that the geometry is drawn using the render texture as a texture, even though I've called glDisable(GL_TEXTURE_2D). Looking at the "White Square" screenshot (below), you can see that the white quad is the same color as the bottom-right pixel. I guess that the quad has no texture coordinates, so only the bottom-right texel is used. Knowing this, better question: how do I disable texturing?.

I have fixed the problem by simply adding
glcontext_ = SDL_GL_CreateContext(window_);
to the SDL_Init code. I think all my calls to openGL functions (like glDisable(GL_TEXTURE_2D) were applied to the wrong context. Explicitly creating a context from SDL sets the right context to be active, I'm guessing.
Something else to look out for: when using textured geometry after using SDL_RenderCopy; I had to make sure to reset
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
before calling glTexImage2d, because it uses
GL_UNPACK_ROW_LENGTH if it is greater than 0, the width argument to the pixel routine otherwise
(from the OpenGL docs)

Related

How to set pixel coordinates?

Is it possible to draw something in OpenGL on the drawing scene with giving window pixel coordinates?
For example, I'd like to draw a single point in a 400x400 window (e.g. in the middle of that window). Is there any quick way to set everything up so I could just type:
glVertex3f(200.0 , 200.0 , 1.0);?
You need to set up an orthogonal projection matrix for that first.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0.0f, WindowWidth, WindowHeight, 0.0f, 0.0f, 10.0f);
glMatrixMode(GL_MODELVIEW);
You can then render in window coordinates.
glPointSize(5.0f);
glBegin(GL_POINTS);
glVertex3f(100.0f, 100.0f, 1.0f);
glEnd();
Should render a point with a diameter of 5 pixels on window coordinates [100, 100]
Do note that this old way of rendering is deprecated and you should use VBOs and the like, but it is still good for testing.

qt + open Gl= paintgl function for drawing a triangle

i have coded what i have read in previous post about a well known subject but i continue to get a green window without any triangle inside.
Here is my paint function :
void mGLWidget::paintGL()
{
glClearColor( Qt::green );
QSize viewport_size = size();
glViewport(0, 0, viewport_size.width(), viewport_size.height());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1, 1, -1, 1, 5, 7); // near and far match your triangle Z distance
glMatrixMode(GL_MODELVIEW);
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
glColor4f( 1.0, 1.0, 1.0, 1.0 );
glTranslatef(-1.5f,0.0f,-15.0f);
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glEnd();
// Finished Drawing The Triangle
// swapBuffers();
}
I only get a green window without any triangle. My QT is qt4.8 and opengl 4.0.
What am I doing wrong ?-\
your near and far value for your glfrustrum is quite a small range, make it 1, 100 instead of 5, 7. might not be the actual solution but it will help if its not
Your near and far value is small and you are translating the triangle very far by -15f unit that means your triangle is not draw or act as a point. So you only see the window color.

gl_lines and gl_clear in QGLWidget

I got a problem with drawing on a QGLWidget. I have several quads on the widget which I can move around when pressing some keys. As long as I just draw quads, everything works fine but now I want to add some lines using:
glBegin(GL_LINE);
glColor3f(c[0], c[1], c[2]);
glVertex3f(v1.x, v1.y, v1.z);
glVertex3f(v2.x, v2.y, v2.z);
glEnd;
The drawing also works fine, but the clearing of the glwidget doesn't work anymore. Means that I see everything I ever drawed on it. Just to mention.
I tried the same with GLUT using the same initializations and it worked, but since I have switched to Qt it doesn't work anymore.
paintGL(), resizeGL() and initializeGL() are below.
void GLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0f, 0.0f, 0.0f, 0.0f, -10.0f, -20.0f, 0.0f, 20.0f, -10.0f);
glTranslatef(0.0f, -30.0f, -40.0f);
glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
glRotatef(s_deg, 0.0f, 0.0f, 1.0f);
glRotatef(s_deg2, cos(DEGRAD(s_deg)), sin(DEGRAD(s_deg)), 0.0f);
float colors[8][3] = {
0.5, 0.0, 0.0,
0.0, 0.5, 0.0,
0.0, 0.0, 0.5,
1.0, 0.5, 0.5,
0.5, 1.0, 0.5,
0.5, 0.5, 1.0,
0.9, 0.9, 0.9,
0.1, 0.1, 0.1,
}; //red, green, blue, red shiny, green shiny, blue shine, light grey, dark grey
for(int i=0;i<glBoxes.size();i++) {
glBoxes.at(i).setColor(colors[i]);
glBoxes.at(i).drawCuboid();
glBoxes.at(i).drawCuboidGrid();
}
}
void GLWidget::initializeGL() {
glDepthFunc(GL_LESS);
glClearColor(0.2, 0.2, 0.2, 0.2);
glClearDepth(1.0);
}
void GLWidget::resizeGL(int width, int height) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0.0f, 0.0f, (float)width, (float)height);
glLoadIdentity();
gluPerspective(45.0f, (float)width/(float)height, 0.5f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}
any Ideas?
The tokens accepted by glBegin are
GL_POINTS
GL_LINES
GL_TRIANGLES
GL_TRIANGLE_FAN
GL_TRIANGLE_STRIP
GL_QUADS
GL_QUAD_STRIP
and
GL_POLYGON
The token used by you, GL_LINE (not the missing trailing S) is not valid for glBegin.
The statement glEnd; will evaluate the address of the function glEnd and silently discard the result. Could it be, that you have a Pascal or Delphi background? In C like languages you have to add a matched pair of parentheses to make it a function call. Functions that don't take a parameter are called with an empty pair of parentheses. E.g. in your case glEnd();.
Not related to your problem. All of the code in resizeGL should go to the head of paintGL (use the widget's width() and height() getters). Also what you have in initializeGL belongs to paintGL.
The proper use of initializeGL is to do one-time initialization, like loading textures, and shaders, preparing FBOs and such.
resizeGL is meant to re-/initialize stuff that depends on the window's size and which is quite time consuming to change, like renderbuffers and/or textures used as attachment in FBOs used for window sized post-processing or similar. Setting the projection matrix does not belong there, and neither does the viewport. Those go into paintGL.
glDepthFunc, glClearColor and glClearDepth directly influence the drawing process and as such belong with the drawing code.
Also you should not use the immediate mode (glBegin … glEnd) at all. It's been outdated ever since OpenGL-1.1 was released over 15 years ago. Use Vertex Arrays, with the possible addition of Buffer Objects.
glEnd; should be glEnd();. This may actually fix your problem.
GL_LINE isn't a valid token for glBegin. To draw lines, you need GL_LINES (that's subtle, and you're in good company - this is a common mistake).
GL_LINE is used to control how polygons are rendered, which is controlled by the glPolygonMode function.
It must be GL_LINES instead of GL_LINE. The symbols accepted by glBegin are plural (i.e. GL_QUADS, GL_LINE_STRIPS...).

glColor coloring all textures

I'm fairly new to OpenGL so maybe the answer will be obvious. I am currently trying to make a blue circle using GL_TRIANGLE_FAN in C++. My problem is that when I set the color using glColor4f, it sets all my other textures to have a blue color over them such as shown below (this is supposed to be silvery metal).
I draw the textures using the method shown below.
glLoadIdentity();
glTranslatef(x,y,0);
glBindTexture(GL_TEXTURE_2D, this->texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0,0,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width,0,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width,height,0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0,height,0);
glEnd();
I'm not sure whether I just have to clear a flag for it to work, but I've been stuck for a few days now.
After drawing your blue circle, you should set the color back to white (default value) using glColor4f(1.f, 1.f, 1.f, 1.f);. Please note that by default the texture gets modulated by the currently set color (blue in your case) and that's the reason why your silver material gets a bluish tone (final color = blue color * texture color).
Unbind the texture and set the color back to white after you're done drawing:
glLoadIdentity();
glTranslatef(x,y,0);
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, this->texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0,0,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width,0,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width,height,0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0,height,0);
glEnd();
glColor4f(1, 1, 1, 1);
glBindTexture(GL_TEXTURE_2D, 0);
And if you aren't rendering textures on the next object, disable texturing:
glDisable( GL_TEXTURE_2D );
When You have enabled glEnable(GL_COLOR_MATERIAL) and changed a color by glColor, then all your textures will be affected by this color. This is because by default the texture is displayed in modulate mode (glColor multiplied by texture colors).
If you don't have lighting enabled, to restore the original texture color is simple - just set glColor to white: glColor4f(1.0, 1.0, 1.0, 1.0).
The problem comes, when you have lighting enabled on your texture. Then, setting the color to white or changing texture mode to REPLACE doesn't help at all - your lighting effects will be removed! (which nobody seems to be noticing!) The reason for this is because with enabling GL_COLOR_MATERIAL by default you're getting behaviour, where glColor commands changes both Ambient and Diffuse colours at the same time - thus your ambient and diffuse material properties will be affected (lost). So all you have to do, to restore the material state (and thus lighting effects), which you had before applying glEnable(GL_COLOR_MATERIAL), is the following:
glDisable(GL_COLOR_MATERIAL); //disable color influence
GLfloat ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f }; //default material has this ambient color!
GLfloat diffuse[] = { 0.8f ,0.8f ,0.8f, 1.0f }; //default material has this diffuse color!
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient); //restore default material ambient color
glMaterialfv(GL_FRONT, GL_AMBIENT, diffuse); //restore default material diffuse color
Please note, what are the default ambient and diffuse colors for default material! There is no pure white there!
This way, all the textures, that you use from this point will be drawn as intended (with the correct color and lighting effects).
Took me some time to find this stuff, so I suppose it's nice to mention it here.
Before binding a texture, you need to enable it. And normally, you should disabled it when you are done with it. Something like this :
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, this->texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0,0,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width,0,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width,height,0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0,height,0);
glEnd();
glDisable( GL_TEXTURE_2D );

OpenGL bitmap text fails after drawing polygon

I'm using Win32 and OpenGL to to draw text onto a window. I'm using the bitmap font method, with wglUseFontBitmaps. Here is my main rendering function:
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glColor3f(1.0f, 0.0f, 1.0f);
glBegin(GL_QUADS);
glVertex2f(0.0f, 0.0f);
glVertex2f(128.0f, 0.0f);
glVertex2f(128.0f, 128.0f);
glVertex2f(0.0f, 128.0f);
glEnd();
glPopMatrix();
glPushMatrix();
glColor3f(1.0f, 1.0f, 1.0f);
glRasterPos2i(200, 200);
glListBase(fontList);
glCallLists(5, GL_UNSIGNED_BYTE, "Test.");
glPopMatrix();
SwapBuffers(hDC);
As you can see it's very simple and the only thing that it's supposed to do is draw a quadrilateral and draw the text "Test.". But the problem is that drawing a polygon seems to mess up any text operations I try to do after it. If I place the text drawing functions before the polygon, both the text and the polygon draw fine. Is there something I'm missing here?
Edit: This problem only happens when the window is run in Fullscreen, by ChangeDisplaySettings. Any reason why this would be??
I know this might be a very late reply but I came across this question looking for answers to this exact problem. The way I attempted to draw text over a polygon is slightly different. I have a method that looked like this:
glClear( GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
glRasterPos2f( pX, pY );
glPushAttrib( GL_LIST_BIT );
glListBase( base - 32 );
glCallLists( length( pText ), GL_UNSIGNED_BYTE, PChar( pText ) );
glPopAttrib();
I tried drawing a polygon and text over it like this:
glPushMatrix();
glBegin(GL_QUADS);
glColor( 1.0, 0.0, 0.0 );
glVertex2f( fX, fY );
glVertex2f( fX + fWidth, fY );
glVertex2f( fX + fWidth, fY + fHeight );
glVertex2f( fX, fY + fHeight );
glEnd( );
glColor( 0.0, 1.0, 0.0 );
Text( 100, 100, fCaption );
glPopMatrix();
But, similar to your problem, only the text would draw or in some case (after moving the Text method around a bit) nothing would draw at all. I realized that the method had
glClear( GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT );
which OBVIOUSLY cleared the buffer after I drew the polygon and before I drew the text... This was such a silly mistake and although I have failed to recognize any similar code in the code you have provided, it may be somewhere else. Either way this bit of code will help you if you just clear the glClear method from the Text method. Hope this helps or might help other people who are in a similar situation.