Game Indie Developer - getting into OpenGL

Hi All,

I have been doing indie game development for 14+ years. I actually have 2D WW2 turn based strategy game done written in VC++ for Windows XP+ platform. For the future I would like to replace the 2D map graphics with 3D. I’m not thinking of something fancy, I just want a 3D hexagonal map plane (with elevation) that will have 3D objects of units and buildings. I have Maya 2016 that I will use to make 3D objects like Buildings, trees and units. I will need to be able to export these objects from Maya for my game to be able to read and display the objects in in the 3D window. I’m not sure if I will need to use 3D OpenGL engine like Ogre or simply just write the OpenGL code in my game without any need for 3D OpenGL engine (Overkill?).

In any case, I have done a bit of OpenGL 5+ years but nothing beyond a bit of messing around with VC++ integration into a MFC application. I have ordered 3 following books on the subject of OpenGL:

  1. OpenGL Programming Guide: The Official Guide to learning OpenGL, Version 4.3 (8th edition)
  2. OpenGL Superbible: Comprehensive Tutorial and Reference (7th Edition)
  3. OpenGL 4 Shading Language Cookebook, Second Edition.

So my idea to now dive deep into OpenGL, figure out how to do the 3D hexagonal “map” (no idea where how to build this) and place 3D objects like units/buildings as well as be able to select hexes based on mouse coordinates. I don’t need to worry about Fog of War Line of Sight processing in 3D since I’m using my own in the 2D world which already has support for FOW and LOS.

I just want to purely use the 3D graphics window to represent the game map (2D array structure) and units state.

Any ideas, how to create the 3D hexagonal maps, do I need to use 3D engine like Ogre and how to generally start with this?

Thank You all for your listening and feedback :slight_smile:

Cheers!

Any ideas, how to create the 3D hexagonal maps …

Not sure what you mean.
But here’s a small glut based program that makes a floor out of hexagonal tiles.


//---9----8----7----6----5----4----3----2----1---++---1----2----3----4----5----6----

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <gl.h>
#include <glut.h>

#define SAN 0.8660       // sin of 60 degs

float zRotate = 0.0;

//---9----8----7----6----5----4----3----2----1---++---1----2----3----4----5----6----
//------------------------------------------   Reshape   ---------------------------

void Reshape (int x, int y)
{
    glMatrixMode   (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective (40.0, (GLdouble)x / (GLdouble)y, 0.5, 20.0);
    glMatrixMode   (GL_MODELVIEW);
    glViewport     (0, 0, x, y); 
}

//---9----8----7----6----5----4----3----2----1---++---1----2----3----4----5----6----
//-----------------------------------------   Animate   ----------------------------

void Animate (void)
{
    zRotate += 0.3;
    glutPostRedisplay();
}

//---9----8----7----6----5----4----3----2----1---++---1----2----3----4----5----6----
//-----------------------------------------   Hexagon   ----------------------------
 
void Hexagon (void)
{
    glBegin (GL_TRIANGLE_FAN);
       glVertex2f ( 0.0, 0.0);
       glVertex2f ( 1.0, 0.0);  glVertex2f ( 0.5,  SAN);  glVertex2f (-0.5,  SAN);
       glVertex2f (-1.0, 0.0);  glVertex2f (-0.5, -SAN);  glVertex2f ( 0.5, -SAN);
       glVertex2f ( 1.0, 0.0);
    glEnd ();
}

//---9----8----7----6----5----4----3----2----1---++---1----2----3----4----5----6----
//-------------------------------------------   Tile   -----------------------------

//  Draw one tile made up of two hexagons placed on top of each other
 
void Tile (void)
{
    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);

    glColor3f (0.3, 0.6, 0.9);
    Hexagon ();
    glScalef (0.95, 0.95, 0.95);
    glColor3f (0.6, 0.3, 0.1);
    Hexagon ();
}

//---9----8----7----6----5----4----3----2----1---++---1----2----3----4----5----6----
//------------------------------------------   Floor   -----------------------------

//  Make a floor out of hexagonal tiles.
 
void Floor (void)
{
    int a;
    static float yt = 2.0 * SAN;

    Tile ();                            // Central tile.

    for (a = 0; a < 6; a++)  {          // Surrounding tiles.
       glPushMatrix();
          glRotatef (a*60, 0,0,1);
	  glTranslatef (0, yt, 0);
	  Tile ();
       glPopMatrix();
    }
}

