LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: Mattbooth on February 20, 2005, 13:20:10

Title: glReadPixels
Post by: Mattbooth on February 20, 2005, 13:20:10
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
Title: glReadPixels
Post by: Mattbooth on February 20, 2005, 14:46:58
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
Title: glReadPixels
Post by: Teeth on February 20, 2005, 18:19:37
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?
Title: glReadPixels
Post by: Mattbooth on February 20, 2005, 20:10:23
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 :)
Title: glReadPixels
Post by: Teeth on February 21, 2005, 10:56:33
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.
Title: glReadPixels
Post by: Mattbooth on February 21, 2005, 15:35:42
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
Title: glReadPixels
Post by: Teeth on February 22, 2005, 14:03:38
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
Title: glReadPixels
Post by: Mattbooth on February 22, 2005, 16:04:39
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
Title: glReadPixels
Post by: Teeth on February 22, 2005, 17:38:36
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 (http://rush3d.com/reference/opengl-bluebook-1.0/ch05.html#id5527285) 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.
Title: glReadPixels
Post by: Mattbooth on February 23, 2005, 01:13:02
I'll have a play tomorow mate thanks for your help :)
Title: glReadPixels
Post by: Mattbooth on March 02, 2005, 11:55:10
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
Title: glReadPixels
Post by: Mattbooth on March 05, 2005, 22:40:14
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
Title: glReadPixels
Post by: princec on March 06, 2005, 15:43:51
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 :)
Title: glReadPixels
Post by: Mattbooth on March 06, 2005, 17:27:43
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 :)
Title: glReadPixels
Post by: princec on March 06, 2005, 19:07:37
glReadBuffer doesn't do any reading, it just tells glReadPixels which buffer it's going to read from.

Cas :)
Title: glReadPixels
Post by: Mattbooth on March 06, 2005, 19:52:36
Hi caz, forgive my ignorance, just a bit of bad wording...

Even if glReadBuffer sets the buffer to read the front or the back buffer, how do you set the camera angle's in the different buffers?

still cant get anywhere  :oops:
Title: glReadPixels
Post by: princec on March 06, 2005, 21:06:38
You don't! You always render to the backbuffer.
What exactly is the effect you're trying to do? I've got a funny feeling you're going sort of the wrong way about it.

Cas :)
Title: glReadPixels
Post by: Mattbooth on March 06, 2005, 22:05:56
quite possibly caz :)

Okay i have a shoal of fish that you can see from the main window

I need to get the RGB values from either side of the fish (in effect what they can see) and interpret it.

So i thought i would have to use the back buffer to change the camera angle get the RGB, same on the other side of the fish, this can then be interpreted, however in the mean time the camera angel is changed back to the main shot of the shoal.

The aim is to calculate in the background without the main image being any different

Anything you can do to save me will be fab :)
Title: glReadPixels
Post by: princec on March 06, 2005, 23:58:30
Erk, ok. Pretty strange way of going about it! It's going to be pretty bloody slow I think.

For every fish you'll need to clear the buffer, render the scene from the fish's left eye, read the backbuffer; then clear the buffer again, render the scene from the fish's right eye, then read the backbuffer again. Repeat for each fish. Then plonk the camera somewhere interesting and render the scene you want to actually see, and swap the buffers.

Cas :)
Title: glReadPixels
Post by: Mattbooth on March 07, 2005, 10:40:09
Caz your the man lol

Yep that worked, i agree its going to be rather slow, i cant think of any other way to do it though.

One last question if you dont mind, when i call the update of hte scene to get all the info it updates the back buffer with the next sequence, so they way its being done at the moment with calling update twice in the same scene, its going to jump a frame.

Is there anyway to avoid this my making a copy of the pixels or something?

Thanks mate :)
Title: glReadPixels
Post by: Mattbooth on March 08, 2005, 20:46:50
slow isnt the word for this, i can make a cuppa between each frame  :roll:
Title: glReadPixels
Post by: Mattbooth on March 09, 2005, 12:25:16
hi guys,

Well i've tried for the last couple of days to swop the model i got working to my actual program.  As i said its slow but its returning the wrong values.  Instead of getting the camerea view of the fish's eye its still returning the value of hte main screen.  Quite a bit of code below.  The get pixels method words fine as it works on the model.

Method that passes the co-ords of the camera
public void vision(){
       int numFish = cFB.getNumOfFish(); // gets number of fish to draw
       for (int i = 0; i<numFish; i++){
           fish currFish = cFB.getFish(i);  
           threePointHolder poss = currFish.getCameraPos(); // gets the x,y,z position of the fish
          getSideView(poss, true); //sends the xyz to the camera position for left side
          getSideView(poss, false);  //sends the xyz to the camera position for left side
   
       }
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
               initGL(); // resets the camera angle
        }


method that clears buffer, sets camera and gets RGB

public void getSideView(threePointHolder newPos, boolean leftP){
       eyex = newPos.getX();
       eyey = newPos.getY();
       eyez = newPos.getZ();
       left = leftP;
             
       GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
       GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
       GL11.glShadeModel(GL11.GL_SMOOTH); // Enable Smooth Shading
       GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
       GL11.glClearDepth(1.0); // Depth Buffer Setup
       GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing
       GL11.glDepthFunc(GL11.GL_LEQUAL); // The Type Of Depth Testing To Do
       GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
       GL11.glLoadIdentity(); // Reset The Projection Matrix
       // Calculate The Aspect Ratio Of The Window
       //GL11.glScalef(0.2f,  0.2f, 0.2f);
       GLU.gluPerspective(10.0f, (float) displayMode.getWidth() / (float) displayMode.getHeight(), 0.1f, 200.0f);
       if (left == false){
           System.out.println("right");
       GLU.gluLookAt(eyex, eyey, eyez, eyex, eyey, (eyez+0.1f), 0.0f,1.0f,0.0f);
       left = true;
       }
       else{
           System.out.println("left");
          GLU.gluLookAt(eyex, eyey, eyez, eyex, eyey, (eyez-0.1f), 0.0f,1.0f,0.0f);
       left = false;
       }
       
       GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix

       // Really Nice Perspective Calculations
       GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
       
       drawAll();
       
      try{
     getShot();
   
     }
     catch(Exception e){
         System.exit(0);
         System.out.println("ERROR");
     }
     GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
   }

Now i know its passing the right values across from testing but the getting of the RGB from these positions isnt right.  It still gets it from the main screen

and after this code is executed i call

drawAll() // draws everything again
Display.update() //swop buffers.

going out my mind now, all things say it should work, but it gets the RGB of the main screen  :roll: [/code]