Change GL_RGBA8 (which makes grayscale images with no alpha ) to GL_INTENSITY :
glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, 16, 16, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer);
The GL_RGBA8 format created using GL_LUMINANCE gives the pixels of the form (Y, Y, Y, 1) , but GL_INTENSITY with GL_LUMINANCE gives (Y, Y, Y, Y) .
You will also want to change your blending mode to suggest that pre-multiplied alpha, for example. the change
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
in
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Alternative:
You can also use GL_ALPHA and then use the normal blending mode for non-multiplex alpha:
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 16, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
Alternative No. 2:
You can continue to use GL_LUMINANCE and change the blending mode.
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
This has the disadvantage that you cannot paint the texture without using something like glBlendColor (which is not part of the OpenGL headers that come with MSVC, so you need to use GLEW or something like that):
glBlendColor(...); glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
Alternative No. 3:
Use OpenGL 3 and modify your fragment shader to process single-channel textures as desired.