glReadPixels

Started by Mattbooth, February 20, 2005, 13:20:10

Previous topic - Next topic

Mattbooth

Hi Guys

I'm doing a project at the moment trying to impliment a BOIDS (flocking behavior) techniques.

I need to use the glReadPixels method to look either side of the current object to see what is next to it.

Is there any simple examples i can follow about? (of course in LWJGL ;) )

Cheers

Mattbooth

So i've created a Buffer

ByteBuffer imageBuffer = BufferUtils.createByteBuffer(length);


and called the glReadPixels

GL11.glReadPixels(x, y, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, imageBuffer);


But seen as i need to have 2 image buffer looking at opposite sides of the object, eg fish eyes, how can this be done?

Cheers

Teeth

Sounds like you're going about it the wrong way - why don't you use logic to work it out, rather than whether you've drawn to the screen at any given point?

Mattbooth

Well, i could quite easily know (which i do) the points of the other fish, however to get the best out of this project as its for a uni project i need to use this function.  Been told i wont get the marks i need if i dont interpret what the scene can see.

Help appreciated :)

Teeth

If I'm understanding you correctly, could you not simply:

a) make a larger buffer and capture a larger area of the screen that includes both sides of the fish, or
b) use two byte buffers, or
c) use the same buffer twice?

// method a)
// where width is 2x the size of the area to one side of the fish,
// and x,y are the coordinates of the fish on the screen
ByteBuffer imageBuffer = BufferUtils.createByteBuffer(width*height);
GL11.glReadPixels(x - (width/2), y, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, imageBuffer);

// method b)
// where width and height are the normal size of one 
// area on the side of a fish to scan
ByteBuffer imageBufferLeft = BufferUtils.createByteBuffer(width*height);
ByteBuffer imageBufferRight = BufferUtils.createByteBuffer(width*height);
GL11.glReadPixels(x - width, y, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, imageBufferLeft);
GL11.glReadPixels(x, y, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, imageBufferRight);

// method c)

ByteBuffer imageBuffer = BufferUtils.createByteBuffer(width*height);
GL11.glReadPixels(x - width, y, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, imageBuffer);
// do your analysis on the buffer here
GL11.glReadPixels(x, y, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, imageBuffer);
// do your analysis on the buffer again here


Forgive me if I've misunderstood you.

Mattbooth

Hi mate

it does need to be 2 seperate buffers like you said but i cant work out how to point them in 2 seperate directions, i would be nice to be able to use one buffer of the whole image but its kind of cheating for what i need to do.

so thats question 1) how do you aim 2 buffers in different directions, i possibly assume you have to create 2 windows, but i'm not sure.

2nd question 2) is i've got a small screen buffer working, i'm getting the data out of it with this code.

for (int row = 0; row< height; row++){
            
            firstElement -= bytesPerRow;
            bufferIndex = firstElement;
            
            for(int column = 0; column <width; column ++){
                
                int red = imageBuffer.get(bufferIndex ++);
                int green = imageBuffer.get(bufferIndex ++);
                int blue = imageBuffer.get(bufferIndex ++);
               
                bufferRGBArray[bufferArrayIndex ++] = 0xFF000000 | ((red & 0x000000FF) << 16) | ((green & 0x000000FF) << 8) | (blue & 0x000000FF);
                System.out.println("BA =" + 0xFF000000 + "RED" + ((red & 0x000000FF) << 16)+ "green" + ((green & 0x000000FF) << 8)+ "blue"+ (blue & 0x000000FF));
            }
            
        }
        }


when it prints out i get mostly -16777216 Red0 green0 blue0
however when it does detect colour it gets -16777216 Red16711680 green65280 blue255

blue is obvous but how so you interpret the Red and Green

Thanks

Teeth

Quote from: "Mattbooth"1) how do you aim 2 buffers in different directions, i possibly assume you have to create 2 windows, but i'm not sure.

Not quite sure what you mean by this - surely you can just input different X and Y coordinates into the first two parameters of glReadPixels so that  you are looking at different areas of the screen?


