opengl-esglslfragment-shaderrender-to-texturegles

Using GL_RED_INTEGER for object picking (GLES 3.0)


I have a scene where I draw a bunch of objects. I want the user to be able to select each object via a mouse. What I want to do is render the scene to a texture, draw each object as a purely solid color (in which the ID of the object is encoded). Then I will read back the texture's bits, take the ID at the mouse's position and use that to select the object.

I'm creating my offscreen buffer like so:

XGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, mWidth, mHeight,0,GL_RED_INTEGER, GL_UNSIGNED_SHORT, mBits));

But my problem is... I have no idea how to make the shader (GLSL3 3.0) to write an integer instead of normalized floats. I could encode the integer ID number into a normalized 4-float color, and then convert it back when I read the pixels, but I am worried that floating point "fuzziness" will cause small inaccuracies (i.e. ID (int)3 becomes ID (float)2.999999999999) when converting back and forth.

Is there a way to simply tell the shader, "here's the 4 bytes I want to write into the color buffer, never mind the floating point conversion stuff?"


Solution

  • The format of the framebuffer has only 1 channel and is integral. So define an integral output variable of type uint in the fragment shader:

    #version 300 es
    
    layout(location = 0) out uint fragOuput;
    
    void main() {
    
        fragOuput = ...;
    }