I have a deferred shading pipeline wherein I keep an “ID” attachment in my G-buffer. It’s format is set to GL_RG32I, where each channel is an ID. Red is a material ID, which is looked up against a UBO of materials. Green is the ID of the model so I can do fast mouse picking. The G-buffer also has attachments for color (albedo), encoded normals, and depth.
I’m using the Cinder creative coding framework, but trust that this code wraps its GL counterparts properly.
int32_t MyApp::pick( const vec2& v )
{
vec2 offset( 8.0f );
Area area( v - offset, v + offset );
area = area.getClipBy( mFboGBuffer->getBounds() );
const gl::ScopedFramebuffer scopedFramebuffer( mFboGBuffer );
gl::readBuffer( GL_COLOR_ATTACHMENT1 );
GLint x = area.x1;
GLint y = mFboGBuffer->getHeight() - area.y2;
GLsizei h = area.getHeight();
GLsizei w = area.getWidth();
size_t len = w * h;
GLint* data = new GLint[ len ];
glReadPixels( x, y, w, h, GL_GREEN, GL_INT, (GLvoid*)data );
map<int32_t, size_t> count;
for ( size_t i = 0; i < len; ++i ) {
int32_t modelId = (int32_t)data[ i ];
if ( modelId >= 0 ) {
++count[ modelId ];
}
}
delete [] data;
int32_t id = -1;
if ( !count.empty() ) {
id = max_element( count.begin(), count.end(), count.value_comp() )->first;
}
return id;
}
glReadPixels gives me a GL_INVALID_ENUM. However, it works if I change the attachment to 0 (albedo) or 2 (encoded normals). I’m wondering whatI need to do to read the green channel from a GL_RG32I formatted buffer texture. My pack alignment is 4, btw. I messed around with glPixelStorei to no avail. I also tried reading the value as GL_FLOAT so no conversion happens. Nothing. The data in the attachment is valid as I can draw it with a shader. The values are actual integers (ie, 392), not floats.