PDA

View Full Version : help 3d texture! (again..)



arthas
01-11-2008, 03:08 AM
Hi! The program I wrote, should read the values of a volume ( the array “volumevalues” is an example of 1x1x3 volume) map it into 3 poligons, blend them, and put the result in an array. It should simulate a radiography..
I have a problem, the program compiles, and runs.. but after blend the 3 slices, in the array result it should write only 3 values, instead it writes 12 values! anyone can help??

#include <cstdio>
#include <cstdlib>
using namespace std;

// --------------------------------------------
// Include
#include <gl\glew.h>
#include <gl\glut.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <windows.h>

//trasform alpha from double to char and in the range 0-255
char DoubleToChar(double alpha){
return (char)(alpha*255.0);
}

int main(int argc, char **argv) {

//Volume values: is a simple 1x1x3 poligon along z

unsigned char VolumeValues[12]={1,0,0,1,2,0,0,0,3,0,0,0};
VolumeValues[3]=DoubleToChar(1.0);
VolumeValues[7]=DoubleToChar(1.0/2.0);
VolumeValues[11]=DoubleToChar(1.0/3.0);

unsigned char result[12]; //array for the result

// inizialize glut
glutInit (&argc, argv);
glutCreateWindow("radiographic simulation");
glewInit();

// create the texture
GLuint tex;
glGenTextures (1, &tex);
glBindTexture(GL_TEXTURE_3D,tex); // target is a 3d texture

// sets texture parameters
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);

/*void glTexImage3D (GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const GLvoid * pixels)*/
// allocate graphioc memory
glTexImage3D(GL_TEXTURE_3D,0,GL_RGBA,1,1,3,0,GL_RG BA,GL_UNSIGNED_BYTE,VolumeValues);

GLenum errCode;
const GLubyte *errString;
if ((errCode = glGetError()) != GL_NO_ERROR) {
errString = gluErrorString(errCode);
fprintf (stderr, "OpenGL Error: %s\n", errString);
}


/* void gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top); The clipping region is a rectangle with the lower-left corner at (left, bottom) and the upper-right corner at (right, top).
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height); Defines a pixel rectangle in the window into which the final image is mapped. The (x, y) parameter specifies the lower-left corner of the
viewport, and width and height are the size of the viewport rectangle.*/
//viewport transform for 1:1 pixel=texel=data mapping
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,1,0.0,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0,0,1,1);



glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();

glEnable(GL_TEXTURE_3D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);


float z= ((float)1)/3;
float y =((float)2)/3;
glBegin(GL_QUADS);
glTexCoord3f(0.0,0.0,0.0); glVertex2f(0,0);
glTexCoord3f(0.0,1.0,0.0); glVertex2f(0,1);
glTexCoord3f(1.0,1.0,0.0); glVertex2f(1,1);
glTexCoord3f(1.0,0.0,0.0); glVertex2f(1,0);

glTexCoord3f(0.0,0.0,z); glVertex2f(0,0);
glTexCoord3f(0.0,1.0,z); glVertex2f(0,1);
glTexCoord3f(1.0,1.0,z); glVertex2f(1,1);
glTexCoord3f(1.0,0.0,z); glVertex2f(1,0);

glTexCoord3f(0.0,0.0,y); glVertex2f(0,0);
glTexCoord3f(0.0,1.0,y); glVertex2f(0,1);
glTexCoord3f(1.0,1.0,y); glVertex2f(1,1);
glTexCoord3f(1.0,0.0,y); glVertex2f(1,0);

glEnd();
glPopMatrix();


/*void glReadBuffer(GLenum mode): specifies a color buffer as the source for subsequent read and copy image commands*/
/*void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);*/
//reads data from the frame buffer and write them in the result
glReadBuffer(GL_FRONT);
glReadPixels(0,0,1,1,GL_RGBA,GL_BYTE,result);

// print out results
printf("Data before roundtrip:\n");
for (int i=0; i<12; i++)
printf("%d\n",VolumeValues[i]);
printf("Data after roundtrip:\n");
for (int i=0; i<12; i++)
printf("%d\n",result[i]);

getchar();


return 0;




the output is:

data before roundtrip:
1
0
0
255
2
0
0
127
3
0
0
85
data after roundtrip:
0
0
0
127
204
204
204
204
204
204
204
204

Bob
01-11-2008, 03:28 AM
Maybe I don't understand your problem, but you print 12 values because the for loop goes from 0 to 11.

