Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Want an OpenGL 2D example (VC++, draw a rectangle)

Tags:

opengl

2d

I want to create a high performace 2D program.

I'm using VC++2008. Suppose I have created the main window. What I want is to draw a red rectangle (top left: 10,20, bottom right: 200, 300) in the main window's client area like what FillRect() API does but using OpenGL.

void InitOpenGL(HWND hwnd)
{
.... // What should I do?
     // Only for 2D drawing, and the (0,0) should be the top left point.
}

// the function below will be called in the WM_PAINT handler
void DrawRectWithOpenGL(RECT* pRect)
{
.... // What should I do?
}

EDIT1: Does OpenGL have a 2D drawing API or lib like Direct2D/DirectWrite?

like image 678
Zach Avatar asked May 04 '11 02:05

Zach


2 Answers

I strongly suggest you take a look at some OpenGL tutorials (http://nehe.gamedev.net/ is a good site, it'll tell you everything you need to know), but assuming you have OpenGL set up correctly in your code, you'd do something like this in your DrawRectWithOpenGL function (I'm not a C++ programmer but I think my code looks right for C++):

void DrawRectWithOpenGL(RECT* pRect)
{
  glPushMatrix();  //Make sure our transformations don't affect any other transformations in other code
    glTranslatef(pRect->x, pRect->y, 0.0f);  //Translate rectangle to its assigned x and y position
    //Put other transformations here
    glBegin(GL_QUADS);   //We want to draw a quad, i.e. shape with four sides
      glColor3f(1, 0, 0); //Set the colour to red 
      glVertex2f(0, 0);            //Draw the four corners of the rectangle
      glVertex2f(0, pRect->h);
      glVertex2f(pRect->w, pRect->h);
      glVertex2f(pRect->w, 0);       
    glEnd();
  glPopMatrix();
}

OpenGL doesn't have a 2D drawing API but its easy to do 2D things by just ignoring the Z axis (or just using the Z axis for making sure that sprites are drawn at the correct depth, i.e. so you can draw the background after the foreground because the background's depth is set so it lies behind the foreground). Hope this helps. Definitely take the time to look at some tutorials and it will all become clear.

EDIT: For setting up OpenGL for 2D drawing, you need to set up an orthographic projection (the tutorials that I linked to uses perspecive projection, sorry for not mentioning that). Here's an example of some of my code that does this (which should be somewhere in your InitOpenGL function, after you have created your window):

glClearColor(0.0, 0.0, 0.0, 0.0);  //Set the cleared screen colour to black
glViewport(0, 0, screenwidth, screenheight);   //This sets up the viewport so that the coordinates (0, 0) are at the top left of the window

//Set up the orthographic projection so that coordinates (0, 0) are in the top left
//and the minimum and maximum depth is -10 and 10. To enable depth just put in
//glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, screenwidth, screenheight, 0, -10, 10);

//Back to the modelview so we can draw stuff 
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); //Clear the screen and depth buffer

So that's the initialisation sorted. You should be able to use values like 100 and 200 and have them appear correctly on the screen, i.e. the coordinates are in pixels.

To handle window size changes, what you would do is find the size of the window (using an external library. I'm not sure you can do it in OpenGL, although glutGet(GLUT_WINDOW_WIDTH) and glutGet(GLUT_WINDOW_HEIGHT) from GLUT might work, but I haven't tested it), and then call glViewport and glOrtho again with the updated window size.

Again, you'd have to use an external library to find out exactly when the window size changes. I'm not sure what you could use, although if you happen to be using SDL then that might have some event handling for it (and may be able to return the screen width and height, if glutGet doesn't work).

I hope this helps!

like image 146
SuperMaximo93 Avatar answered Nov 15 '22 09:11

SuperMaximo93


Thank SuperMaximo93. I fininally got my code to work. Here is my code on window's size is changed. The function below is called in WM_SIZE's handler.

void OpenGlWindow::Resize(HWND hwnd)
{
    // Get new window size
    RECT rect;
    int width, height;

    GetClientRect(hwnd, &rect);
    width = rect.right;
    height = rect.bottom;

    glClearColor(0.0, 0.0, 0.0, 0.0);  //Set the cleared screen colour to black
    glViewport(0, 0, width, height);   //This sets up the viewport so that the coordinates (0, 0) are at the top left of the window

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    //Back to the modelview so we can draw stuff 
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glRotatef(180, 1.0f, 0, 0);
    glTranslatef(-1.0f, -1.0f, 0);
    glScalef(2.0f/width, 2.0f/height, 1);

    glTranslatef(2.0f, 2.0f, 0);
}
like image 30
Zach Avatar answered Nov 15 '22 09:11

Zach