Quote from: "Mattbooth"2) i've got a small screen buffer working, i'm getting the data out of it with this code.
/snip

Not sure quite what you're doing there: I can see you're getting the colours out but then you appear to be squashing them into an int and stashing them in a different byte buffer?

In any case you probably just need to be removing the shifts for your println. You don't need to shift the values if you're just gettin gthe raw value and printing it out.

System.out.println("red " + red + " green " + green + " blue "+ blue);


Try that

Mattbooth

hi mate

Thanks again, question i have my head around thank god, just my brain trying to make it more complicated than it really is.

Do you actually need to draw a buffer on the screen for the glReadPixels to work?

Now back to question 2) of above

i need to extract the R G B of each pixel so that simple analysis can be done on it, is the way that i'm doing it above the easiest way, the above was taken from an example i found and i not 100% what it does and how its stored.

Any easier way to get the RGB and store them seperatly and easily would be appreciated :)

Thanks

Teeth

glReadPixels will work, but you have to have drawn stuff to the screen first, either using primitivevs such as triangles or by using one of the many gl###Pixels commands, or glBitmap, or whatever else.

To be honest I haven't worked with glReadPixels a lot, but you can find reference here which may help you. It sounds and looks like you're getting the correct values out of the buffer once you've read them in. I assume you want to copy the data from the byte buffer over to something where you can easily get at the data? If you wanted to do it easily, you could do it like this:

int redArray[width][height]; // or however you declare useable 2D arrays in Java
int blueArray[width][height]; 
int greenArray[width][height]; 

for (int row = 0; row< height; row++) {
           
            // I assume these are here because OpenGL reads data in from the screen upside-down
            firstElement -= bytesPerRow;
            bufferIndex = firstElement;
           
            for(int column = 0; column <width; column ++){
               
                redArray[column][row] = imageBuffer.get(bufferIndex ++);
                greenArray[column][row] = imageBuffer.get(bufferIndex ++);
                blueArray[column][row] = imageBuffer.get(bufferIndex ++);

                // print out the value if you like
                // System.out.println("red " + red + " green " + green + " blue "+ blue);
            }
}

// now you can find out the red, green or blue value of a location using the x,y coordinates


Not sure if that's what you want and it certainly isn't "optimal" but it's readable and easy to use I guess.

Mattbooth

I'll have a play tomorow mate thanks for your help :)

Mattbooth

Has anyone else had any success with using glReadPixels without actually drawing to screen?

I need to get the pixels, interpret them, then move onto the next, however the interpretation is a different angle on the screen which i dont really need to see..

Any thoughts?

Cheers

Mattbooth

Okay now i am stumped....

so apprently you can use glReadBuffer and so longs you are using double buffering you can get the pixels, however i want to get them from a seperate camera angle withough moving the main camera, which is what i think the readbuffer is for....

Anyone give me a hand...

Cheers

princec

What you need to do is, set up the camera for the particular viewpoint you're interested in, draw the entire scene, then call glReadPixels on the backbuffer. Then move the camera to where you actually want people to see things and draw the entire scene again, and swap the buffers.

Basically - you're drawing it all twice.

Cas :)

Mattbooth

Hi Cas,

Thats what i have been trying to do mate, but unsuccesfully, i'll attach the code but in simple terms...

main camera angel -  GLU.gluLookAt(0.5f,0.5f, 0.0f, 0.6f,0.5f, 0.0f, 0.0f,1.0f,0.0f);

call draw object

get back buffer with  GL11.glReadBuffer(GL11.GL_BACK);

change view to GLU.gluLookAt(0.5f,0.5f, 0.0f, 0.5f,0.5f, 1.0f, 0.0f,1.0f,0.0f);

call method to get pixels using glReadPixels

change view back to main view

RGB values still read 0, 0, 0

code @ http://www.booth123.pwp.blueyonder.co.uk/zViewTEST.java

god this is depressing  :roll:  any further help appreciated :)

princec

glReadBuffer doesn't do any reading, it just tells glReadPixels which buffer it's going to read from.

Cas :)