Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CityDoctor
CityDoctor2
Commits
861dafdf
Commit
861dafdf
authored
Jun 19, 2026
by
Matthias Betz
Browse files
Add PickingFramebuffer for color-pick readback
parent
20b56607
Changes
1
Hide whitespace changes
Inline
Side-by-side
CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/gl/PickingFramebuffer.java
0 → 100644
View file @
861dafdf
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
;
}
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment