I still don't think that there is a clear answer here. So here is how I made it work through a 2D texture:
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1, &textureid);
glBindTexture(GL_TEXTURE_2D, textureid);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, w, h, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textureid, 0);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
GLuint buffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, buffers);
glFlush();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
On the GLSL side the fragment shader should have (4.3 core profile code here):
layout(location = 0) out vec4 colorOut;
layout(location = 1) out uvec4 elementID;
void main()
{
elementID = uvec4( elementid, 0, 0, 0 );
}
You can read the values on the host side:
unsigned int* ids = new unsigned int[ w*h ];
glBindTexture(GL_TEXTURE_2D, textureid);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, ids);