arthas
01-11-2008, 09:02 AM
yes.. but what i want to read back, are the values of the result plane ( 4 values not 12). i mean, that in the frame buffer should be only 4 values, because i want to blend the "slices" of the volume (representes with a 3d texture) and read the result, that is only a plane.. am i clear??

-NiCo-
01-11-2008, 09:14 AM
What Bob is trying to say is that you're already only reading back the 4 pixel values of one 'blended' plane.
The code will still run if you use

unsigned char result[4];

and

for (int i=0; i<4; i++)
printf("%d\n",result[i]);

Because you're requesting a 1 pixel rectangle with rgba components in readpixels it will only write to the first 4 elements of your results-array.

The problem is elsewhere. You probably have to move the drawing calls into a display function and set it with glutDisplayFunc() followed by glutMainLoop(). And IIRC you have to offset the z-coordinates by 0.5 so that you sample at 0.5/3, 1.5/3 and 2.5/3.

N.

arthas
01-11-2008, 11:53 AM
i don't need to display the result of blending, but only the blended value.. questions:
- why should I offset the z coordinates?
- why the alpha blended value is equal to the value of the 2nd slice?
- and finally.. do you know why the 5th value is 204?

Bob
01-11-2008, 02:43 PM
i don't need to display the result of blending, but only the blended value.. questions:
- why should I offset the z coordinates?

Texel centers, where the color is defined, is located at half-integers coordinates. That is, since your texture is 3 texels deep, texel centers are located at 0.5/3, 1.5/3 and 2.5/3. At 0, 1/3 and 2/3, as in your code, you're referencing the exact border between adjacent texels which is highly sensitive rounding errors when using nearest filtering.


- why the alpha blended value is equal to the value of the 2nd slice?

Could be affected by the fact that you're not properly referencing the texels you expect, as mentioned above.


- and finally.. do you know why the 5th value is 204?
You're reading back one 4-channel RGBA pixel as unsigned bytes. That means result[0] is the red component of that pixel, result[1] the green, result[2] the blue and result[3] the alpha of that pixel. result[4] to result[11] is not written because you're only reading one pixel, and the value in those places are left unchanged. 204 is what happens to be in that array befor you're reading the pixel value into it.

arthas
01-12-2008, 02:04 AM
thanks Bob, i changed that piece of code into:

float x= ((float)0.5)/3;
float z= ((float)1.5)/3;
float y =((float)2.5)/3;
glBegin(GL_QUADS);
glTexCoord3f(0.0,0.0,x); glVertex2f(0,0);
glTexCoord3f(0.0,1.0,x); glVertex2f(0,1);
glTexCoord3f(1.0,1.0,x); glVertex2f(1,1);
glTexCoord3f(1.0,0.0,x); glVertex2f(1,0);

glTexCoord3f(0.0,0.0,z); glVertex2f(0,0);
glTexCoord3f(0.0,1.0,z); glVertex2f(0,1);
glTexCoord3f(1.0,1.0,z); glVertex2f(1,1);
glTexCoord3f(1.0,0.0,z); glVertex2f(1,0);

glTexCoord3f(0.0,0.0,y); glVertex2f(0,0);
glTexCoord3f(0.0,1.0,y); glVertex2f(0,1);
glTexCoord3f(1.0,1.0,y); glVertex2f(1,1);
glTexCoord3f(1.0,0.0,y); glVertex2f(1,0);

now the result contain:

1
0
0
127
204
..
204

the alpha value is still 127.. could it be right? and, now the red channel is 1 but i'm not sure that is correct, what do you think?

Bob
01-12-2008, 04:31 AM
The result is most likely correct given the states you set. Whether it's wrong or not depends on what you actually expect to get, which is something only you know at the moment.

An alpha value of 127 is probably due to a lack of destination alpha. 127 is the maximum value representable by a singled byte, which is the type you're requesting. Red channel is correct to. You're performing blending calculations on values extremely close to the quntization levels, so pretty much anything from 0 to 3 could be expected in this case, depending on how the hardware performs calculations and roundings.

arthas
01-12-2008, 04:53 AM
as i said, what i want to do, is simulate a radiography.. so, i use a 3d texture to represent the volume, i expect to obtain a projection of the planes( the slices of my volume..) blendling the slices. at the end of the operations, i should find in the frame buffer, the "radiography".. and finally, i want to read the values..
question bis :-) : is the code correct for what i want to do?