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:
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:
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:
glColor3f(0.0f, 0.0f, 1.0f); // Colour our shape blue glBegin(GL_QUADS); // Start drawing a quad … // Vertex information 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:
glBegin(GL_QUADS); // Start drawing a quad glColor3f(1.0f, 0.0f, 0.0f); // Colour our shape blue … // Vertex information glColor3f(0.0f, 1.0f, 0.0f); // Colour our shape blue … // Vertex information glColor3f(0.0f, 0.0f, 1.0f); // Colour our shape blue … // Vertex information glColor3f(1.0f, 1.0f, 1.0f); // Colour our shape blue … // Vertex information 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:
glEnable(GL_COLOR_MATERIAL);
If you have any questions, please email me at swiftless@gmail.com
Tutorial Code
#include <GL/glew.h> // Include the GLEW header file #include <GL/glut.h> // Include the GLUT header file bool* keyStates = new bool[256]; // Create an array of boolean values of length 256 (0-255) void keyOperations (void) { if (keyStates['a']) { // If the 'a' key has been pressed // Perform 'a' key operations } } void renderPrimitive (void) { glColor3f(0.0f, 0.0f, 1.0f); // Set the colour of the square to blue glBegin(GL_QUADS); // Start drawing a quad primitive glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner glEnd(); } void display (void) { keyOperations(); glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red glClear(GL_COLOR_BUFFER_BIT); //Clear the colour buffer (more buffers later on) glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations glTranslatef(0.0f, 0.0f, -5.0f); // Push eveything 5 units back into the scene, otherwise we won't see the primitive renderPrimitive(); // Render the primitive glFlush(); // Flush the OpenGL buffers to the window } void reshape (int width, int height) { glViewport(0, 0, (GLsizei)width, (GLsizei)height); // Set our viewport to the size of our window glMatrixMode(GL_PROJECTION); // Switch to the projection matrix so that we can manipulate how our scene is viewed glLoadIdentity(); // Reset the projection matrix to the identity matrix so that we don't get any artifacts (cleaning up) 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 glMatrixMode(GL_MODELVIEW); // Switch back to the model view matrix, so that we can start drawing shapes correctly } void keyPressed (unsigned char key, int x, int y) { keyStates[key] = true; // Set the state of the current key to pressed } void keyUp (unsigned char key, int x, int y) { keyStates[key] = false; // Set the state of the current key to not pressed } int main (int argc, char **argv) { glutInit(&argc, argv); // Initialize GLUT glutInitDisplayMode (GLUT_SINGLE); // Set up a basic display buffer (only single buffered for now) glutInitWindowSize (500, 500); // Set the width and height of the window glutInitWindowPosition (100, 100); // Set the position of the window glutCreateWindow ("Your first OpenGL Window"); // Set the title for the window glutDisplayFunc(display); // Tell GLUT to use the method "display" for rendering glutReshapeFunc(reshape); // Tell GLUT to use the method "reshape" for reshaping glutKeyboardFunc(keyPressed); // Tell GLUT to use the method "keyPressed" for key presses glutKeyboardUpFunc(keyUp); // Tell GLUT to use the method "keyUp" for key up events glutMainLoop(); // Enter GLUT's main loop }
Thank you very much , it is really helpfull 🙂
Bad tutorials. OpenGL 2.0 support shaders man, so you should use shaders, don’t use fixed functions!
Hi Dario90,
I’m going to approve this for fun. Check out the GLSL tutorials (using OpenGL 2.x). Avoiding fixed functions makes no sense for beginners wanting to learn about computer graphics in general.
Also if you really want shaders and to avoid fixed functions, feel free to look at the OpenGL 4.x tutorials where we do just that (OpenGL 4.x has removed the fixed functions).
Thanks,
Swiftless
Your tutorials are absolutely wonderful.
Thank you dearly for them.
-kropcke
Thnx a lot buddy,
Got what actually needed.
Great Work
Thanks a lot for these tutorials 🙂
Hi
Is it possible to alter vertex colors after you have built the mesh?
Thanks for your effort.
Hi, noticed a little mistake in the title window- I assume it should be “Your first openGL window” instead of “You’re first openGL window” (You are first openGL window).
Hey Ruud,
Thanks for that, now everyone has seen my spelling fail. I’m usually quite good in that regard, and now it’s in every tutorial 😀
Cheers,
Swiftless
You made some mistake at the commenting: When you say you set each vertex of a quad to different colors, you always write “// Colour our shape blue” in the code.
Greetings
Cheers, I’ll try fixing it up soon, that would be a copy and paste error 🙂
Swiftless
Glad you got it worked out 🙂
Swiftless
oh i see my mistake, i didnt have the blending enabled, re-read the article.
glEnable(GL_BLEND); //enable the blending
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
just needed to add those lines to my display method
when i use glColor4f the alpha value doesnt seem to do anything
//in display method
if(selected == i){
cube(x[i], y[i], z[i], r[i], g[i], b[i], 0.3);
}
else {
cube(x[i], y[i], z[i], r[i], g[i], b[i], 1);
}
void cube (float x, float y, float z, float r, float g, float b, float a) {
glPushMatrix();
glTranslatef(x, y, z);
glColor4f(r, g, b, a);
glutWireCube(1);
glPopMatrix();
}
ive made sure the selection works properly by changing the color instead of the alpha value, but yet when i make it change just the alpha it doesnt work
any idea?