Cheking the Color
Checking the color of the pixel where the mouse was clicked involves reading that same pixel from the back buffer. This can be accomplished using the following function:
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
x,y : the bottom left corner
width, length: the size of the area to be read
format: The type of data to be read. In here it is assumed to GL_RGB.
type: the data type of the elements of the pixel. In here we'll use GL_UNSIGNED_BYTE.
pixels: An array where the pixels will be stored. This is the result of the function
Both format and type have a lot of other possibilities, check the Red or Blue books for more information.
Just as when using the OpenGL API it is necessary to invert the y coordinate. Reading the viewport information is therefore also required when using this approach. After getting the viewport info, it is possible to call glReadPixels as shown in the code bellow. The x and y parameters represent the cursor position. Width and height are both set to one since only a single pixel is being read. Afterwards it is just a matter of checking the values of the pixel.
void processPick ()
printf("%d %d %d\n",pixel,pixel,pixel);
if (pixel == 255)
printf ("You picked the 1st snowman on the 1st row");
else if (pixel == 255)
printf ("You picked the 1st snowman on the 2nd row");
else if (pixel == 255)
printf ("You picked the 2nd snowman on the 1st row");
else if (pixel == 250)
printf ("You picked the 2nd snowman on the 2nd row");
printf("You didn't click a snowman!");
To get this approach running without problems there are a few things that you should be aware. First set your colors using unsigned bytes as opposed to floats. When in RGB mode there are only 256 possible values for each component, so when you set a color using floats OpenGL will pick the nearest color possible. Secondly make sure your monitor is set to True Color. Otherwise the color presented on screen is only an approximation to the required color and therefore when reading back the pixels there is a possibility that the values wont match with the set values. Finally make sure you disable dithering, lighting and texturing for the color coded rendering function, since any of these operations may change the original color.
If you really want to work with floats to set the color, or you can't guarantee that the monitor will be set to True Color then you can always to a test to check what the specified colors will look like when rendered.
This approach requires that before your application starts you must render blocks of the requested colors and read them back using glReadPixels to get the real rendered colors. Store those colors in an array and use them instead of the colors you specified when rendering.
Be careful when choosing the colors though. If the values for each component are not set sufficiently apart then the may turn out to be the same color when rendered. For instance when setting the red component to 250, using unsigned bytes, with the monitor set to High Color instead of True Color, you actually get a red component of 255. This is because there are less possible values for each component when using only 16 bits to specify a color instead of 32 or 24. Check out the pixel packing values in the Red Book to find out about the possible combinations of bits for each component with 16 bits.