2D C++ OpenGL/GLFW Basecode

I’m teaching some games programming stuff this year, and we’d started off using SDL, but the students are having a hard time with it – the main problems being:
– It’s bulky,
– It demands control of the mainline and then bloats it,
– The documentation is okay, but significantly less than stellar.

This isn’t to say that I have much against SDL – it does a lot of good things, but I’m concerned it’s providing too much specific functionality, which I don’t want to rely on and be tied to when (not if) things change in the future. So with this in mind, I’ve spent the evening reading about OpenGL frameworks and have decided to take the class in a new direction – namely GLFW, the cross-platform OpenGL framework.

We’re mainly going to be working in 2D, so I’ve put together some OpenGL/GLFW basecode that initialises a window, sets orthogonal projection (i.e. things further away don’t get any smaller) and just draws a line from the top-left to the bottom-right (so is easy to strip out when you want to adapt it to your own purposes) – and the entire thing is only around 100 lines of code! (and that’s with stacks of whitespace). The equivalent in SDL is closer to 350 lines and is significantly more complex/complex-looking.

Check it out…

  1. // OpenGL/GLFW Basecode | r3dux
  3. #include <iostream>
  4. #include <GL/glfw.h> // Include OpenGL Framework library
  5. using namespace std;
  7. void initGL(int width, int height)
  8. {
  9. 	// ----- Window and Projection Settings -----
  11. 	// Set the window title
  12. 	glfwSetWindowTitle("GLFW Basecode");
  14. 	// Setup our viewport to be the entire size of the window
  15. 	glViewport(0, 0, (GLsizei)width, (GLsizei)height);
  17. 	// Change to the projection matrix, reset the matrix and set up orthagonal projection (i.e. 2D)
  18. 	glMatrixMode(GL_PROJECTION);
  19. 	glLoadIdentity();
  20. 	glOrtho(0, width, height, 0, 0, 1); // Paramters: left, right, bottom, top, near, far
  22. 	// ----- OpenGL settings -----
  24. 	glfwSwapInterval(1); 		// Lock to vertical sync of monitor (normally 60Hz, so 60fps)
  26. 	glEnable(GL_SMOOTH);		// Enable (gouraud) shading
  28. 	glDisable(GL_DEPTH_TEST); 	// Disable depth testing
  30. 	glEnable(GL_BLEND);		// Enable blending (used for alpha) and blending function to use
  33. 	glLineWidth(5.0f);		// Set a 'chunky' line width
  35. 	glEnable(GL_LINE_SMOOTH);	// Enable anti-aliasing on lines
  37. 	glPointSize(5.0f);		// Set a 'chunky' point size
  39. 	glEnable(GL_POINT_SMOOTH);	// Enable anti-aliasing on points
  40. }
  42. void drawScene()
  43. {
  44. 	// Clear the screen
  45. 	glClear(GL_COLOR_BUFFER_BIT);
  47. 	// Reset the matrix
  48. 	glMatrixMode(GL_MODELVIEW);
  49. 	glLoadIdentity();
  51. 	// ----- Draw stuff! -----
  53. 	glBegin(GL_LINES);
  54. 		glColor3ub(255, 0, 0);
  55. 		glVertex2f(0.0f, 0.0f);
  57. 		glColor3ub(0, 0, 255);
  58. 		glVertex2f(800.0f, 600.0f);
  59. 	glEnd();
  61. 	// ----- Stop Drawing Stuff! ------
  63. 	glfwSwapBuffers(); // Swap the buffers to display the scene (so we don't have to watch it being drawn!)
  64. }
  66. int main()
  67. {
  68. 	// Frame counter and window settings variables
  69. 	int frame      = 0, width     = 800, height      = 600;
  70. 	int redBits    = 8, greenBits = 8,   blueBits    = 8;
  71. 	int alphaBits  = 8, depthBits = 0,   stencilBits = 0;
  73. 	// Flag to keep our main loop running
  74. 	bool running = true;
  76. 	// Initialise glfw
  77. 	glfwInit();
  79. 	// Create a window
  80. 	if(!glfwOpenWindow(width, height, redBits, greenBits, blueBits, alphaBits, depthBits, stencilBits, GLFW_WINDOW))
  81. 	{
  82. 		cout << "Failed to open window!" << endl;
  83. 		glfwTerminate();
  84. 		return 0;
  85.     	}
  87. 	// Call our initGL function to set up our OpenGL options
  88. 	initGL(width, height);
  90. 	while (running == true)
  91. 	{
  92.     		// Increase our frame counter
  93.         	frame++;
  95. 		// Draw our scene
  96. 		drawScene();
  98. 		// exit if ESC was pressed or window was closed
  99. 		running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam(GLFW_OPENED);
  100. 	}
  102. 	glfwTerminate();
  104. 	return 0;
  105. }

How streamlined is that?!? Sweeeeeeet!

Next task – do stuff with it! =D

