5. OpenGL Color (Version 2.0)

Introduction

A world without colour is a very dull world indeed. Colour makes up absolutely everything you see and without it, everything would either be a shade of grey, or just black. Luckily for us, this most fundamental component in any art form is standard in every graphics library, and even luckier for us, is the initial simplicity involved in setting and changing colours in OpenGL.

Colour Models

First we’ll have a look at some different colour models. There are many ways to describe colour in computer graphics. You may have a CMYK printer for example, which stores colours according to their Cyan, Magenta, Yellow and Key (black) values, or you may have a printer with an RGB cartridge, which takes Red, Green and Blue values, often with a separate cartridge for black. Then there are other formats such as HSL and HSV which stand for Hue, Saturation and Luminance or Value. You may have noticed the ability in some image editors to set the Hue and Saturation values, and they may refer to Luminance and Value as the Brightness.  Then there is YUV which is often used for cameras, and it is harder to describe. The Y value determines how bright the colour is, while the U and V values determine the colour. YUV is used because it uses less storage and therefore less bandwidth in cameras.

Coding

For most of us, we find it easiest to interpret colours in their RGB format, and OpenGL also works using this method. Now you may have used an image editor, where your RGB colours will range from 0 to 255. OpenGL works using colour values from 0 to 1, but you can interchange between both by either multiplying your OpenGL colour by 255, or dividing your other colour method by 255.

To give an example to get the following colours, you need the corresponding RGB values:

Red – (Red – 1.0f, Green – 0.0f, Blue – 0.0f)

Green – (Red – 0.0f, Green – 1.0f, Blue – 0.0f)

Blue – (Red – 0.0f, Green – 0.0f, Blue – 1.0f)

White – (Red – 1.0f, Green – 1.0f, Blue – 1.0f)

Black – (Red – 0.0f, Green – 0.0f, Blue – 0.0f)

Yellow – (Red – 1.0f, Green – 1.0f, Blue – 0.0f)

Pink (Magenta) – (Red – 1.0f, Green – 0.0f, Blue – 1.0f)

OpenGL provides us with several methods for setting the colours of shapes. There are methods that take 3 inputs, each one corresponding to Red, Green or Blue, and there are other methods that take 4 inputs, which relate to the Red, Green, Blue and Alpha values for our colours.

Now in order for you to set a colour, you can call one of these methods, with something similar to:

  1. glColor3f(r, g, b);  

Where the 3 stands for 3 colours, red, green and blue, and the f stands for a float, and tells OpenGL we are wanting to use float values to represent our colours. OpenGL also provides methods for using doubles, integers, bytes and shorts.

You will only ever want to use the Alpha value if you have some sort of blending enabled in your application, but once you have blending setup, setting colours with alpha values is as simple as:

  1. glColor4f(r, g, b, a);  

Keep in mind that the alpha value also ranges from 0.0 to 1.0, with 0.0 being completely transparent or see-through and 1.0 being completely opaque or filled.

In OpenGL fashion, there are also versions of these methods that can take arrays of values. But I won’t look into them.

Now if you remember that OpenGL is based on state machines, when you set a colour, you are setting the colour of everything that you draw since you made the call to glColor. Keep this in mind if you choose to draw something first, and then find that all your shapes are now this colour. You will have to set the colour of each shape separately.

As for when you set the colour of the shape, you have two options. You can either set the entire colour of the shape by calling glColor3f before you call glBegin, like so:

  1. glColor3f(0.0f, 0.0f, 1.0f); // Colour our shape blue  
  2.   
  3. glBegin(GL_QUADS); // Start drawing a quad  
  4. … // Vertex information  
  5. glEnd(); // Finish drawing our quad  

Or you can set the colour of you shape on a per-vertex basis. This means you could set one vertex to red, another to green, another to blue and a fourth one to white, and have them all interpolate over the entire shape like so:

  1. glBegin(GL_QUADS); // Start drawing a quad  
  2. glColor3f(1.0f, 0.0f, 0.0f); // Colour our shape blue  
  3. … // Vertex information  
  4. glColor3f(0.0f, 1.0f, 0.0f); // Colour our shape blue  
  5. … // Vertex information  
  6. glColor3f(0.0f, 0.0f, 1.0f); // Colour our shape blue  
  7. … // Vertex information  
  8. glColor3f(1.0f, 1.0f, 1.0f); // Colour our shape blue  
  9. … // Vertex information  
  10. glEnd(); // Finish drawing our quad  

