Pages

Friday, 13 February 2015

Color picking or selection in OpenGL using shaders


Color picking is a simple method to implement the object selection.  It is very accurate as well, actually pixel accurate.

However since it involves read back the frame buffer data the performance won't be that good.

Steps involved in the implementation,

1. Draw your 2d or 3d object as you would normally do
2. Setup a frame buffer object
3. Assign unique ID and color to each object
4. Draw the object with the unique color assigned
5. Using the given screen coordinate retrieve the color.
6. Use the color to identify the object, and you are done

Frame buffer object creation 

            
glGenFramebuffers(1, &mChoose.mFrameBuffer);
glGenRenderbuffers(1, &mChoose.mDepthRenderbuffer);
glGenTextures(1, &mChoose.mTexture);

glBindTexture(GL_TEXTURE_2D, mChoose.mTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mW, mH,
                         0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glBindRenderbuffer(GL_RENDERBUFFER, mChoose.mDepthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, mW, mH);

glBindFramebuffer(GL_FRAMEBUFFER, mChoose.mFrameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                                   mChoose.mTexture, 0);

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                                      GL_RENDERBUFFER, mChoose.mDepthRenderbuffer);

Object selection

Let the mesh to be drawn are stored in vector objects and let px and py be the screen coordinates.

unsigned char data[4] = {0.0f};
glReadPixels(px, mH-py, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
for (ObjectMapIter iter = objects.begin(); iter != objects.end(); ++iter) {
    if (iter->mR == data[0] &&
        iter->mG == data[1] &&
        iter->mB == data[2]) {
        clickedItem = iter->mObject;
        break;
    }
}

Complete source code is available at https://github.com/trsquarelab/glexamples

No comments:

Post a Comment