P.S. If you wanted to add GLEW to it to take care of all your extension wrangling needs, then just add the glew.h header before glfw.h, include the glew library in your project and add the following to the top of the initGL function:

//  ----- Initialise GLEW -----
GLenum err = glewInit();
if (GLEW_OK != err)
	cout << "GLEW initialisation error: " << glewGetErrorString(err) << endl;
cout << "GLEW intialised successfully. Using GLEW version: " << glewGetString(GLEW_VERSION) << endl;


Update: Modified initGL() function to disable the depth testing correctly via glDisable(GL_DEPTH_TEST) and not glDisable(GL_DEPTH) – silly mistake.

How To: Create a Simple Fireworks Effect in OpenGL and SDL

I’m teaching the programming stream for Diploma in I.T. – Multimedia at the moment, so we’re going to be making some simple games and things over the next couple of months, but to start them off we’re doing a little bit of work on particle effects because they’re simple and fun – you just write a single class which describes the properties and behavior of your particle, and then scale it up by adding a large number of particles to get some pretty nice effects.

So instead of doing a particle fountain, I thought some fireworks might be kinda neat… Take a swiz at the video below and see what you think!

Full C++ source-code available after the break for those of a curious nature =D

Continue reading How To: Create a Simple Fireworks Effect in OpenGL and SDL

How To: Draw Motion-Blur/Trails using the Accumulation Buffer in OpenGL

I read that this is the slow/old-school/borderline-retarded way of going about adding motion blur to your scenes, but I haven’t started learning GLSL yet, so for the time being at least, this works :D

OpenGL Accumulation Buffer Motion-Blur/Trails

The trick is that you have to perform the following actions in this specific order in your drawing function for it to work:

  1. Clear the colour buffer (i.e. the screen) and the depth buffer (really, the colour buffer doesn’t need to be cleared because we’re over-writing it later, but the depth buffer definitely does!).
  2. Copy the accumulation buffer over the top of the colour buffer. (i.e. the contents of the colour buffer gets overwritten with the contents of the accumulation buffer).
  3. Clear the accumulation buffer.
  4. Draw your geometry.
  5. Copy the colour buffer onto the accumulation buffer. (i.e. the contents of the accumulation buffer gets overwritten with the contents of the colour buffer).

The relevant section of code from my drawScene() function is:

    // Clear the draw and depth buffers
    // Take the contents of the current accumulation buffer and copy it to the colour buffer with each pixel multiplied by a factor
    // i.e. we clear the screen, draw the last frame again (which we saved in the accumulation buffer), then draw our stuff at its new location on top of that
    glAccum(GL_RETURN, 0.95f);
    // Clear the accumulation buffer (don't worry, we re-grab the screen into the accumulation buffer after drawing our current frame!)
    // Translate everything into the screen (z-axis) by -windowDepth
    glTranslatef(0.0f, 0.0f, -windowDepth);
    // Apply oscillating rotation to the matrix around the Z-axis.
    // Multiplying by 100 is just a fudge factor to increase the total rotation amount
    glRotatef(cos(deg2rad(Star::rotationAmount)) * 100, 0.0f, 0.0f, 1.0f);
    vector<star>::iterator starIter; // This needs to be a standard iterator not a constant iterator so we can modify what's being pointed to!!
    // Do the actual drawing...
    for (starIter = stars.begin(); starIter != stars.end(); starIter++)
        // Change the point size to the stars size property
        glBegin(GL_POINTS); // This needs to be inside the loop so the PointSize change (above) takes effect
            // Set the colour
            glColor3f(starIter->getRedComponent(), starIter->getGreenComponent(), starIter->getBlueComponent());
            // Draw the point
            glVertex3f(starIter->getX(), starIter->getY(), starIter->getZ());
        // Move the star closer (or reset it if it's too close) ready for the next frame
    // Swap the buffers so we can see what we've drawn without -watching- it being drawn

Note: See that </star> tag at the end of the above code snippet? That doesn’t exist. It’s an artifact produced by WordPress in combination with the WP-Syntax plugin and is somehow related (I think) to escaping HTML entities and auto-completion of mismatching XHTML. Don’t believe me? Click the title of the post or the read more link below and find the same section of code in the full listing – for some reason it doesn’t appear there… Odd, huh?

Update: Uploaded a screen capture of the program running to YouTube so you can see it in action without having to compile it yourself:

Full source-code available after the jump for those interested…

Continue reading How To: Draw Motion-Blur/Trails using the Accumulation Buffer in OpenGL

OpenGL: Chequered Tunnel

Did a bit of coding a little while back, just to use some stuff I’d been reading in my OpenGL books – so, I made a tunnel out of triangles which looks like this…


It comes towards you, the vanishing point pulses and the colours change etc. Also, it’s documented to the hilt, so you too can create simplistic, uninspiring graphical knick-knacks!

Let there be light!

Linux binary + src and makefile for Tunnel prog