PDA

View Full Version : glTexSubImage2D - independent RGB component update



Ondras
10-23-2010, 08:33 AM
I am using quite large RGB texture:

glTexImage2D(GL_TEXTURE_2D, 0, 3, 8192, 8192, 0, GL_LUMINANCE, GL_BYTE, NULL);

This texture is used to visualize live data from special HW scanner, which provides the data continuously (usually couple of scan lines every 10-50 ms). I am collecting the scans in buffer and then updating the texture in visualization thread by:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, currentScanLine, 8192, numScanLines, GL_LUMINANCE, GL_BYTE, scans);
currentScanLine = (currentScanLine + numScanLines) % 8192;

It works perfectly.



As a next step I wanted to visualize data from two or three scanners at the same time. My Idea was to use RGB texture and update individual RGB components (each component for one scanner). So, I created RGB texture:

glTexImage2D(GL_TEXTURE_2D, 0, 3, 8192, 8192, 0, GL_RGB, GL_BYTE, NULL);

and updated it:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, currentScanLine, 8192, numScanLines, GL_RED, GL_BYTE, scans);

The problem is that even I am updating only one component (RED), the other components (GREEN and BLUE) are overwritten by zeros. I was playing with
glPixelTransferf(GL_GREEN_SCALE, 0.0f);
glPixelTransferf(GL_BLUE_SCALE, 0.0f);
but it doesn't help. The othter components are always overwritten. I want them to stay untouched. Is there any way to do accomplish that?
I know can use separate texturue for each scanner and combine them in pixel shader but it is more complicated and probably more GPU time consuming solution.

Any help appreciated.

ZbuffeR
10-23-2010, 10:07 AM
You do not have any other option.

BionicBytes
10-23-2010, 01:18 PM
You can't do want you are attempting. You could merge those three streams into a cache buffer and upload that to GL

mfort
10-24-2010, 12:20 AM
I was playing with
glPixelTransferf(GL_GREEN_SCALE, 0.0f);
glPixelTransferf(GL_BLUE_SCALE, 0.0f);
but it doesn't help.

This is probably not HW accelerated. (read: slow)



I know can use separate texturue for each scanner and combine them in pixel shader but it is more complicated and probably more GPU time consuming solution.


Use fragment shader.This is perfect solution for you. Do not worry about GPU load. The shader to combine 3 textures is 3 lines long. This is really very simple shader.

mhagain
10-24-2010, 06:14 AM
Another vote for the fragment shader. At that kind of texture size I presume that you have reasonably modern hardware available, so the 3-textures-with-fragment-shader approach shouldn't even come close to stressing it. The only real bottleneck you would have would be in your glTexSubImage2D function, in fact, and selecting formats and types for your textures that more closely match how they are actually stored in hardware will resolve most of that. Using a fragment shader would add some interesting possibilities here too, like being able to pack 4 luminance texels into 1 BGRA texel, allowing you to quarter the size of your textures (2048x8192 may be the most useful quartering).

nickels
10-24-2010, 10:12 AM
i.e. 3 textures of type GL_LUMINANCE (better choice, maybe??) (1d textures). Update 1 at a time, but then use a fragment shader to combine them:

red = texture2D(redTex, uv);
grn = texture2D(grnTex, uv);
blu = texture2D(bluTex, uv);

gl_FragColor = vec4(red.r, grn.r, blu.r, 1.0);

Ondras
10-24-2010, 02:36 PM
Thanks for your suggestions. I will write the fragment shader to mix textures at GPU. Hope that accessing three textures instead of one won't slow it down much.

As you also suggested, the same merge can be done at CPU. Scans are received by collecting threads and copied to buffer anyway. So instead of using standard memcpy there would be custom copy with 3 byte destination increment to do the merge into RGB array and then update RGB texture. I would probably do it this way because have little experience with shaders but then I found another issue - asynchronous data reception. Sometimes one of the scanners delays its data so there would be slow visualization response when waiting for that data to merge them. If I still want fast visualization response, I must update the texture repeatedly after delayed data come. At worst case, when two scanners are delayed by different amount of time, the same part of texture must be rewritten 3 times by full RGB data. With three independent textures and shader this is not an issue.

Yes, I must also experiment with different texture formats. I am not sure if GL_LUMINACE is the right one. According to this http://forums.nvidia.com/index.php?showtopic=165569 it was deprecated in OpenGL 4.0. They recommend GL_RED instead. If I use GL_BGRA (very common and probably fast) with only 2048x8192 textutre I have really no idea how to decompose it in fragment shader.

Just one more question. Is there some default vertex shader or do I have to write one as well?

nickels
10-25-2010, 09:41 AM
I am not sure if GL_LUMINACE is the right one. According to this http://forums.nvidia.com/index.php?showtopic=165569 it was deprecated in OpenGL 4.0. They recommend GL_RED instead.

Just one more question. Is there some default vertex shader or do I have to write one as well?


Thanks for the link, I learned something as well!!
Regarding shaders; once you start with them you will never want to go back ;) !!