OpenGL Tutorials for Absolute Beginners

Discussion in 'C' started by Trinity, Dec 18, 2011.

  1. Trinity

    Trinity New Member

    Joined:
    Nov 23, 2011
    Messages:
    28
    Likes Received:
    11
    Trophy Points:
    3
    Occupation:
    Software Engineer

    What is OpenGL?



    OpenGL is a set of standard API's for developing 2D and 3D graphics applications. The standard provides it in the form of a library which can be linked along wih your program (could be C/C++). OpenGL includes vast scope of API's which can be used to render figures, textures, shading, etc. The man pages are available along with openGL SDK documentation.

    Getting Started With OpenGL



    As such, there is lot more to discuss when we talk about OpenGL, but to start with a simple program would be a good breather for a novice. Here we'll be writing a program to draw a rectangle to get a hold of basic know-how of OpenGL programming.

    The article assumes :
    1. Platform as Linux
    2. Native programming language as C
    Libraries to install:

    Glut libraries i.e. the openGL Utility toolkit needs to be installed which provides a platform independent windowing along with the window event handling for interactive graphics programs.

    Use following commands to install openGL and Glut
    Code:
    sudo apt-get install libglu1-mesa-dev freeglut3-dev mesa-common-dev
    sudo apt-get install freeglut3
    
    Regarding windowing for openGL rendering, there are other available libraries as well apart from Glut like GLOW Toolkit and SDL. However, we'll be using glut library in this article.

    OpenGL Programming



    As unusual, OpenGL programming with C also has main() as the starting point. There would be glut calls to initialise/create windows for the openGL to draw onto followed by GL calls to do the actual drawing.

    First of all, call
    Code:
    glutInit(&argc, argv)
    This initiates the glut library and takes the same parameters as main(), reason being it takes a few of main() commandline arguments whatever it understands to initialise the glut library. To mention a few like -display, -geometry, -direct. More information can be found in the man pages.

    Next call is,
    Code:
    glutInitWindowSize(window-width, window-height);
    glutInitWindowPosition(x-coord, y-coord);
    
    This requests the future window of the specified width and specified height and at a certain position specified by inputted (x-coord,y-coord) coordinates.

    Then we need to call
    Code:
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE)
    There are modes of Glut windows and we set these modes through this call. Here, GLUT_RGB means red-blue-green framebuffer for rendering and GLUT_DOUBLE means to enable use of double buffers. Double buffering is a concept used in drawing graphics to reduce flickering. One buffer is used to display and other is used to compute the next frame, and the technique keeps swapping these buffers.

    Please refer the man page for more modes accepted.

    Creating a window,
    Code:
    glutCreateWindow("Basic OpenGL Example")
    This creates a glut window of title "Basic OpenGL Example. This function accepts an ascii string as the title of the newly created window.

    Next is,
    Code:
    glutIdleFunc(drawRect)
    This method sets the global idle callback function. Here, drawRect() is our defined function which draws the rectangle.

    Global idle callback function is called during no event-handling. All rendering is done during the idle callbacks as to not to affect the responsiveness of the interactive events.

    The next call is an openGL call,
    Code:
    glViewport( 0, 0, window-width, window-height )
    This sets the view port i.e. the viewing region specified by left-bottom and top-right coordinates.

    We have to set the current matrix mode by
    Code:
    glMatrixMode( GL_PROJECTION )
    Most of the graphics computations are done in matrices. And so is the underlying implementation of openGL. Hence, we need to set the matrix stack prior to computive openGL calls. Standard OpenGL supports three major matrix modes:
    • GL_PROJECTION - for camera positioning
    • GL_MODELVIEW - for various transformations
    • GL_TEXTURE - as the name suggests it is used for texturing
    Here, because we want to set the camera view perspective (forthcoming call), we are setting the matrix mode to GL_PROJECTION

    We can enable the depth testing, which is a part of graphics pipeline, by following call
    Code:
    glEnable( GL_DEPTH_TEST )
    Following is the call for setting the projection perspective matrix
    Code:
    gluPerspective( 45, (float)window-width/window-height, .1, 100 )
    This call sets the camera view frustum, which specifies a 3D space region in world coordinates which would be visible in the rendered scene.

    The frustum consists of a clipping plane nearest to camera eye (called the near clipping plane) and a farthest plane from the camera eye (called far clipping plane).

    Please note, any object before to the near clipping plane and farther to the far clipping plane would be clipped.

    Here in our call,
    1. The First parameter is the angle of the camera view frustum = 45 degrees
    2. The second parameter is the aspect ratio = our window aspect ratio in our case
    3. The third parameter is the distance of the camera eye from the near clipping plane = 0.1 units
    4. Fourth parameter is the distance of the camera eye from the far clipping plane = 100 units
    Now, its time to start the drawing which would involve transformations. Hence, lets change the matrix mode to GL_MODELVIEW.
    Code:
    glMatrixMode( GL_MODELVIEW )
    Remember, we had mentioned to do all drawing in a separate method - drawRect()? We had mentioned this function as aparameter to glutIdleFunc(). So, its time to call a glut method to start the loop where it will do its drawing part whenever its idle from the event handling.
    Code:
    glutMainLoop()
    Here it enters the glut event processing loop with no returning. It will render as per the function drawRect(), with high priority to interactive events.

    Coming to the drawing part, lets enter the drawRect() method.

    The first call would be,
    Code:
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    This call clears the bits of the buffer screen along with the color buffer and the depth buffer.

    It is a good programming practice to clear all enabled buffers before starting to draw or in between frames of animation.

    Alongwith, we need to load an identity matrix before transformations which are relative to the current loaded matrix. Hence, if we want the translation/rotation to happen with respect to origin, then we need to load the identity matrix first.
    Code:
    glLoadIdentity()
    To translate the to-be-drawn figure, we call
    Code:
    glTranslatef(0,5, -20)
    Translation is a matrix multiplication internally. This gl translate call translates the to be drawn figure by specified input (x,y,z) parameters. The input parameters are specified in float for this call. It can be inputted as integers as well. Please refer the man page for the various other versions of gltranslate().

    The actual drawing is done as:
    Code:
       glBegin(GL_QUADS);
       glColor3ub(255, 0, 0); 
       glVertex2f(0, 3);
       glVertex2f(6, 3);
       glColor3ub(255, 255, 0);
       glVertex2f(6, 0);
       glVertex2f(0, 0);
       glEnd()
    
    Here openGL needs the programmer to specify what figue to draw and then specify the vertices (x, y coordinates) as per the figure. We specify one vertex through one glVertex() call. We can also set the color for each vertex where openGL would render the color gradient figure as per each vertex set color.

    Here we are specifying 2D vertices in float values to draw a two colored rectangle.

    Color is set through glColor(), and every vertex is drawn with the previous set glColor() call. The color is mentioned in RGB format i.e. Red, Green, Blue.

    We need to explicitly call,
    Code:
    glutSwapBuffers()
    in case of double buffering. Generally its a good practice to call glutSwapBuffers() after drawing each frame in an animation.

    Thats it, we are done with openGL programming to draw a colored rectangle :)

    The complete Program



    Here is how the complete programs looks like:

    FileName : myRect.c
    Code:
    #include<stdio.h>
    #include<GL/glut.h>
    
    void drawRect();
    int main (int argc, char**argv)
    {
       int windowWidth = 640;
       int windowHeight = 480;
       glutInit(&argc, argv);
       glutInitWindowSize(windowWidth, windowHeight);
       glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
       glutCreateWindow("Basic OpenGL Example");
       glutIdleFunc(drawRect);
    
       glViewport( 0, 0, windowWidth, windowHeight );
       glMatrixMode( GL_PROJECTION );
       glEnable( GL_DEPTH_TEST );
       gluPerspective( 45, (float)windowWidth/windowHeight, .1, 100 );
       glMatrixMode( GL_MODELVIEW );
    
       glutMainLoop();
       return 0;
    
    }
    
    void drawRect()
    {
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       glLoadIdentity();
       glTranslatef(0,5, -20);
    
       glBegin(GL_QUADS);
       glColor3ub(255, 0, 0); 
       glVertex2f(0, 3);
       glVertex2f(6, 3);
       glColor3ub(255, 255, 0);
       glVertex2f(6, 0);
       glVertex2f(0, 0);
       glEnd();
       glutSwapBuffers();
    
    }
    

    Compiling and Running



    While compiling, you will need to link to the installed GL and glut libraries.
    Code:
    gcc -Wall myRect.c -o myRect -lglut -lGLU
    [​IMG]

    Conclusion



    Now we know how to write a basic drawing program using openGL and most importantly we understand what each line of code means. Since, openGL programming needs the knowldge of its API's, hence the more you know and understand and with the ability to imagine, the more you enhance on your graphics programming skills.

    For drawing animations, we can add a varying static parameter , whose value changes after every run. Hence, that would lead to a different frame each time, creating an animation. As an example, in the above program, provide the z-value of gltranslate() call as a static variable in our method drawRect(), whose value is incremented in each run. Wondering, what the animation will look like? Try and enjoy playing :)
     
    Last edited by a moderator: Jan 21, 2017
    shabbir and poornaMoksha like this.
  2. AhmedHan

    AhmedHan New Member

    Joined:
    Oct 11, 2005
    Messages:
    30
    Likes Received:
    0
    Trophy Points:
    0
    Home Page:
    http://www.stirve.com
    What differences does occur when the platform is Windows?
    I don't believe that there is be much of a difference for this tutorial. Why don't you explain it for both platforms by editing the Linux related parts like "For Linux, you do it this way. And for Windows, you do it this way..."?
     
  3. Trinity

    Trinity New Member

    Joined:
    Nov 23, 2011
    Messages:
    28
    Likes Received:
    11
    Trophy Points:
    3
    Occupation:
    Software Engineer
    Thanks AhmedHan for the suggestion.
    Yes, using the Glut library for windowing, there won't be much difference for windows and linux except for the specific library installations. I'll take care to consider widely used platforms for my future articles.
     
    Scripting likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice