Hello Guest

LWJGL 2 - glReadPixel and Pbo Asynchronous read

  • 4 Replies
  • 4877 Views
LWJGL 2 - glReadPixel and Pbo Asynchronous read
« on: July 08, 2018, 13:45:45 »
So I've been trying to implement the Pbo asynchronous read in order to pick objects in 3d space by first rendering an Id pass and then the normal color pass, to do that I used the last section of this article http://www.songho.ca/opengl/gl_pbo.html#pack
I implement the code as follows:

Main class:
Code: [Select]
PBOManager PBOManager = new PBOManager();

// Main game loop
while (!Display.isCloseRequested())
{
// Capturing inputs to move the camera
viewMat = camera.move();

//Render with id shader
MasterRenderer.renderIdView = true;
renderer.renderScene(light, viewMat, camera.getPosition());
PBOManager.readPixelData();

MasterRenderer.renderIdView = false;

//Render with normal shader
renderer.renderScene(light, viewMat, camera.getPosition());
PBOManager.readPixelData();

        //Display the normal shader
display.update();
}

PBOManager.cleanUp();


And the PBOManager class looks like this:

Code: [Select]
package Render_engine;

import java.nio.ByteBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL21;

public class PBOManager
{
private static final int BYTES_PER_PIXEL = 4;
private int pbos[];
private int index = 0;
private int nextIndex = 1;

public static ByteBuffer buffer;

public PBOManager()
{
buffer = BufferUtils.createByteBuffer(BYTES_PER_PIXEL);

initPbos(2);
}

private void initPbos(int count)
{
this.pbos = new int[count];

for (int i = 0; i < pbos.length; i++)
{
this.pbos[i] = createPbo();
}
}

private int createPbo()
{
int pbo = GL15.glGenBuffers();

GL15.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, pbo);

GL15.glBufferData(GL21.GL_PIXEL_PACK_BUFFER, BYTES_PER_PIXEL, GL15.GL_STREAM_READ);

GL15.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, 0);

return pbo;
}

public void readPixelData()
{
// "index" is used to read pixels from framebuffer to a PBO
// "nextIndex" is used to update pixels in the other PBO

// set the target framebuffer to read
GL11.glReadBuffer(GL11.GL_FRONT);

// read pixels from framebuffer to PBO
// glReadPixels() should return immediately.
GL15.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, this.pbos[this.index]);

GL11.glReadPixels(Mouse.getX(), Mouse.getY(), 1, 1, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, 0);

// map the PBO to process its data by CPU
GL15.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, this.pbos[this.nextIndex]);
buffer = GL15.glMapBuffer(GL21.GL_PIXEL_PACK_BUFFER, GL15.GL_READ_ONLY, buffer);

//If buffer not empty (will be empty only on first frame)
if (buffer != null && buffer.hasRemaining())
{
this.printCurrentPixelColor();

GL15.glUnmapBuffer(GL21.GL_PIXEL_PACK_BUFFER);
}

// back to conventional pixel operation
GL15.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, 0);

this.index = (this.index + 1) % 2;
this.nextIndex = (this.index + 1) % 2;
}

private void printCurrentPixelColor()
{
while (buffer.hasRemaining())
{
System.out.print(((int) buffer.get() & 0xFF) + ":");
}

System.out.println();
}

public void cleanUp()
{
GL15.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, 0);

for (int pbo : this.pbos)
{
GL15.glDeleteBuffers(pbo);
}
}
}

As you can see the readPixelData() method is the same snippet of code at the bottom of the article, just translated to java.

With this setup I see the normal colors, which is what I want, but the colors detected are not from the id pass but from the normal color pass:
http://prntscr.com/k3x9wm

And if comment out the second render call in the main method I see the Id pass (of course) and the color detected is correct: http://prntscr.com/k3x9cm

So from what I can see I did some error in the code for which instead of, render the id, read the color and render the normal color, and process the previosuly read color, Im only able to read and process the pixel color of the last render call.

Is my diagnosis right?


*

Offline CoDi

  • *
  • 49
Re: LWJGL 2 - glReadPixel and Pbo Asynchronous read
« Reply #1 on: July 08, 2018, 16:48:20 »
[edit] never mind, misread

Re: LWJGL 2 - glReadPixel and Pbo Asynchronous read
« Reply #2 on: July 08, 2018, 20:21:40 »
Quote
[edit] never mind, misread

Is my post unclear?

*

Offline spasi

  • *****
  • 2261
    • WebHotelier
Re: LWJGL 2 - glReadPixel and Pbo Asynchronous read
« Reply #3 on: July 09, 2018, 15:54:17 »
OpenGL rendering is double-buffered. Afaict, with your current setup you end up reading the color pass of the previous frame. Try changing glReadBuffer(GL_FRONT) to glReadBuffer(GL_BACK), it should let you read the ID pass of the current frame.

Re: LWJGL 2 - glReadPixel and Pbo Asynchronous read
« Reply #4 on: July 10, 2018, 08:37:22 »
Thanks it works!