Click here to Skip to main content
15,881,803 members
Articles / Desktop Programming / Win32

Native Win32 API OpenGL Tutorial - Part 1

Rate me:
Please Sign up or sign in to vote.
4.37/5 (7 votes)
17 Apr 2016CPOL5 min read 26.6K   3.9K   16   4
Native Win32 API OpenGL Tutorial - Part 1

Introduction

Some question posted by users on Code Project forums made me realize that most of the tutorials on OpenGL on the internet are sadly out of date. Many reference the old NeHe tutorials which have not been updated since Jeff Molofee turned over maintenance of his site to GameDev.

Visual Studio 2013 and 2015 have been released since then as has Windows 7, 8 and 10. So it seemed like it was time to at least try and create some basic tutorials in line with the changes.

Background

Our goal will be simple - produce the standard rotating bitmap cube in an OpenGL window.

Image 1

All Windows versions since Windows 98 carry OpenGL natively there is nothing you need to add or do. Windows 7, 8 and 10 all run OpenGL version 3.3.0 out of the box but some video cards manufacturers as part of their driver installs may boost that to as high as version 4.5. You can however assume that you have OpenGL version 3.3 at the very minimum on any current Windows machine.

The first problem encountered by people trying to use the NeHe tutorials is that the GLAUX library has been deprecated and no longer exists either in Visual Studio or as a DLL for Windows. The reasoning for that is the functions are easily replaced by using standard Win32 API calls and in this article series, we will use that process. I see comments all the time about going and downloading the header file and compiled DLL for GLAUX but will we avoid that as there is no future in it.

I am going to try to use the Keep It Simple Stupid (KISS) approach and part of that approach is the programming code has no Objects or Frameworks. It is not because I don't believe such things have merits but it is to try to keep the code as simple as possible and to the widest audience.

The code uses the standard <TChar.h> interface so it compiles in Ansi, Unicode and Wide character modes. I debated about not doing it in keeping with the KISS principle but felt to not do so would restrict the compilation modes and options particularly for non English speaking countries. As all that is involved is the exchange of the "char" type for "TCHAR" and a few _T statements around text strings I felt it detracts little from understanding.

Using the Code

First let's look at the pseudo code for our OpenGL window system we will use that like this:

C++
1.) Initialize OpenGL (Called Once)
2.) Scale the OpenGL viewPort (Initial Call)
repeat
3.) Draw the scene
4.) Transfer the scene to screen
until window closes

** Note Item 2) the scale process also gets called if the window changes size 

The reason for this approach is because it will make the OpenGL sections flexible including migration into frameworks like MFC, WPF, etc.

The other concept I have used is putting all the OpenGL data into a simple structure which is attached as a property to the Window itself. In this first tutorial, people may wonder why bother to do that as it would be easy to just use normal global variables. The reasons will become obvious in Lesson 2 when we have multiple OpenGL windows and then on following lessons with more advanced multiple viewports.

This is our OpenGLData for the first lesson. The Render Context will always be there in future lessons but all the other data will vary depending on what is needed. In our first lesson, we will load a bitmap as a texture (gltexture in the struct), we will put that texture on the sides of a cube and rotate it (xrot, yrot being used for the rotation).

C++
typedef struct OpenGLData {
    HGLRC Rc;                                   // Our render context ** Always Needed
    GLuint glTexture;                           // Our texture to draw
    GLfloat    xrot;                            // X Rotation
    GLfloat    yrot;                            // Y Rotation
} GLDATABASE;code blocks look like this

That basic data structure is attached to a window handle via a static defined label string using the SetProp API call and retrieved whenever needed by using the GetProp call.

The label property we use in this tutorial is:

C++
static const TCHAR* DATABASE_PROPERTY = _T("OurDataStructure");

This is the code for creating and attaching the data structure to a window handle we use:

C++
GLDATABASE* db = (GLDATABASE*) malloc(sizeof(GLDATABASE)); // Allocate structure
db->Rc = InitGL(Wnd);                                      // Initialize OpenGL hold render context
db->glTexture = 0;                                         // Zero the texture
db->xrot = 0.0f;                                           // Zero x rotation
db->yrot = 0.0f;                                           // Zero y rotation
SetProp(Wnd, DATABASE_PROPERTY, (HANDLE) db);              // Data structure to window property

Anytime, we want access to the data we make a simple retrieval call like this:

C++
GLDATABASE* db = (GLDATABASE*) GetProp(Wnd, DATABASE_PROPERTY); // Fetch the data structure

That all said, what we have in this lesson is then a standard window application skeleton. As the application Window is created, the WM_CREATE will be used to initialize the OpenGL system. The returned Render context will be held in our data structure. The ReSizeGLScene is called directly after it to set the initial size of the OpenGL system to the window size created.

With the normal window then running, that just leaves us to deal with the WM_PAINT message for the window and the code for that looks like this:

C++
case WM_PAINT: {                                                   // WM_PAINT MESSAGE
   PAINTSTRUCT Ps;
   GLDATABASE* db = (GLDATABASE*) GetProp(Wnd, DATABASE_PROPERTY); // Fetch the data base
   BeginPaint(Wnd, &Ps);                                           // Begin paint
   DrawGLScene(db, Ps.hdc);                                        // Draw the OpenGL scene
   SwapBuffers(Ps.hdc);                                            // Swap buffers
   EndPaint(Wnd, &Ps);                                             // End paint
   return 0;
}

It starts with the normal BeginPaint call but then calls out to OpenGL to draw its scene onto its render context. On the return back, we swap the render context onto the PaintStructure device context which draws the OpenGL scene onto our window. We then cleanup and exit.

The trick to this is the render process is not continually running it only occurs when a WM_PAINT message is provided so if you wish to animate things, you need to provide WM_PAINT messages after changes. When we activate the timer, it changes the rotation and then Invalidates the window which does exactly that creating a WM_PAINT message to make the window redraw.

This process is great for things like constructing an 3D Object editor and the like but not very good in fast moving games where we need fast continual render processing of the scene. In later lessons, we will deal with that process and use threads.

So now, run the program and using the file menu, select to load a bitmap and on doing so, you will see something like this:

Image 2

Now start a timer and your cube should start to rotate and you that is it for this lesson. So there we have it, our first OpenGL tutorial done with OpenGL running in a standard application window.

In our next lesson, we are going to push things a bit further with an MDI application.

History

  • Version 1.0: First release of code

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Australia Australia
Experience hardware/software design engineer with specialization in the field of embedded controllers and software. Software credits include Free Pascal development RTL, Cipher Multitask engraving software and Symmetry Laser/Cutting software. Firmware/hardware credits include Cipher CNC controllers series 1-3, Vision series 1 engraver controller and I-Marc pet tagger controller.

It is about now you realize you have been doing this for far too long Smile | :)

contact: ldeboer@gateway.net.au

Comments and Discussions

 
QuestionRemove SDF file from zips Pin
gunamoi119-Apr-16 21:04
gunamoi119-Apr-16 21:04 
QuestionOld OpenGL Code? Pin
Bartlomiej Filipek17-Apr-16 19:05
Bartlomiej Filipek17-Apr-16 19:05 
In the article you mentioned about modern OpenGL 3.3, 4.5, etc... but in the code I've seen old style of coding: with glBegin/glVertex/glEnd... do you plan to use modern OpenGL or only legacy approach?

BTW: please don't insert large Visual Studio files - like OpenGLAppDemo.sdf (60MB!), obj files, etc...! - it's better to clean the solution before creating a zip package...
AnswerRe: Old OpenGL Code? Pin
leon de boer18-Apr-16 3:55
leon de boer18-Apr-16 3:55 
GeneralRe: Old OpenGL Code? Pin
Bartlomiej Filipek18-Apr-16 9:15
Bartlomiej Filipek18-Apr-16 9:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.