c++openglglfwglm-mathglreadpixels

glReadPixel return fault result


I want to do the 3D-picking on OpenGl by the way of frame pick. On this way I need to use glReadPixel to get some information of the pixels on the screen currently, so I test it on the following way but get the wrong result. First , I use Callback glfwSetCursorPosCallback(window, mouse_callback)and mouse_callback(GLFWwindow* window, double xpos, double ypos) to get the current mouse position (screen positon) and the pixel's color(when I change the mouse's position) ,then use std::cout to print it .

void mouse_callback(GLFWwindow* window, double xpos, double ypos)   
{
    uint32_t color;
    glm::vec4 c;
    GLfloat stencil;
    glReadPixels(xpos, ypos, 1, 1,GL_RGBA, GL_UNSIGNED_BYTE, &color);
    c.r = (color & 0xFF) / 255.0F;
    c.g = ((color >> 8) & 0xFF) / 255.0F;
    c.b = ((color >> 16) & 0xFF) / 255.0F;
    c.a = ((color >> 24) & 0xFF) / 255.0F;
    std::cout << "color[0]" << c.r<< std::endl;
    std::cout << "color[1]" << c.g << std::endl;
    std::cout << "color[2]" << c.b << std::endl;
    std::cout << "color[3]" << c.a << std::endl;
}

But the problem is when I render the scene below, and put my mouse on different part of this scene , the result seems to be wrong. From left-top region to the right-bottom regionm,the RBG should be (1.0,0.0,0.0) , (0.6,0.0,0.4) , (0.4,0.0,0.6) , (0.2,0.0,0.8) , (0.0,0.0,1.0). The pictures are below .

the return result is (0.4,0.0,0.6) but the right result shoud be (1.0,0.0,0.0)

the return result is (0.0,0.0,0.1) but the right result shoud be (0.4,0.0,0.6)

the return result is (0.8,0.0,0.2) but the right result shoud be (0.4,0.0,0.6)

I have try to use the simple examples (draw a triangle) to test the glReadPixel, the rusult seems to be right. I do not know why it goes wrong when use my scence. Could anyone give me some advices ? Or how to do the frame pick picking ? Thank u for your help!!


Solution

  • OpenGL uses coordinates where the origin (0, 0) is the bottom-left of the window, and +Y is up. You have to convert to OpenGL's coordinate system when reading, since the cursor events use (0, 0) as the top-left of the window, and +Y is down.

    void mouse_callback(GLFWwindow* window, double xpos, double ypos)
    {
        int width, height;
        glfwGetWindowSize(window, &width, &height);
        int ixpos = (int)xpos;
        int iypos = height - 1 - (int)ypos;
        uint32_t color;
        glReadPixels(ixpos, iypos, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
        ...
    }