PDA

View Full Version : Using a PBO to create a binary mask representing



mark g
03-09-2010, 07:33 AM
Hi,

I am new to OpenGL. I need to copy the data from the framebuffer to the CPU to perform computations on the pixels. In fact all I want to do is to create a binary matrix having the same dimensions as the framebuffer for which the bixel values are 1.0 for pixels which are (rendered) coloured and 0.0 for those not. In essence I use this to know whether the pixel is inside (1.0) or outside (0.0) a polyhedron rendered in an uniform colour. Typically the matrix is 400x400 pixels.
Once I have this matrix I want to determine an aperture which best fits the polyhedron, where the aperture consists of two banks of moveable leaves (in X-direction) of a finite thickness 4-10pixels(mm).

I have done some reading around the subject and the consensus seems to be to use a PBO , to avoid the performance penalty of glPixelRead().

Is a PBO the best method to achieve this?

Is there a simple test to verify whether my graphics card supports a PBO? If not what alternatives are there to a PBO? VBO? FBO?

Any assistance would be gratefully received.

Thanks

Mark

aqnuep
03-09-2010, 09:15 AM
Even with PBO the efficiency of framebuffer readback is very limited. If you really want to have performance, then stick to fragment shaders instead.

PBO in this case has its drawbacks as even if the actual read from the framebuffer to the pixel buffer is much faster than copying to host memory, and it's also done asynchronously, the problem is in order to have access to the data with CPU you would need to do one of the following with the resulting PBO:

- get the data back with GetBufferData, but then you still need that additional copying from GPU to host memory, of course it is still faster than direct framebuffer readback.
- map the pixel buffer and work directly in GPU address space, but it is very implementation dependent whether this has any performance benefits compared to the previous ones, maybe it's even slower.

mark g
03-09-2010, 11:47 PM
Thanks for the response. As I understand it (!) fragment s

mark g
03-10-2010, 06:32 AM
Hmmh don't know what happened to my previous post, but it should have been ...
Thanks for the respon

ZbuffeR
03-10-2010, 06:37 AM
Sorry, say that again ?

mark g
03-10-2010, 06:40 AM
okay I'll try again

Thanks for the response. As I understand it (!) fragment shaders are c

mark g
03-10-2010, 06:44 AM
okay I'll try to post this again...

Thanks for the response. As I understand it (!) fragment sh

mark g
03-10-2010, 11:01 PM
Thanks for the response. As I understand it (!) fragment shaders are coded for and executed by the GPU. However I still need to transfer the binary mask to the CPU to determine the necessary positions of the leaves (left and right) which form the aperture enclosing the rendered polyhedron.

Below is a code snippet to illustrate what the CPU needs to do, in the hope that this will make the explanation clearer. Basically the function scans the binary mask and looks for the transition 0 to 1 (leaf side) and 1 to 0 (right side) to set the position of the leaves used to generate the aperture.


for (int k=0;k<b->leafPairs+1;k++){
// reset temps and latches for each leaf pair
tempB=tempA=0.0;
latchB=latchA=0;
// Mask coordinates run from 0,X and 0,Y whereas actual MLC has X1,X2 and Y1,Y2 therefore need subtract offset value
for(int h=int(b->leafBoundary[k]-b->leafBoundary[0]);h<int(b->leafBoundary[k+1]-b->leafBoundary[0]);h++){
for (int w=0;w<width;w++){
// now set B-leaves (left in BEV): transition h,w and h,w+1=0->1
if ((value[h][w]==false &amp;&amp; value[h][w+1]==true)&amp;&amp;(k<b->leafPairs)) {
latchB++;
if (latchB==0) tempB=w-marginX-b->X2;// 5mm margin
else tempB=MIN(tempB,w-marginX-b->X2); // overwrite value with minimum (tempB,w-marginX)

}
//now set A-leaves value transition h,w and h,w+1 = 1->0
if ((value[h][w]==true &amp;&amp; value[h][w+1]==false)&amp;&amp;(k<b->leafPairs)) {
latchA++;
if (latchA==0) tempA=w+marginX-b->X2;// 5mm margin
else tempA=MAX(tempA,w+marginX-b->X2); //overwrite value with maximum (tempA,w-marginX)

}
//
}//
}if (k<b->leafPairs) {
std::cout << "\nWill now try to set " << k+1 << "B to " << tempB << " and " << k+1 << "A to " << tempA << "\n";
b->setLeafPosition(tempB,tempA,k);
}
}
return true;

So the questions are: Is a fragment shader the best choice, bearing in mind perfromance and what I am trying to achieve? If so how do I send the binary mask data to the CPU? If not is a PBO the next best choice? Or is there something better (in terms of performance)?

Thanks

Mark

mark g
03-10-2010, 11:08 PM
For some reason the server kept timing out when trying to submit my previous messages. Sorry!

I forgot to explicitly mention that I am sending the polyhedra vertex coordinates down the graphics pipeline (a simple perspective projection) and rendering them to the screen with GL_POLYGON (since some faces are quadrilateral or higher order polgons- otherwise I would use triangles!)

Mark

mark g
03-12-2010, 05:17 AM
Okay I've had a go at doing this, but would appreciate some further assistance



#include "glext.h"
#include <GL/glut.h>

GLuint pboName;

glGenBuffersARB(1, &amp;pboName);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboName);
glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB,width * height, myPixelPtr,GL_STREAM_READ_ARB);


// Map the PBO so that it is readable by client (CPU)
// only want to read pixel data in order to set mask values
glBufferDataARB();
glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);


// check whether pixel value == colour/set if yes then set corresponding Mask bixel (i,j) to true
for (int i=0;i<height;++i){
for (int j=0;j<width;++j){
Mask[i][j]=false; // initialise all values to false

if (myPixelPtr[(i*width)+j]==glColors3fv(colours[1])) Mask[i][j]=true;
}
}

// Now unmap the PBO releasing the client side mapping
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER);


// Finally clean up
glDeleteBuffersARB(1, &amp;pboName);

I want to check whether the pixel has a particular value i.e. glColor3fv(colours[1]), which is set if the perspectivve projected vertex is visible. Am I going about this the right way?

Thanks in advance

Mark