Display Red channel of a texture as luminance ?

Started by
16 comments, last by Majestik666 18 years, 9 months ago
Hi, for a simple application I have textures loaded as RGB in memory and I need to be able to display separatly the three channels R,G,B I can get this to work using PixelTransferf , i.e. the Red channel is displayed as a red scaled image, but instead I'd like this R channel to be displayed as a greyscaled image: now my texture looks like (r,0,0) and i want (r,r,r) Is there a simple way to get this ? not using cg or etc :) Thanks a lot ! Francois
Advertisement
Not sure from where you start and where you want to get. Do you have an image loaded, and only want to load the red channel as a greyscale texture (case 1), or do you have an existing texture, and you want to display only the red channel of this texture (case 2)?

I can explain both cases anyway.

1: Using glPixelTransfer, you can set the blue and green scale to zero, and then upload the image as a texture using GL_LUMINANCE as internal format, and GL_RGB as external format. In this case, the final intensity will be the sum of all color channels after scaling and bias as set by glPixelTransfer. Since you set the scale to zero for green and blue, only the red channel will contribute to the final intensity.

This means the texture, once created, it fixed. If you want another channel, you have to redo this process and upload new image data (actually, the same data, but with different scale factors for the pixel transfers).

2: You can use the dot product texture combiner function to calculate a weighted sum of all channels. For example, you can set the combiners to output the dot product of the texture color and a constant color, where the constant color acts as the channel weights. For example, If you set the constant color to RGB=(1, 0, 0), only the red channel will contribute to the final output.

Check out the ARB_texture_env_dot3 and ARB_texture_env_combine extension specification for information on how to use the dot product combiner function. You can set the function to GL_DOT3_RGB, sources to GL_TEXTURE and GL_CONSTANT, and then set the weights using glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, w), where w is an array of 4 floats containing the weights.

This allows you to use an arbitrary texture and extract an arbitrary channel at any time by just updating the constant color. VERY efficient compared to case 1 if you're after per-frame changes of the weights or similar.

The weights, aswell as the scale factors in case 1, can of coruse be set to calculate an arbitrary weighted sum, given proper weights for each channel. It's not just to extract a particular channel.
Hi,

sorry for the lack of details in my question...
I actually achived to get it to work the way you said in case 1.
using glPixelTransfer and GL_LUMINANCE mode.
But the glPixelTransfer functions slows down the rendering a lot...
it that normal ? or any way to speed it up ?

EDIT: oops sorry didn't read the second part of your post about efficiency
will try the second method now !
the biggest bottle neck is actually not the glPixelTransfer function
but setting the internal format to GL_LUMINANCE
Thanks a lot for all that !

Cheers
Francois

[Edited by - Majestik666 on July 23, 2005 8:04:41 PM]
maybe you should seperate them into three different textures, one R, one G, and one B, and you can upload them each as GL_LUMINANCE textures and don't have to worry about the glPixelTransfer.

If not you can do it with a matrix:

http://www.opengl.org/resources/tutorials/advanced/advanced98/notes/node185.html#SECTION000142430000000000000
"It's such a useful tool for living in the city!"
instead of splitting my textures in 3 (can't really do that ,,)
I'm trying to workout the dot3 solution but get a small problem ,
if i'm correct when doing a dot 3 , the result is :
r = 4*((r0-0.5)*(r1-0.5)+(g0-0.5)*(g1-0.5)+(b0-0.5)*(b1-0.5));

in my case the r1,g1,b1 vector will always have a 1 and two 0s
so for example to display the red channel :
r = 4*(r0-0.5)*(1-0.5);

so my resulting red value won't be in [0..1] anymore
but in [-0.5..0.5] ??
how can i go back to the [0..1] value from there ??
Thanks a lot !!!
Francois
Now that you mentioned the 0.5 offset in the dot product equation, which I should have noticed myself, I doubt it's doable using the set of functions I mentioned in my post. Depending on how far you want to go, you could try some more advanced, but also vendor specific, sets of functions, like NV_tegister_combiners. Other than that, or shaders, I currently don't see any way to do this. But I may be missing something obvious.
yeah i've been trying a LOT with all kind of tricks to get
it back correctly it doesn't seem i can do it this way...
(maybe i'm missing something myself !)
I was also thinking again about the idea that someone expressed
before, splitting the channels ..
but if my final buffer is :

RRRR...RRRGGGG....GGGGBBB....BBBBAAAA....AAAA

is there anyway to display this texture as a classic
RGB or RGBA texture ?

Thanks !
Francois
Why can't you just create 3 luminance textures from the RGB texture?
Can't do it because of the time ...
I will use image sequences etc..
and need as much speed as i can ,
so it has to be a simple post process!
If the bottleneck is switching to GL_LUMINANCE, then use a RGB texture instead. EDIT : glPixelTransfer scaling won't work for this, use the GL_COLOR matrix when building the texture.

[Edited by - trippytarka on July 24, 2005 8:00:09 AM]

This topic is closed to new replies.

Advertisement