That is basically all there is to it, but I feel compelled to share the following information. If you happen to enable lighting in your OpenGL application and expect to find your colours still work, then by default you will be a little disappointed. However there is a fix for this and it is actually an OpenGL state that you can enable, called GL_COLOR_MATERIAL which sets your shapes material information to be that of the colour you assigned to it. You can enable this when you initialize your OpenGL state with:

  1. glEnable(GL_COLOR_MATERIAL);  

If you have any questions, please email me at swiftless@gmail.com

Tutorial Code

  1. #include <GL/glew.h> // Include the GLEW header file  
  2. #include <GL/glut.h> // Include the GLUT header file  
  3.   
  4. bool* keyStates = new bool[256]; // Create an array of boolean values of length 256 (0-255)  
  5.   
  6. void keyOperations (void) {  
  7. if (keyStates['a']) { // If the 'a' key has been pressed  
  8. // Perform 'a' key operations  
  9. }  
  10. }  
  11.   
  12. void renderPrimitive (void) {  
  13. glColor3f(0.0f, 0.0f, 1.0f); // Set the colour of the square to blue  
  14.   
  15. glBegin(GL_QUADS); // Start drawing a quad primitive  
  16. glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner  
  17. glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner  
  18. glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner  
  19. glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner  
  20. glEnd();  
  21. }  
  22.   
  23. void display (void) {  
  24. keyOperations();  
  25.   
  26. glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red  
  27. glClear(GL_COLOR_BUFFER_BIT); //Clear the colour buffer (more buffers later on)  
  28. glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations  
  29.   
  30. glTranslatef(0.0f, 0.0f, -5.0f); // Push eveything 5 units back into the scene, otherwise we won't see the primitive  
  31.   
  32. renderPrimitive(); // Render the primitive  
  33.   
  34. glFlush(); // Flush the OpenGL buffers to the window  
  35. }  
  36.   
  37. void reshape (int width, int height) {  
  38. glViewport(0, 0, (GLsizei)width, (GLsizei)height); // Set our viewport to the size of our window  
  39. glMatrixMode(GL_PROJECTION); // Switch to the projection matrix so that we can manipulate how our scene is viewed  
  40. glLoadIdentity(); // Reset the projection matrix to the identity matrix so that we don't get any artifacts (cleaning up)  
  41. gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes  
  42. glMatrixMode(GL_MODELVIEW); // Switch back to the model view matrix, so that we can start drawing shapes correctly  
  43. }  
  44.   
  45. void keyPressed (unsigned char key, int x, int y) {  
  46. keyStates[key] = true// Set the state of the current key to pressed  
  47. }  
  48.   
  49. void keyUp (unsigned char key, int x, int y) {  
  50. keyStates[key] = false// Set the state of the current key to not pressed  
  51. }  
  52.   
  53. int main (int argc, char **argv) {  
  54. glutInit(&argc, argv); // Initialize GLUT  
  55. glutInitDisplayMode (GLUT_SINGLE); // Set up a basic display buffer (only single buffered for now)  
  56. glutInitWindowSize (500, 500); // Set the width and height of the window  
  57. glutInitWindowPosition (100, 100); // Set the position of the window  
  58. glutCreateWindow ("Your first OpenGL Window"); // Set the title for the window  
  59.   
  60. glutDisplayFunc(display); // Tell GLUT to use the method "display" for rendering  
  61.   
  62. glutReshapeFunc(reshape); // Tell GLUT to use the method "reshape" for reshaping  
  63.   
  64. glutKeyboardFunc(keyPressed); // Tell GLUT to use the method "keyPressed" for key presses  
  65. glutKeyboardUpFunc(keyUp); // Tell GLUT to use the method "keyUp" for key up events  
  66.   
  67. glutMainLoop(); // Enter GLUT's main loop  
  68. }  
  • March 25, 2010
  • 15