I want to use a grayscale image generated in OpenCV in a GLSL shader.
Based on the question on OpenCV image loading for OpenGL Texture, I've managed to come up with the code that passes RGB image to the shader:
cv::Mat image;
// ...acquire and process image somehow...
//create and bind a GL texture
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, // Type of texture
0, // Pyramid level (for mip-mapping) - 0 is the top level
GL_RGB, // Internal colour format to convert to
image.cols, image.rows, // texture size
0, // Border width in pixels (can either be 1 or 0)
GL_BGR, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.)
GL_UNSIGNED_BYTE, // Image data type
image.ptr()); // The actual image data itself
glGenerateMipmap(GL_TEXTURE_2D);
and then in the fragment shader I just use this texture:
#version 330
in vec2 tCoord;
uniform sampler2D texture;
out vec4 color;
void main() {
color = texture2D(texture, tCoord);
}
and it all works great.
But now I want to do some grayscale processing on that image, starting with cv::cvtColor(image, image, CV_BGR2GRAY);
, doing some more OpenCV stuff to it, and then passing the grayscale to the shaders.
I thought I should use GL_LUMINOSITY
as the colour format to convert to, and probably as the input image format as well - but all I'm getting is a black screen.
Can anyone please help me with it?
input format
I'd use GL_RED, since the GL_LUMINANCE format has been deprecated
internalFormat
depends on what you want to do in your shader, although you should always specify a sized internal format, e.g. GL_RGBA8 which gives you 8 bits per channel. Although, with GL_RGBA8, the green, blue and alpha channels will be zero anyway since your input data only has a single channel, so you should probably use the GL_R8 format instead. Also, you can use texture swizzling:
which will cause all channels to 'mirror' the red channel when you access the texture in the shader.