//---9----8----7----6----5----4----3----2----1---++---1----2----3----4----5----6----
//----------------------------------------   Draw_Scene   --------------------------
 
void Draw_Scene (void)
{
    glMatrixMode   (GL_MODELVIEW);
    glClear        (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity ();

    glTranslatef (0.0, 0.0, -10.0);
    glRotatef    (-60, 1,0,0);
    glRotatef    (zRotate, 0,0,1);

    Floor ();
  
    glutSwapBuffers();
}

//---9----8----7----6----5----4----3----2----1---++---1----2----3----4----5----6----
// ------------------------------------------   main   -----------------------------
 
void main (int argc, char **argv)
{
    glutInit               (&argc, argv);
    glutInitDisplayMode    (GLUT_DEPTH | GLUT_DOUBLE);
    glutInitWindowSize     (800, 700);
    glutInitWindowPosition (700, 200);
    glutCreateWindow       ("Tiled Hexagons - Carmine");
 
    glClearColor (0.0, 0.2, 0.1, 0.0);
 
    glutDisplayFunc (Draw_Scene);
    glutReshapeFunc (Reshape);
    glutIdleFunc    (Animate);
 
    glutMainLoop();
}

//---9----8----7----6----5----4----3----2----1---++---1----2----3----4----5----6----

From your description of the type of game, an engine isn’t necessary. You may wish to use libraries for specific features, e.g. loading textures or models, and you’ll probably want to use a “toolkit” library (e.g. SDL, GLFW, GLUT) for creating a window and handling input (particularly if you’re targeting multiple platforms).

Beyond that, ignore Carmine’s example code, and anything else which use glBegin/glEnd. Rendering should always be done using vertex arrays. glBegin/glEnd are deprecated in modern OpenGL, and they weren’t a particularly good idea for “real world” code even in older versions. All rendering should be performed using glDrawArrays() or glDrawElements(), or one of the more “advanced” versions (multi-draw, instanced, etc) of those.

Another issue is to decide which version(s) of OpenGL to target. Using newer features (e.g. shader programs, buffer objects) will preclude running the program on older hardware. On the other hand, don’t use legacy features if you want to target mobile platforms with substantially the same code, as mobile platforms typically use OpenGL ES, which doesn’t support legacy interfaces such as glBegin/glEnd or the fixed-function pipeline. Also, if you want to target Apple MacOS X, use of any legacy interfaces limits you to OpenGL 2.1 (although that may well be sufficient for your purposes).

As for learning OpenGL, start by reading one of the first two books you cite from cover to cover, then come back with specific problems.

[QUOTE=GClements;1280019]From your description of the type of game, an engine isn’t necessary. You may wish to use libraries for specific features, e.g. loading textures or models, and you’ll probably want to use a “toolkit” library (e.g. SDL, GLFW, GLUT) for creating a window and handling input (particularly if you’re targeting multiple platforms).

Beyond that, ignore Carmine’s example code, and anything else which use glBegin/glEnd. Rendering should always be done using vertex arrays. glBegin/glEnd are deprecated in modern OpenGL, and they weren’t a particularly good idea for “real world” code even in older versions. All rendering should be performed using glDrawArrays() or glDrawElements(), or one of the more “advanced” versions (multi-draw, instanced, etc) of those.

Another issue is to decide which version(s) of OpenGL to target. Using newer features (e.g. shader programs, buffer objects) will preclude running the program on older hardware. On the other hand, don’t use legacy features if you want to target mobile platforms with substantially the same code, as mobile platforms typically use OpenGL ES, which doesn’t support legacy interfaces such as glBegin/glEnd or the fixed-function pipeline. Also, if you want to target Apple MacOS X, use of any legacy interfaces limits you to OpenGL 2.1 (although that may well be sufficient for your purposes).

As for learning OpenGL, start by reading one of the first two books you cite from cover to cover, then come back with specific problems.[/QUOTE]

First of all thank you both Carmine and GClements for your replies.

I’m glad to hear that I don’t need to use an engine to get my 3D stuff done for the game. Today I spent some time after work with VC++ 2013, reading the Superbible 7th edition and trying to setup an OpenGL “toolkit” with MFC. The challenge I have is that my game is written in MFC (Microsoft Foundation Classes, 32bit) I can’t find a good example on the net either with freeglut, GLEW or GLFW how to make it work with MFC.

I found a sample of GLEW on codeproject.com “OpenGL-MFC-CDialog-Basic”, the challenge I have with this sample is I’m not sure if the sample is robust enough. Also when I use the project files and setup all the libraries, when I compile and run the same the window blue rectangles flicker and then the final state is black two rectangles. I wasn’t able to find GLFW sample for MFC. I tried freeglut according to this example (www.cs.uregina.ca/Links/class-info/315/WWW/Lab1/MFC/) but looks like there is come missing I can’t make the project compile.

The target platform for my game is Windows Vista/7/8/10 only, so no support for Apple OSX or mobile platform. An example of what I would like to is matrix games Battle Academy 2 (matrixgames.com/products/564/details/Battle.Academy.2.Battle.of.Kursk, please see the screenshots), however using hexes rather than squares

GLUT and GLFW are primarily basic GUI toolkits, and as such are alternatives to MFC. If you want to use MFC, look at the WGL functions. These provide the “glue” between OpenGL and the Win32 API. GLUT/GLFW may still be useful as examples of how to use those functions.

The main thing when using higher-level GUI toolkits is to get the most bare-bones “widget” available for the drawing canvas. A common problem is with widgets trying to manage the drawing process (e.g. clearing their background automatically), which you want to avoid.

GLEW’s primary function is simplifying the handling of different OpenGL versions and extensions.

Windows’ opengl32.dll only exports the symbols from the OpenGL 1.1 API. For functions added in later versions or in extensions, you need to use wglGetProcAddress() to obtain a function pointer. Additionally, before attempting to use such functions, you need to either check that the provided OpenGL version is sufficient or that the extension is supported.

GLEW hides most of this, allowing you to just use any function from any version or extension supported by the current version of GLEW. However, it is somwhat fragile. GLEW is typically linked as a static library, which requires that you define the macro GLEW_STATIC. It also requires that you use <glew.h> instead of <GL/gl.h>, as the headers will conflict (they both define many of the same names, but GLEW declares functions as macros rather than as prototypes).

Hi GClements,

So if I understand you correctly, I shouldn’t be using any toolkits. I don’t have much understanding what is required to make OpenGL work, however I will need to build an OpenGL interface myself in the MFC app barebones. I’m also wondering at this point, if I shouldn’t use Directx instead as if I’m having hard time just getting OpenGL to work I wonder how will I be able to import maya 3D objects into my OpenGL layer in my app (meaning, I’m thinking in long term what other gaps I will need to address by using OpenGL rather than Dirextx)

Thanks!

To be completely honest, given that you’re not a graphics programmer and ultimately don’t care much about graphics programming, you really ought to just use a game engine. It’d let you focus on what you’re trying to actually achieve (ie: making a game), not the nuts-and-bolts of how that gets done.

You are using a toolkit: MFC. You shouldn’t be trying to use two toolkits (e.g. MFC and GLUT or whatever).

Have you tried searching for “OpenGL MFC”?

The setup doesn’t appear to be much different to using OpenGL with the Win32 API directly. The key functions involved are ChoosePixelFormat, SetPixelFormat, wglCreateContext and wglMakeCurrent.

The interactions with the window system are notoriously messy (which is why libraries such as GLUT and GLFW exist). But the situation doesn’t seem to be any better for DirectX.

Yes I did spent 2 evenings so far trying to make freeglut or GLFW to work. I did find MFC OpenGL example on codeproject.com (OpenGL MFC/CDialog - Basic - CodeProject), though I’m not sure it covers everything as I need to have proper OpenGL setup. This demo code uses GLEW and it’s library.

Thanks for listing all the key functions of OpenGL, that definitely helps. If I may ask you, how should I proceed with getting OpenGL into my app. Do you have any recommendation?

thanks!

Thans for your feedback, I appreciate it! I will need to look into Ogre3D. Though I don’t mind doing some investigation to see if I actually really need it or not. At this point, I’m just exploring to see how much effort would be just to use OpenGL and do all the 3D programming. Thing is, my game is already fully written in MFC (using GDI+ 2D graphics) and so I would like to find what fits with the game design scope. Ultimately, I just want to build a 3D hexagonal based map and I would like to make 3D unit models in maya and import the objects into the 3D engine.

Getting FreeGLUT or GLFW to work is mostly down to installing the libraries and setting up the IDE to use them. They’re both very easy to use, if somewhat limited (GLUT was created in order to simplify the programming examples in the Red Book).

If you’re sticking with MFC to simplify porting your existing code … replacing the 2D rendering with OpenGL (or any other 3D API) is likely to be an order of magnitude more work than changing the GUI toolkit. That’s assuming a typical game structure, i.e. creating a single “canvas” window and drawing the user interface yourself. If you’re using MFC for menus, toolbars, dialogs, etc, that’s a different matter.

Most non-trivial examples use GLEW, particularly on Windows. As opengl32.dll only exposes the OpenGL 1.1 API, anything added in later versions either requires using wglProcAddress() to obtain a function pointer (or equivalent functions on other platforms), or using a library such as GLEW to handle that for you. GLEW is almost transparent in use, but has a few gotchas, mainly:

  • GLEW_STATIC must be defined (preferably via a compiler switch so that it’s defined consistently) if you’re using the static library, and must not be defined if you’re using the DLL. Otherwise, you’ll get linking errors.
  • glewInit() needs to be called after a context has been created and made current, but before other OpenGL functions.
  • The <GL/gl.h> and <GL/glu.h> headers must not be used; you need to (consistently) use <glew.h> instead.

If you’re sticking with MFC, I’d start by trying to incorporate the context-management code from one of those examples into the “view” control, and checking that you can actually render something. Even being able to clear the window to a specific colour with glClearColor() and glClear() would be an indication that the context has been created successfully.

[QUOTE=GClements;1280038]Getting FreeGLUT or GLFW to work is mostly down to installing the libraries and setting up the IDE to use them. They’re both very easy to use, if somewhat limited (GLUT was created in order to simplify the programming examples in the Red Book).

If you’re sticking with MFC to simplify porting your existing code … replacing the 2D rendering with OpenGL (or any other 3D API) is likely to be an order of magnitude more work than changing the GUI toolkit. That’s assuming a typical game structure, i.e. creating a single “canvas” window and drawing the user interface yourself. If you’re using MFC for menus, toolbars, dialogs, etc, that’s a different matter.

Most non-trivial examples use GLEW, particularly on Windows. As opengl32.dll only exposes the OpenGL 1.1 API, anything added in later versions either requires using wglProcAddress() to obtain a function pointer (or equivalent functions on other platforms), or using a library such as GLEW to handle that for you. GLEW is almost transparent in use, but has a few gotchas, mainly:

  • GLEW_STATIC must be defined (preferably via a compiler switch so that it’s defined consistently) if you’re using the static library, and must not be defined if you’re using the DLL. Otherwise, you’ll get linking errors.
  • glewInit() needs to be called after a context has been created and made current, but before other OpenGL functions.
  • The <GL/gl.h> and <GL/glu.h> headers must not be used; you need to (consistently) use <glew.h> instead.

If you’re sticking with MFC, I’d start by trying to incorporate the context-management code from one of those examples into the “view” control, and checking that you can actually render something. Even being able to clear the window to a specific colour with glClearColor() and glClear() would be an indication that the context has been created successfully.[/QUOTE]

I have to stick with MFC because the game project for 2D game is done. I use FormView Class and I use MFC for controls on the GUI (mostly buttons and Tree Control). So I was hoping that I could just disable drawing the 2D hex map portion of the window and simply reuse that area for OpenGL. However I plan to release the game with the 2D engine and then focus on the next release that will be only in 3D (either OpenGL, or Directx). So for the next release I can reuse the whole area of the View for 3D graphics - OpenGL. I’m not sure how I will be able to replace the MFC buttons in OpenGL interface; though I’m sure it can be done. It seems GLEW is the way to go for me…all I need to do is find proper GLEW & Win32 example (Win32API can be easily converted to MFC). I can statically link the GLEW library to the game executable, it’s no problem.

I have done a bit more reading about OpenGL vs Directx and it’s unfortunate that OpenGL is not as well supported on Windows as is directx (thanks to mess up in 3D labs and Microsoft). Just for the heck of it, I spent some time yesterday looking at adding Directx11 (VS2013, Win7 Pro) support to my MFC game and it took about 20 minutes - I huge difference I was surprised how accessible Directx is. However, I would still prefer to use OpenGL as I don’t want to be dependent on Microsoft. I use OggVorbis for the game sound for the same reason (rather than using Microsoft Wave files - DirectSound) and currently my game runs on linux under Wine just fine. So if possible, going with OpenGL my game next release should continue to run on Linux - under wine.

U hae=ve