Click here to Skip to main content
Click here to Skip to main content

A multithreaded, OpenGL-enabled application.

By , 15 Nov 2006
 
  • Download source code - 28.3 Kb
  • Download example project - 28.8 Kb

    Sample Image

    Prologue

    As most people learning about OpenGL tend to find out, it provides a wonderful means of allowing developers direct access to the underlying graphics hardware and/or the GPU for a computer. What it does not provide is any mechanisms, whatsoever, to work with its host operating system environment.

    This includes things like system IO, Windowing, timing, etc. just to name a few. The traditional approach to fill this gap has been to use yet another library to handle the specifics. This approach can be nice in the fact that the abstraction can allow platform-independent GUI, etc. operation. But, as with most abstractions the underlying OS functionality - ready for the picking and tweaking - is hidden from you.

    The second method is to interface with the platform's specifics directly to achieve the extra functionality necessary. This approach does not allow for platform independent code, but it does allow you fine-grained control on how your application works and without the extra overhead involved. Being a longtime Windows developer myself, this is the route I chose because to me, speed is important and getting exactly what I want out of Windows is important.

    So, I propose a skeleton Windows-based application that hosts an OpenGL rendering environment. Unlike most other skeletons or wizards out there for OpenGL-based applications, this is more complete with the functionality required to create a real-world application rather than a hello world scenario, and actually uses multithreading to achieve a performance boost on newer systems.

    Goals

    The goal of this application is to provide the mundane work required to get an OpenGL rendering environment up and running using no external libraries other than what is already provided by Windows by default. This also allows us to use a common set that is well-tested and debugged.

    The design followed the KISS principle. Rather than including everything in the world that doesn't apply directly to an OpenGL command, include the functionality that would be present in just about every application you made that uses it. It does, however, contain enough of a structure to allow you plug in extra functionality as needed.

    Features

    • Timed-Based Animation

      One of the age-old issues in animation for games has been when running on a faster CPU/GPU than the game was designed for the game becomes unplayable as it runs too fast. The opposite of this is true as well. If a game was designed on a fast system, but run on a slower one, the animation can be too slow.

      Due to this, the skeleton application employs a technique called timed-based animation, which uses the amount of CPU cycles per second the computer takes to render a frame as a multiplicative factor when animating. Using this method allows for smooth animation regardless of the frame rate.

    • Multithreading
      The skeleton application takes advantage of a multithreaded paradigm. It uses one thread to handle the Windows specific processing and a separate thread to handle the OpenGL specifics. This has two distinct advantages. One, this will allow for a performance boost on modern CPUs that use Hyper Threading and/or dual core technologies. Two, this also ensures a smoother operation of the rendering pipeline for OpenGL, as it will not be bottlenecked by Windows message processing (which is required so the user can interact with the application).
    • Inter-Thread Communication
      In the application, the two threads are able to communicate via a messaging system. The main thread can use the PostThreadMessage() API to talk to the render thread, and the render thread can use the SendMessage() API to talk to the main thread. This allows for a customizable, extensible means for the two threads to share information.
    • Serialization

      Realistically, any Windows-based application will tend to use some means to save and restore settings. One very popular way is to take advantage of the Windows registry. As such, the application supports reading and writing to the registry under the Users hive, but can be easily adapted to also write to the System one, etc.

      By default, the skeleton will check for BPP data, main Window positioning data, and the vertical refresh rate to use for fullscreen mode.

    • Command Line Parsing
      And what would an application be, if it didn't use the command line? The skeleton application allows you easy add support for as many command line options as you wish. By default, it checks for a /fullscreen option that allows the user to specify if they wish to run in fullscreen or windowed mode.
    • Debug Macros & Information

      For debug mode only, the skeleton application will do two extra things:

      First, it will provide you with status information on the title bar of the main window providing the version of OpenGL installed on the system and the frame rate (FPS). This information is useful in determining what you can do with your installed implementation and performance tweaking.

      Second, it enables two debug macros called ENTER_GL and LEAVE_GL, which is intended to be used to surround code blocks of OpenGL calls. OpenGL's error handling mechanism isn't straightforward, and these macros will help alleviate this. The application itself demonstrates the usage of them.

    • Extensive Configuration Options

      To accommodate many different scenarios, the skeleton application makes use of preprocessor directives in WinMain.h to enable or disable or configure the features to use. Below is a description of the ones that may provide a bit of confusion:

      APP_ALLOW_FULLSCREEN Set this to true if you wish to allow the application to enter fullscreen mode; otherwise set it to false. Note: if false, this will override all other settings (registry, command line, etc.) regarding fullscreen.
      APP_ALLOW_RESIZE Set this to true if you wish to allow the main application window to be resized; otherwise set it to false. Note: if false, the application will not take into account any information regarding the window's size (only position).
      APP_ALLOW_MENU Set this to true if you wish to allow a standard Windows menu on the main application window; otherwise set it to false. Note: if true, the application assumes the menu's resource id is IDR_MAINFRAME. Also, by default, the ESC key will show and hide the menu. Doing this will enable the user to free up more real estate on the screen.
      APP_ALLOW_VSYNC Set this to true if you wish to allow the application to adjust the vertical refresh rate synchronization for the frame rate (VSync) on the video card. Note: if true, it attempts to turn VSync on or off depending on if it's possible for the system and configurations. If it is not possible or set to false it will do nothing no matter what the settings. If allowed VSync can be turned on or off by using the VSync key in the registry.
      APP_DEF_BPP Default bits-per-pixel (BPP) to use if the application is in fullscreen mode. Note: This can be overridden by setting a BPP key in the registry.
      APP_DEF_FULLSCREEN If fullscreen mode is allowed, then set this to true if you want to the application to default to fullscreen mode or false if you want to default to windowed mode. Note: as it is currently, the /fullscreen switch can override this as it's just a default value.
      APP_DEF_HEIGHT
      APP_DEF_WIDTH
      Default width and height of the main application window. Note: if the window is not allowed to resize this will effectively be the main window's size always.
      APP_MAX_REFRESH
      APP_MIN_REFRESH
      By default the application will look into the registry for a vertical refresh rate to use for fullscreen mode under the key Refresh. These two settings will determine the maximum and minimum refresh rates allowed as a safety precaution.
      APP_MIN_WINVER_MAJOR
      APP_MIN_WINVER_MINOR
      Allows you to specify the minimum version of Windows the application will run on.
      APP_MIN_HEIGHT
      APP_MIN_WIDTH
      Allows you to specify the minimum width and height of the main application window. If set, the window cannot be resized below these points. Note: setting these to 0 effectively means there are no minimums.
      APP_SINGLE_INSTANCE Set to true if you want the application to limit itself to only one instance (using a mutex); otherwise, set it to false.
      APP_WINVER_NTONLY Set to true if you want the application to run only on NT-based versions of Windows; otherwise, set it to false.

    Points of Interest

    • The Use of C Over C++

      The skeleton application is written in C rather than C++. Many of you may prefer using C++ and more power to you. It should be easy enough to wrap the functionality of the application into a few classes. I have nothing against C++, but my choice in C is more a practical one rather than a philosophical one.

      I'm fully aware of all the key areas in a C vs. C++ debate, and I assure you I don't care to repeat them. If you have to use C++, then please simply create a wrapper or use this application as guidance while you create a C++ version.

    • Source Code Key Areas
      While the majority of the code is relatively self-explanatory, it is worth noting that in DrawMain.c the function RenderFrame() is the starting point for anything that is to be rendered in OpenGL. It will be called once every frame and all rendering operations that don't include preloading, etc. should stem from it.

    Example Application

    Also provided is an example application that demonstrates a simple usage of the skeleton to animate the Triforce from the well-known Zelda series by Nintendo. It is a bare bones example, not written for speed but for clarity. However, it does take advantage of the time-based animation provided by the skeleton.

    Notes

    Is it my intention to write OpenGL-related articles for CodeProject in the future. If applicable, this skeleton application will serve as the basis in which I'll use to run code samples in the downloadable demo applications.

    Credits & History

    Article's Author  - Jeremy Falcon
    High Resolution Timer Suggestion  - Jeffry J. Brickley
    InitScene() Update Suggestion  - JWood
    • 2006-08-27 - Ver. 1.1 released.
    • 2006-08-26 - Ver. 1.0 released.
  • License

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

    About the Author

    Jeremy Falcon
    Software Developer (Senior)
    United States United States
    I've been in software development since 1994. Over the years I've learned quite a lot in what it takes to complete the process of pushing out a quality product to customers in a timely fashion. As most of my colleagues could attest, there have been many challenges in our new and growing field in the past couple of decades as the industry matures rapidly. Much more so than most others historically speaking.
     
    As such, I've learned one of the best aspects of software engineering is embracing the change that inherently comes along with it as new technologies constantly emerge to help us improve our world one application at a time as we make sense of the overwhelming amount of data now prevalent in the Information Age.
     
    We truly live in a time unlike that ever known to mankind in recorded history, and it is my hope to do my part to help it along to face the challenges and demands of tomorrow.

    Sign Up to vote   Poor Excellent
    Add a reason or comment to your vote: x
    Votes of 3 or less require a comment

    Comments and Discussions

     
    You must Sign In to use this message board.
    Search this forum  
        Spacing  Noise  Layout  Per page   
    GeneralRe: Very nice articlememberJeremy Falcon28-Jan-07 20:19 
    lazygenius wrote:
    Any insights of using OpenMP and OpenGL would be greatly appreciated.

     
    I haven't used it, although it would be a bit interesting to look into. So far, I've been allowing the OS's SMP scheduler handle the grunt work, of course I do set affinity. But, if I can push better performance out of OpenMP that would be nice, although I don't really have a supercomputer to test things out on. Big Grin | :-D
     

    GeneralRe: Very nice articlememberlazygenius31-Jan-07 6:19 
    For more complex models I wonder about introducing a third thread (or utilising the main thread more) for manipulating the model. As I understand it there is a latency issue with SwapBuffers whereby the SwapBuffers call, or the next GL call will block the thread.
     
    Even in your secondary thread you are going to experience that latency, no? If SwapBuffers does block it would be nice to kick off another thread for doing CPU based work such as collision detection or general housekeeping. If SwapBuffers doesn't block then I guess this work could be done directly after SwapBuffers being sure not to call any GL functions.
     
    Still beats the hell out of GDI either way! Smile | :)
     

    GeneralRe: Very nice articlememberJeremy Falcon31-Jan-07 6:58 
    lazygenius wrote:
    For more complex models I wonder about introducing a third thread (or utilising the main thread more) for manipulating the model.

     
    Definitely, I don't want to suggest you only need two threads in all scenarios. Typically though, most apps tend to have only one render thread however.
     
    This skeleton isn't a end-all-be-all by any means. I wanted I wanted to achieve with this is give people something to use as a skeleton when making their multithreaded OGL apps on Windows. It's just a start that contains most of what you'll use over and over again.
     
    lazygenius wrote:
    Even in your secondary thread you are going to experience that latency, no?

     
    Yup, but the latency can't be avoided with just about any 3D pipeline. As far as blocking, I haven't ran across that myself. If you have a link or more info on it; I'd be grateful.
     
    The idea behind the threading is more about concurrency in that while you do swap buffers going on you could also be doing something like processing the AI for the next frame on another core. The slow down is mitigated and not really gotten rid of, but the end result could be faster overall.
     
    lazygenius wrote:
    Still beats the hell out of GDI either way!

     
    Amen to that. Laugh | :laugh:
     

    GeneralRe: Very nice articlememberrinchendawa13-Aug-08 10:53 
    Did you check out ApocalyX3D (scipted in LUA) ?
    Another good option is the Breve engine (has it own script language and Python).
     
    Both are excellent pieces of open source
    GeneralSlick...memberPaulC197226-Nov-06 11:19 

    Very well done article. Found it well written and informative. I am going to add it to my blog Smile | :)
     
    Paul
     


    I'd like to help but I don't feel like Googling it for you.

    GeneralRe: Slick...memberJeremy Falcon26-Nov-06 18:46 
    Thank you. I'm just debating on whether or not to leave it as is or update to reference the engine when it's done.
     
    So far, I'm thinking of leaving it be and using to show small, concentrated aspects of OGL. And then maybe have a engine base example for the larger, more complex examples. Meh, who knows.
     

    GeneralRe: Slick...memberPaulC197226-Nov-06 19:19 
    Jeremy Falcon wrote:
    maybe have a engine base example for the larger, more complex examples


    That would be really cool Smile | :)
     


    If you try to write that in English, I might be able to understand more than a fraction of it. - Guffa

    GeneralRe: Slick...memberJeremy Falcon26-Nov-06 21:27 
    PaulC1972 wrote:
    That would be really cool

     
    Well the idea is to release it on CP. So I may as well write articles on it so I can get platinum status. Big Grin | :-D
     

    GeneralRe: Slick...memberPaulC197227-Nov-06 3:20 
    Jeremy Falcon wrote:
    So I may as well write articles on it so I can get platinum status


    Yeah, go for it. I only have like 25 articles to write :->
     


    Some people have a memory and an attention span, you should try them out one day. - Jeremy Falcon

    GeneralRe: Slick...memberDanoo18-Dec-06 20:51 
    How far is your engine now? Do you have something ready? I would be very interested...
    Regards
    Daniel
    GeneralRe: Slick...memberJeremy Falcon19-Dec-06 4:26 
    Thanks for the interest. It recently passed the initial design phase. I already have Windowing abstractions set in place for cross platform, but no inter-game GUI elements yet like listboxes, etc.
     
    I was in the middle of implementing the thread pool when I got pulled aside to do some work (not by choice Smile | :) ). But, once that's done and I get a rough renderer set in place I may go ahead and write a pre-alpha article on it just to get some feedback/ideas about it.
     
    I still have a long way to go. It'll be in alpha for a while. I want to get something functional first (3D audio, scene graph, timing, etc.) going before adding more advanced stuff like shaders. It's all a work in progress and could easily be a year before it's done. But, I'll most likely post something on CP before that time.
     
    GUI
    Generalpick and panmemberjekata21-Nov-06 19:26 
    hi,
     
    i am looking for a minimal opengl framework that supports picking elements in the model and interactive navigation such as pan, zoom, rotate, orbit ... does anybody know of a good clean implementation of such a beast? preferable platform independent, e.g. wxWindows based?
     
    cheers
     
    jeremy
    GeneralRe: pick and panmemberJeremy Falcon22-Nov-06 17:59 
    jekata wrote:
    i am looking for a minimal opengl framework that supports picking elements

     
    How minimal is minimal? If all you're looking for is picking, then just integrate the code from a tutorial online rather than using a full-blown framework.
     
    One such example: Clickety[^]
     
    jekata wrote:
    interactive navigation such as pan, zoom, rotate, orbit

     
    There are a lot of camera classes for OpenGL in C++. Here's one such example for you're coding pleasure: Clickety[^]
     

    QuestionIs Windows messaging faster??memberKenneth Krueger21-Nov-06 8:39 
    I agree with everyone else and your article is well written and will definitely aid coders in writing OpenGL apps. Earlier in my Windows programming career, I did some testing to determine the speed difference between Windows messaging and using Events and memory mapped files to pass messages. Like you, my first code was written in C, not C++. I cannot find my data after 8 years, but I seem to remember that the Windows based mesaging came out slower. I alo did some playing around with priorities at the time and that certainly could have been a factor in the differences. Have you ever done any tests in looking at the differences in response times of the 2 methods?
     
    Kenneth Krueger Jr.

    AnswerRe: Is Windows messaging faster??memberJeremy Falcon22-Nov-06 18:03 
    Kenneth Krueger wrote:
    Have you ever done any tests in looking at the differences in response times of the 2 methods?

     
    No I haven't. My threading experience has been in Windows only, so I naturally got used to using the messaging route. You have, however, piqued my interest and I'd love to hear more about using memory mapped files for messaging. I'm not sure if it's faster or not, but I have no problem testing it out to see.
     
    As far as threading priority, that very may well be something I add to the example at a later date. I kinda got side-tracked working on my engine and it's taking a lot of time. Smile | :)
     

    GeneralRe: Is Windows messaging faster??memberTodd Smith22-Nov-06 23:54 
    Windows uses the message loop as one of the triggers for context switching applications. Another trigger is the Sleep() function. So perhaps by avoiding the message loop and using memory mapped files you could give your application a higher priority when it really needed it. Or did you get more consistent framerates by avoiding the message loop?
     
    Todd Smith

    GeneralRe: Is Windows messaging faster??memberJeremy Falcon23-Nov-06 11:59 
    Todd Smith wrote:
    So perhaps by avoiding the message loop and using memory mapped files you could give your application a higher priority when it really needed it.

     
    Well, I've never used memory mapped files for threading, so it's still a subject I'd like to dig into some more. Perhaps over the holiday weekend and compare to the two.
     
    Todd Smith wrote:
    Or did you get more consistent framerates by avoiding the message loop?

     
    I never did avoid using a message loop. The reason being I wanted to allow Windows to handle the threading priorities naturally so I don't hog down the system. With that being said, I don't notice a major performance penalty over using messaging say compared to global variables (yeah, there is one of course). But, the idea behind messaging is A: it's a lot more flexible and B: it helps with encapsulating details.
     
    However, if using a memory mapped file can help me achieve the same thing but faster then I'm all ears.
     

    GeneralError checkingmemberJWood27-Sep-06 5:44 
    Good article and refresher on multithreading. My only complaint is that it might have abit heavier error checking, especially in InitScene, where initialization can and will go wrong.
     

    A cynic is a man who, when he smells flowers, looks around for a coffin.
    -H.L. Mencken


    GeneralRe: Error checkingmemberJeremy Falcon27-Sep-06 14:39 
    JWood wrote:
    Good article and refresher on multithreading.

     
    Thanks.
     
    JWood wrote:
    My only complaint is that it might have abit heavier error checking, especially in InitScene, where initialization can and will go wrong.

     
    You're right. I may make an update to it that adds this, as the whole purpose of the skeleton app is to be ready for the real world.
     

    GeneralA stupid question..memberSuper Lloyd28-Aug-06 18:47 
    hu... what about a D[^] version?
     
    I know, I could write it myself, but I have a lazy and sick curiosity about it...
    GeneralRe: A stupid question..memberJeremy Falcon28-Aug-06 18:55 
    Super Lloyd wrote:
    what about a D[^] version?

     
    Um... Yeah, I'll have it ready around the year 2045. Poke tongue | ;-P
     
    Seriously though, I don't know D, and I'm trying to stay away from learning a new language right now while I'm racking my brain with all sorts of learning materials (I'm making a game engine), and if I push it any further I'm afraid my head will explode.
     

    GeneralRe: A stupid question..memberSuper Lloyd28-Aug-06 19:01 
    Already busy doing something else!! Good luck then!
    (I know that feeling, same for me in fact)
     
    A game engine, cool! Is it based around the quake engine? OMG | :OMG:
    GeneralRe: A stupid question..memberJeremy Falcon28-Aug-06 19:12 
    Super Lloyd wrote:
    A game engine, cool! Is it based around the quake engine?

     
    It's a home brew engine, using libs (like libpng) internally where I can cut a few corners.
     
    I'm mainly doing it for the learning experience. It already supports texture mapped fonts w/ kerning, PNG HDR TGA and JPG image formats, and filters like sharpen, etc. Of course, I still have a looooooong way to go, but one step at a time.
     

    GeneralRe: A stupid question.. [modified]memberSuper Lloyd28-Aug-06 19:26 
    I see.
    As you mentionned "fonts w/ kerning" I can't resist to taunt you a bit more... Poke tongue | ;-P
     
    I guess it's OS independant font handling (because of the "texture mapped font" hint) but does it support international rich text?!
    Ok, bad question... Laugh | :laugh:
     
    Just for fun and to show that I do some homework too (although with the evil .NET technologies):
    http://csgl.sourceforge.net/[^] by Lloyd Dupont! (me!)
     
    http://www.nova-mind.com/[^] by ... me again! (well I was the only windows developer 'till last month) and although I have a small hebrew bug, it does support international characters (and it's using home made text view)! Poke tongue | ;-P

    GeneralRe: A stupid question..memberJeremy Falcon28-Aug-06 19:42 
    Super Lloyd wrote:
    but does it support international rich text?!

     
    Well, the engine uses a pre-rasterized, luminance (w/ alpha) image for speed during loading.
     
    At first I tried using freetype, but the load time was too slow for my liking, and then came its issue with being dog-slow with kerning, so I dumped it.
     
    Anywho, rich text is supported in the fact that if you want a bold and/or italic font, the font creator program included with my engine will convert that. So, you can create two different fonts (say a normal version and an italic version) and mix and match them however you want when displaying the text.
     
    Is does support different colors by passing a command and color value in the input string for the drawing routine, so you could draw any char in any color you wanted.
     
    It theoretically supports Unicode in the image file format as it stores the char codes mapped at 16-bit ints, but the little helper tool I made to create the font file loads the ANSI charset to pull the glyph data from (forward thinking at least for now).
     
    Super Lloyd wrote:
    Just for fun and to show that I do some homework too

     
    It looks cool. How much do you plan on doing with it?
     
    Super Lloyd wrote:
    http://www.nova-mind.com/[^]

     
    Ok, that looks real interesting. How much does that sell out of curiosity? You making a killing yet? Laugh | :laugh:
     

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

    Permalink | Advertise | Privacy | Mobile
    Web04 | 2.6.130617.1 | Last Updated 16 Nov 2006
    Article Copyright 2006 by Jeremy Falcon
    Everything else Copyright © CodeProject, 1999-2013
    Terms of Use
    Layout: fixed | fluid