Commit 861dafdf authored by Matthias Betz's avatar Matthias Betz
Browse files

Add PickingFramebuffer for color-pick readback

parent 20b56607
package de.hft.stuttgart.citydoctor2.gui.gl;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL3;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/** Off-screen framebuffer that stores picking ids as RGBA8; supports single-pixel readback. */
public class PickingFramebuffer {
private int fbo;
private int colorTex;
private int depthRbo;
private int width;
private int height;
private boolean created;
public void resize(GL3 gl, int w, int h) {
if (w <= 0 || h <= 0 || (w == width && h == height && created)) {
return;
}
dispose(gl);
width = w;
height = h;
int[] tmp = new int[1];
gl.glGenFramebuffers(1, tmp, 0);
fbo = tmp[0];
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo);
gl.glGenTextures(1, tmp, 0);
colorTex = tmp[0];
gl.glBindTexture(GL.GL_TEXTURE_2D, colorTex);
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA8, w, h, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, null);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, colorTex, 0);
gl.glGenRenderbuffers(1, tmp, 0);
depthRbo = tmp[0];
gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, depthRbo);
gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT16, w, h);
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depthRbo);
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
created = true;
}
public void bind(GL3 gl) {
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo);
gl.glViewport(0, 0, width, height);
}
/**
* Reads the picking id at canvas pixel (x, y) measured from the top-left. GL's origin is bottom-left,
* so the row is flipped.
*/
public int readId(GL3 gl, int x, int y) {
if (!created || x < 0 || y < 0 || x >= width || y >= height) {
return 0;
}
ByteBuffer buf = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder());
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo);
gl.glReadPixels(x, height - 1 - y, 1, 1, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buf);
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
int r = buf.get(0) & 0xFF;
int g = buf.get(1) & 0xFF;
int b = buf.get(2) & 0xFF;
return PickingCodec.decode(r, g, b);
}
public void dispose(GL3 gl) {
if (created) {
gl.glDeleteFramebuffers(1, new int[]{fbo}, 0);
gl.glDeleteTextures(1, new int[]{colorTex}, 0);
gl.glDeleteRenderbuffers(1, new int[]{depthRbo}, 0);
created = false;
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment