PDA

View Full Version : Delay in texture 2D slicing

Kal Mar
09-28-2010, 10:12 AM
Hi all,

I am showing a sequence of slices, from back to front, of volume data using 2D textures.

I would show each texture at intervals, say, 0.25 seconds, so you notice the volume, as if in slow motion (delay).

Any idea for implement it ?

BionicBytes
09-29-2010, 07:51 AM
If your h/w and drivers support it (i.e. you have ARB_TEXTURE_ARRAY or OpenGL 3.0) I would suggest converting the sequence of 2D textures into a 2D_TEXTURE_ARRAY. If you dont have this feature, then convert the sequence into a 3D texture.
Then, the slice you wish to view can be controlled via the 3rd texture coordinate. For Texture arrays the 3rd coordinate is just the slice number (0,1,2,3,5,...n). For 3D textures you use the following formula:

3rd coord = (2.0 * slice) + 1.0 / (max slices * 2.0)

If you need mipmapping, then Texture_Array is the way to go as each slice can have it's own mipmaps. If you need to lerp between slices I would suggest a pixel shader reads slice[n] and slice[n+1] and just linearly interpolates between them.
With 3D textures you can get that effect for free just by increamenting the 3rd texture coordinate and the h/w will 'blend' between the 3D layers. The downside is that 3D textures don't have mipmaps for each slice - which may or may not be a problem for you.

As an example, let's say you have 8 slices in your 3D texture. The 3rd texture coordinate for the first slice will be (2 * 0 + 1) / 16 = 1/16; the second slice = 3/16; 3rd slice = 5/16; 8th slice = 15/16.
So to lerp between slice 2 and slice 3, you just need to increament the 3rd coordinate by some small value, eg 0.01 to take the value from 0.1875 to 0.3125. Personally I'd take the difference and divide by the number of 'animation steps' you want.

varying vec2 texco; //your usual texture coordinates
uniform float slice; //3rd texture coordinate
uniform float lerpfactor; //amount to lerp between slice 1 and slice 2. Value between 0.0 -> 1.0

vec4 slice1 = texture2DArray(volumedata, vec3 (texco.st, slice) );
vec4 slice2 = texture2DArray(volumedata, vec3 (texco.st, slice + 1.0) );

gl_FragData = mix (slice1, slice2, lerpfactor);

Kal Mar
09-29-2010, 10:18 AM
Thanks, BionicBytes.

I can render the volume, but the volume data is all about in black in a cube.
I tried to show only a slice, and I can see the data, but everything around it is black, so in general, all the volume is wrapped in black.

I implemented your suggestion, my card supports 3D texture.

I tried many ways to blend, but I can not see the volume inside.

There is a way to show a picture of a slice in this forum?

My code is:

glEnable(GL_BLEND);
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); //defines blending factors
int slice;
double Pos = -1.0;
double Step = 2.0 / (double) (ZDIM);

for (slice = 0; slice <= ZDIM; ++slice) {
glTexCoord3d(0.0, 0.0, (Pos + 1.0) / 2.0); //Normalize texture coordinate
glVertex3d(-1.0, -1.0, Pos);
glTexCoord3d(1.0, 0.0, (Pos + 1.0) / 2.0);
glVertex3d(1.0, -1.0, Pos);
glTexCoord3d(1.0, 1.0, (Pos + 1.0) / 2.0);
glVertex3d(1.0, 1.0, Pos);
glTexCoord3d(0.0, 1.0, (Pos + 1.0) / 2.0);
glVertex3d(-1.0, 1.0, Pos);

glEnd();
Pos += Step;
}

BionicBytes
09-30-2010, 05:22 AM
I can render the volume, but the volume data is all about in black in a cube.
I tried to show only a slice, and I can see the data, but everything around it is black, so in general, all the volume is wrapped in black.

I must confess; I'm not clear what you are saying. Are you saying the image data you want is in the middle of the texture and the pixels around that are all coloured black?
Do your images have an alpha channel component? If they don't then when loading the textures I suggest you copy the RGB channels (convert to greyscale) and set the alpha channel to this value. When rendering, you can enable alpha test to clip away all the black
glEnable (GL_ALPHA_TEST);
glAlphaFunc (GL_GREATER, 0.0);

Kal Mar
09-30-2010, 10:39 AM
I am sorry,
I working in direct volume rendering, a scalar data is storage in the texture3D, as:

glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, X, Y, Z, 0, GL_LUMINANCE,
GL_UNSIGNED_BYTE, vol);

the internal format storage in my board is RGBA8.

How can i do your suggestion ?

"I suggest you copy the RGB channels (convert to greyscale) and set the alpha channel to this value."

BionicBytes
10-01-2010, 04:41 AM
So your source format is already a single channel 8-bit image format- ie luminance.
When loading the textures, create a temporary buffer so you can copy the byte(s) into the alpha channel of the dentination temporary buffer before uploading to GL.
If your source data really is LUMINANCE, then why would you select RGBA8 as the internal format? You may be better off using GL_LUMINANCE8_ALPHA8 as the internal format, and GL_LUMINANCE_ALPHA as the source format for glTexImage3D().
In which case, I suggest you create a temp buffer width*height*slices*2 bytes in size for the image manipulation.
Then, when you read each pixel (byte in your case) of the source, store that byte into the destination buffer at index n and n+1 (since the destination buffer is two channel and the source is one channel).

Kal Mar
10-04-2010, 10:08 AM
Hi BionicBytes

I now understand all procedure. For visualize I needed any form to blend, I used:

glEnable(GL_BLEND); //Composition
glBlendFunc( GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR );

and, I can visualize well, in gray scale, because my data is recovered as LUMINANCE8 and stores as RGBA8

Thanks You

Now, I writing a transfer function for coloring the volume.

BionicBytes
10-05-2010, 04:40 AM
Glad to help in some small way...