Over the years I've created several frameworks for OpenGL Applications. Although some of them were only a private libraries I've managed to write some code that was actually used by some other people as well. In my previous posts (startup_1, startup_2, startup_3) I described the "first" version of the framework for my workshops. This framework evolved and now I can say that it is in the "third" version.
This post is a description of this new framework.
Design goals
- Be as simple as possible. This means no complex class hierarchies. No complex design patterns.
- Small amount of additional code - the whole pack should be quite small. Students should be able to grab a whole solution (without downloading tens of MB) and quickly compile this.
- Modern OpenGL. My previous frameworks was a mix of OpenGL 2.0 and 3.0... now I wanted to have only 3.+ solution. Unfortunately this involves some third party math library, additional code for shader loading, etc, etc.
- Easy to read and understand.
Components
- C++
- freeGLUT
- GLM
- SOIL
- antTweakBar
- glLoadGen
- custom code: shader loading, shader object wrapper, logger, utils
- VisualStudio 2008, 2010, 2012 - code is based on freeGLUT thus it should be not so hard to compile it under Linux/Mac
Example file structure |
Physical Structure
- app.cpp - source file with custom code for the app (name can be different, like w04_stripes.cpp in the picture on the right)
- main.h/main.cpp - main code for the framework - GLUT init, OpenGL 3.* functions loading, basic GLUT event handling, timer, antTweakBar init & event handling (mouse only).
- addons folder - folder with all the additional libraries - headers and libs - GLM, freeGlut, SOIL library, OpenGL Loader
- commonCode - Shaders, utils and additionally Framebuffer wrappers and Geometry utils
- data and shaders folders
Code structure
main()
1. init_glutGLUT callbacks:
2. set glut callbacks
3. init GL (load extensions, print some basic info)
4. init antTweakBar
5. call initApp() - calls custom function defined in app.cpp file
6. call glutMainLoop()
7. call cleanUp() - cunstom function defined in app.cpp file
8. cleanup additional libs like antTweakBar
callbacks are used to process basic events (like for antTweakBar) and they call custom code defined in app.cpp file.
// window:mainIdle
void mainChangeSize(int w, int h);
// mouse:
void mainProcessMouse(int button, int state, int x, int y);
void mainProcessMouseMotion(int x, int y);
void mainProcessMousePassiveMotion(int x, int y);
updates the timer, calculates fps, calls updateScene and renderScene custom functions
Custom code
{
double deltaTime;
utils::updateTimer(&deltaTime, &Globals::sAppTime);
utils::calculateFps(&Globals::sFps);
updateScene(deltaTime);
renderScene();
TwDraw();
glutSwapBuffers();
}
This is defined in app.cpp file, contains code specific for the particular application.
// init textures, camera, shaders, etc, etc
bool initApp()
void cleanUp();
// window:
void changeSize(int w, int h);
// keyboard:
void processNormalKeys(unsigned char key, int x, int y);
void pressSpecialKey(int key, int x, int y);
void releaseSpecialKey(int key, int x, int y);
// mouse:
void processMouse(int button, int state, int x, int y);
void processMouseMotion(int x, int y);
void processMousePassiveMotion(int x, int y);
// update & rendering (called from mainIdle())
void updateScene(double deltaTime);
void renderScene();
Example Code
// shader loading
ShaderProgram gStripesProgram; // declared as global (not nice!)
shaderUtils::loadAndBuildShaderPairFromFile(&gStripesProgram,
"shaders/stripes.vs",
"shaders/stripes.fs");
// transformations & camera (declared as globals)
glm::vec3 gCamPos;
glm::mat4 gModelViewMatrix;
glm::mat4 gProjectionMatrix;
// in renderScene:
gModelViewMatrix = glm::lookAt(gCamPos, glm::vec3(0.0f, 0.0f, gCamPos[2]-2),
glm::vec3(0.0f, 1.0f, 0.0f));
// shader setup:
gStripesProgram.use();
gStripesProgram.uniform1f("animParam", gAnimParam);
gStripesProgram.uniform1i("texture0", 0);
gStripesProgram.uniformMatrix4f("projectionMatrix",
glm::value_ptr(gProjectionMatrix));
gStripesProgram.uniformMatrix4f("modelviewMatrix",
glm::value_ptr(gModelViewMatrix));
// Tweak:
TwAddVarRW(Globals::sMainTweakBar, "camera Z", TW_TYPE_FLOAT,
&gCamPos[2], "min=0.0 max=12.0 step=0.1");
Screens
Problems
- Use of globals - I do not like usage of global variables, but it is very convenient when creating simple examples for classes.
- C style for most of the framework. C style is quite clean, but maybe C++ (with some classes) would not be so scarry.
Future improvements
- new framework for WebGL? Most of my classes are in C++, but in a future version I could use some other language. Maybe WebGL (thus JavaScript) would be also nice.
Links
- https://github.com/fenbf/startup3 - source code for the framework (without third part libraries)
- wiki - OpenGL_Loading_Library - description of OpenGL function loaders