The Internal format of OpenGL CUDA interop - opengl

I use CUDA surface Reference to write and read OpenGL 3D Texture fllowing this post Write to 3D OpenGL textures in CUDA ... .
There is a problem confused me.
For example,this function
glTexImage3D(GL_TEXTURE_3D, 0, GL_INTENSITY, volDim_.x, volDim_.y
, volDim_.z, 0, GL_LUMINANCE, getVolumeTypeGL(vol), vol->getData());
the third parameter is internal format.
In CUDA kernel,I need write or read the texture,like below code,
ElementType v;
surf3Dread(&v,surfaceRef,x*sizeof(ElementType),y,z);
surf3Dwrite(&v,surfaceRef,x*sizeof(ElementType),y,z);
I don't know how to match Internal Format with ElementType.
Example
glTexImage3D(GL_TEXTURE_3D, 0, GL_INTENSITY, volDim_.x, volDim_.y
, volDim_.z, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, vol->getData());
In host memory,the type of volume data type is unsigned char.
Which ElementType shuld I choose?
uchar4 or uchar ,or float
My some code could find in here My GitHub
UPDATE:
I have solved this problem.
GL_RGBA32F ---- float4
GL_RGBA ---- uchar4
GL_INTENSITY -- uchar

If the internal format of glTeximage3D is GL_INTENSITY, the element type of surf3Dread or surf3Dwrite is unsigned char. GL_RGBA32F matches float4 and GL_RGBA matches uchar4.

Related

Should I provide a full or partial image to glTexSubImage2D?

I have a piece of GLvoid* data that contains an entire image, which is periodically updated throughout my program. I use glTexImage2D to initialize a texture on the GPU with this data.
I would like to use glTexSubImage2D to update parts of the texture as necessary. The documentation for glTexSubImage2D describes the GLvoid* pixels argument as such:
Specifies a pointer to the image data in memory.
What "image data" is this expecting? Can I provide the entire GLvoid* data, or is it expecting a buffer that only contains the data being copied?
If it expects the partial data, is there an alternative way to provide the whole buffer instead?
You can provide entire image data with call
glTexSubImage2D( target, level, 0, 0, W, H, format, type, pixels);
W and H are texture width and height, the whole texture will be copied, pixels is W*H array. Or you can provide only modified data with call
glTexSubImage2D( target, level, offset_x, offset_y, w, h, format, type, pixels);
where w and h is weigth and height of modified data so offset_x + w < W and offset_y + y < Y. pixels is w*h array.
Edit:
glPixelStorei( GL_UNPACK_ROW_LENGTH, W);
glPixelStorei( GL_UNPACK_SKIP_PIXELS, offset_x);
glPixelStorei( GL_UNPACK_SKIP_ROWS, offset_y);
glTexSubImage2D( target, level, offset_x, offset_y, w, h, format, type, pixels);
where pixels is W*H
It's only the data to be copied. Or you will have to waste a lot of memory to upload only a part of the image(sometimes the only part you currently have).
P.S. And it's rather painful that it doesn't even support strided data. So if you have a full image, you can't upload left or right half of it without copying it to a smaller buffer.

Conversion to Cinder gl::Texture

I am trying to create a gl::Texture object using image data as a BYTE * with the parameters below.
FreeGLUT - I use this to create a 2d texture and bind it to a quad.:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureWidth, textureHeight, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
glBindTexture(GL_TEXTURE_2D, 0); etc etc
This works fine, however I cannot find a way to create a gl::Texture object in Cinder.
text = gl::Texture(loadImage(loadAsset("text.jpg"))); // works with images files
text = gl::Texture(data, GL_RGBA8, 640, 480); // BTYE * data This gives me a grey screen -
This seemed the most likely, however I have no idea what to do with Format format = format();
Texture (const unsigned char *data, int dataFormat, int aWidth, int aHeight, Format format=Format())
I really have no understanding of how this works and cant find any better tutorials online. Thanks.
apparently dataFormat is the format parameter to glTexImage2D and should be something like GL_RGBA or GL_RGB (or GL_BGRA_EXT as in the example you provided)
What you want is the "internal format" which is set via the Format struct. So you set it like:
gl::Texture::Format fmt;
fmt.setInternalFormat(GL_RGBA8);
text = gl::Texture(data, GL_RGBA, 640, 480, fmt);
The GL_UNSIGNED_BYTE format is pre-set in that constructor of the cinder wrapper
Sometimes it can be easier to just look at the code instead of trying to find the 100% applicable documentation

opengl glReadPixels

