20

I have a texture which has only 1 channel as it's a grayscale image. When I pass the pixels in to glTexImage2D, it comes out red (obviously because channel 1 is red; RGB).

glTexImage2D(
    GL_TEXTURE_2D, 0, GL_RGBA,
    dicomImage->GetColumns(), dicomImage->GetRows(),
    0, GL_RGBA, GL_UNSIGNED_BYTE, pixelArrayPtr);

Do I change GL_RGBA? If so, what to?

Nick Bolton
  • 38,276
  • 70
  • 174
  • 242

4 Answers4

22

Change it to GL_LUMINANCE. See https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
ypnos
  • 50,202
  • 14
  • 95
  • 141
  • 3
    It seems your link is broken. (It redirects to the home page). [glTextImage2D](http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml) works but it doesn't mention GL_LUMINANCE anywhere. It seems they obsoleted it... – Calmarius Dec 03 '13 at 08:10
  • 10
    Deprecated in OpenGL 4.0. But OpenGL 4.0 does not have a fixed function pipeline, you need to bind your own shaders, that's why there is no use in LUMINANCE, ALPHA, etc. any more. You need to use GL_RED and process the single channel accordingly. – ypnos Dec 07 '13 at 02:42
9

in the FragmentShader, you can write:

uniform sampler2D A;
vec3 result = vec3(texture(A, TexCoord).r);

in the cpp file,you can write:

glTexImage2D(
    GL_TEXTURE_2D, 0, GL_RED,
    dicomImage->GetColumns(), dicomImage->GetRows(),
    0, GL_RED, GL_UNSIGNED_BYTE, pixelArrayPtr);
Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
Ming
  • 91
  • 1
  • 1
  • 2
    Can you elaborate a little more and explain what is done by the code snippet? – Gnqz Jan 08 '18 at 09:36
  • 3
    If you want to get greyscale with this function【glTexImage2D()】, you can only adjust the color format parameter to GL_RED. But the effect is red, because only the red channel is taken. Therefore, we can modify the color information of the obtained images in Fragment Shader, so that the value of green channel and blue channel is equal to the value of red channel, so as to obtain the effect of gray image. – Ming Jan 10 '18 at 13:20
  • You should mentioned that `GL_LUMINANCE` was obsoleted and that's why `GL_RED` should be used. – Alexis Wilke Dec 21 '20 at 18:37
1

It appears that I should use GL_LUMINANCE instead of GL_RGBA for the 3rd argument.

Edit (in reply to comments):

When I set the 7th argument to GL_LUMINANCE (as well as the 3rd), the picture goes completely distorted. With the DICOM pixel format, it appears that the 7th argument must be GL_RGBA for some reason.

The strange behavior is because I'm using the DICOM standard. The particular DICOM reader I am using outputs integer pixel values (as pixel values may exceed the normal maximum of 255). For some strange reason the combination of telling OpenGL that I am using an RGBA format, but passing in integer values rendered a perfect image.

Because I was truncating the DICOM > 255 pixel values anyway, it seemed logical to copy the values in to a GLbyte array. However, after doing so, a SIGSEGV (segmentation fault) occurred when calling glTexImage2D. Changing the 7th parameter to GL_LUMINANCE (as is normally required) returned the functionality to normal.

Weird eh?

So, a note to all developers using the DICOM image format: You need to convert the integer array to a char array before passing it to glTexImage2D, or just set the 7th argument to GL_RGBA (the later is probably not recommended).

Community
  • 1
  • 1
Nick Bolton
  • 38,276
  • 70
  • 174
  • 242
  • It is argument #7 that counts here! – ypnos Mar 25 '09 at 03:32
  • Hmm, when change #7, it goes red... but #3 has the desired effect. Can you explain this please? – Nick Bolton Mar 25 '09 at 03:51
  • As ypnos says, arguments 7 and 8 are what you're interested in. They tell OpenGL the format of the data which the pointer points to. The earlier arguments indicate the type of texture, as I recall. – Jay Kominek Mar 25 '09 at 03:53
  • 1
    Nick, argument #3 is for internal storage, #7 is for input format. GL will convert from #7 to #3. The effect you are getting can have several reasons I can't tell from here. In almost every case however you want both be the same anyway. – ypnos Mar 25 '09 at 19:55
0

You would use GL_LUMINANCE format in old versions of openGL, but now in modern 3.0+ OpenGL versions GL_LUMINANCE is deprecated, so new way of doing it is to use GL_RED format, but that would result in a red texture, so to get around this you should create a costum shader as above answers have shown, in that shader you grab red component of the texture, as it's the only one with data you have given and set green/blue channels to red channel's value, that will convert is to grayscale, because grayscale textures have all 3 RGB channels the same and Alpha/Transparency channel set to 1.

G.Azma
  • 37
  • 9