I want to get color of a pixel. The pixel is mouse position. I use glReadPixels but i can't
POINT pt;
GetCursorPos(&pt);
unsigned char pixel[3];
glReadPixels(pt.x, pt.y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
After this codes value of pixel is: 'Ì'
any idea?
204 is CC in hex representation. This value is often used to fill non-initialized memory. If you'll initialize pixel with zero (for example)
unsigned char pixel[3] = {0};
99,(9)% you'll see zero after call to glReadPixels. Depending on documentation glReadPixels
If an error is generated, no change is made to the contents of data.
that is your data in pixel was not changed because of error. Follow #OlegTitov's fourth advice (look for what glGetError(); will tell you)
Upd: If you want to get a pixel value from the main screen using only glReadPixels, and if you didn't create any GLFrameBuffer, I'm not sure, but I think you'll fail. I'll repeat - I'm not sure, but I think, that glReadPixels can read pixel values only from frame buffers, that was previously created by gl-functions
When outputting char to console, compiler will print as a symbol, not as letter. This is done for C style strings could be printed normal way. To print integer value first cast variable to integer type.
When reading from screen: Note that openGL's coordinate origin is bottom left corner while window systems use upper left corner, so you need to convert from one coordinate system to another
glReadPixels(pt.x, window_height - pt.y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
If you experience further problems make sure that correct pixel buffer is bound as read beffer. For window output:
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
If still have some problems start checking your code with glGetError();

Load bmp file as texture using auxDIBImageLoad in OpenGL

I am learning OpenGL NeHe Production.When I read lesson22 Bump-Mapping、Multi-texture,I got a problem.
When I load logo bmp file,I need to load two bmp files:one stores color information ,and another stores alpha information.
here is the two bmp files:
OpenGL_Alpha.bmp:
and OpenGL.bmp :
Here is the code:
if (Image=auxDIBImageLoad("Data/OpenGL_ALPHA.bmp")) {
alpha=new char[4*Image->sizeX*Image->sizeY];
for (int a=0; a<Image->sizeX*Image->sizeY; a++)
alpha[4*a+3]=Image->data[a*3]; //???????
if (!(Image=auxDIBImageLoad("Data/OpenGL.bmp"))) status=false;
for (a=0; a<Image->sizeX*Image->sizeY; a++) {
alpha[4*a]=Image->data[a*3];//??????????
alpha[4*a+1]=Image->data[a*3+1];
alpha[4*a+2]=Image->data[a*3+2];
}
glGenTextures(1, &glLogo);
glBindTexture(GL_TEXTURE_2D, glLogo);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Image->sizeX, Image->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, alpha);
delete alpha;
}
My question is :why the index of Image->data is a*3???
Could someone interpret for me ?
I am learning OpenGL NeHe Production.When I read lesson22 Bump-Mapping
Why? The NeHe tutorials are terribly outdated, and the Bump Mapping technique outlined there completely obsolete. It's been superseeded by shader based normal mapping for well over 13 years (until 2003 texture combiners were used instead of shaders).
Also instead of BMPs you should use a image file format better suited for textures (with alpha channel). Like:
TGA
PNG
OpenEXR
Also the various compressed DX texture formats are a good choice for several applications.
My question is :why the index of Image->data is a*3???
Extracting the red channel of a RGB DIB.
It's the channel offset. The RGB data is stored as three consecutive bytes. Here 'a' represents which pixel (group of 3 bytes, one for R, one for G, one for B).
Think of a*3 as a pointer to an array of 3 bytes:
char* myPixel = Image->data + (a*3);
char red = myPixel[0];
char green = myPixel[1];
char blue = myPixel[2];

Stiching multiple textures/frames together in OpenGL using a Kinect

I came across the following situation:
I have a Kinect camera and I keep taking frames (but they are stored only when the user presses a key).
I am using the freenect library in order to retrieve the depth and the color of the frame (I am no interested in skeleton tracking or something like that).
For a single frame I am using the glpclview example that comes with the freenect library
After retrieving the space data from the Kinect sensor, in the glpclview example, the current frame it is drawn like this:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_SHORT, 0, xyz);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_SHORT, 0, xyz);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gl_rgb_tex);
glTexImage2D(GL_TEXTURE_2D, 0, 3, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb);
glPointSize(2.0f);
glDrawElements(GL_POINTS, 640*480, GL_UNSIGNED_INT, indices);
where
static unsigned int indices[480][640];
static short xyz[480][640][3];
char *rgb = 0;
short *depth = 0;
where:
rgb is the color information for the current frame
depth is the depth information for the current frame
xyz is constructed as :
xyz[i][j][0] = j
xyz[i][j]3 = i
xyz[i][j]4 = depth[i*640+j]
indices is (I guess only) array that keeps track of the rgb/depth data and is constructed as:
indices[i][j] = i*640+j
So far, so good, but now I need to render more that just one frame (some of them rotated and translated with a certain angle/offsets). How can I do this?
I'ved tried to increase the size of the arrays and keep reallocationg memory for each new frame, but how can I render them?
Should I change this current line to something else?
glTexImage2D(GL_TEXTURE_2D, 0, 3, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb)
If so, to what values should I change 640 and 480 since now xyz and rgb is a contiguos pointer of 640x480x(number of frames)?
To get a better ideea, I am trying to get something similar to this in the end (except the robot :D ).
If somewone has a better ideea, hint anything on how I should approach this problem, please let me know.
It isn't as simple as allocating a bigger array.
If you want to stitch together multiple point-clouds to make a bigger map, you should look into the SLAM algorithms (that is what they are running in the video your link to). You can find many implementations at http://openslam.org. You might also look into an ICP algorithm (Iterative Closest Point) and the KinectFusion from Microsoft (and the open source KinFu implementation from PCL).