Imagination PowerVR SDK Blog

glReadPixels


#1

Hello





i was trying to get picking object up to work by using glReadPixels





GLbyte color[4];


               GLfloat depth;


               GLuint index;


               GLint x = m_position[0]*640;


               GLint y = m_position[1]*480;





               glReadPixels(x, screen_height-y , 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,


                         color);


               glReadPixels(x, screen_height-y , 1, 1, GL_DEPTH_COMPONENT,


                         GL_FLOAT, &depth);


               glReadPixels(x, screen_height- y , 1, 1, GL_STENCIL_INDEX,


                         GL_UNSIGNED_INT, &index);


the depth AND INDEX value are always equal to 0





before to request glReadPixels


during the init


        glEnable(GL_BLEND);


     glEnable(GL_DEPTH_TEST);


     glEnable(GL_STENCIL_TEST);


     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


     // Request Stencil Buffer support


     PVRShellSet(prefStencilBufferContext, true);





during the rendering :


     glClearStencil(0);


     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);


     glEnable(GL_STENCIL_TEST);





glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);





just before the draw


glStencilFunc(GL_ALWAYS, i, -1);








may you tell me why my stencil index is not properly working like the one i did using glu inspired by


http://en.wikibooks.org/wiki/OpenGL_Programming/Object_selection





Kind regards


david



#2

Hi David,

I think that you may be seeing this problem because your glReadPixels() call for your color buffer is invalid. If you change the type from GL_UNSIGNED_BYTE to GL_UNSIGNED_SHORT_4_4_4_4, or GL_UNSIGNED_SHORT_5_5_5_1, it should resolve the problem.

Thanks,
Joe




#3

Hello JOE,





the problem remain with the values you give to me ,





REgards


david


#4

I mean the pixel value is correct that is good but stencil value is not updated to the correct value






#5
dgu wrote:
I mean the pixel value is correct that is good but stencil value is not updated to the correct value




then render secrion is :

bool Selection::RenderScene() {



     glClearColor(1.0, 1.0, 1.0, 1.0);

     glClearStencil(0);

     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

     glEnable(GL_STENCIL_TEST);



     glUseProgram(program);

     glUniform1i(uniform_mytexture, /*GL_TEXTURE*/0);

     glEnableVertexAttribArray(attribute_coord3d);

     // Describe our vertices array to OpenGL (it can't guess its format automatically)

     glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_vertices);

     glVertexAttribPointer(attribute_coord3d, // attribute

               3, // number of elements per vertex, here (x,y,z)

               GL_FLOAT, // the type of each element

               GL_FALSE, // take our values as-is

               0, // no extra data between each position

               0 // offset of first element

               );



     glEnableVertexAttribArray(attribute_texcoord);

     glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_texcoords);

     glVertexAttribPointer(attribute_texcoord, // attribute

               2, // number of elements per vertex, here (x,y)

               GL_FLOAT, // the type of each element

               GL_FALSE, // take our values as-is

               0, // no extra data between each position

               0 // offset of first element

               );



     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_cube_elements);

     int size;

     glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);



     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);



     glm::mat4 view = glm::lookAt(camera_position, glm::vec3(0.0, 0.0, 0.0),

               glm::vec3(0.0, 1.0, 0.0));

     glm::mat4 projection = glm::perspective(45.0f,

               1.0f * screen_width / screen_height, 0.1f, 10.0f);



     GLfloat color_normal[4] = { 1, 1, 1, 1 };

     GLfloat color_highlight[4] = { 2, 2, 2, 1 };



     for (int i = 0; i < NCUBES; i++) {

          glm::mat4 model = glm::scale(

                    glm::translate(glm::mat4(1.0f), positions),

                    glm::vec3(0.2, 0.2, 0.2));



          glm::mat4 anim = glm::rotate(glm::mat4(1.0f), angle * rotspeeds.x,

                    glm::vec3(1, 0, 0)) * // X axis

                    glm::rotate(glm::mat4(1.0f), angle * rotspeeds.y,

                              glm::vec3(0, 1, 0)) * // Y axis

                    glm::rotate(glm::mat4(1.0f), angle * rotspeeds.z,

                              glm::vec3(0, 0, 1)); // Z axis



          glm::mat4 mvp = projection * view * model * anim;

          glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, glm::value_ptr(mvp));



          if (highlight)

               glUniform4fv(uniform_color, 1, color_highlight);

          else

               glUniform4fv(uniform_color, 1, color_normal);



          glStencilFunc(GL_ALWAYS, i + 1, -1);



          /* Push each element in buffer_vertices to the vertex shader */

          glDrawElements(GL_TRIANGLES, size / sizeof(GLushort), GL_UNSIGNED_SHORT,

                    0);

     }

     float* m_position = (float*) this->PVRShellGet(prefPointerLocation);



     if (m_position) {



          /* Read color, depth and stencil index from the framebuffer */

          GLbyte color[4];

          GLfloat depth;

          GLuint index;

          GLint x = m_position[0] *640;

          GLint y = m_position[1] *480;



     //      printf(" click on x,y %i %i %fn", x,y,depth);





           glReadPixels(x, screen_height-y , 1, 1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1,

           color);

           glReadPixels(x, screen_height-y , 1, 1, GL_DEPTH_COMPONENT,

           GL_FLOAT, &depth);

           glReadPixels(x, screen_height- y , 1, 1, GL_STENCIL_INDEX,

                     GL_UNSIGNED_SHORT_5_5_5_1, &index);



           printf(

           "Clicked on pixel %d, %d, color %02hhx %02hhx %02hhx %02hhx, depth %f, stencil index %un",

           x, y, color[0], color[1], color[2], color[3], depth, index);



          /* Convert from window coordinates to object coordinates */

          glm::mat4 view = glm::lookAt(camera_position, glm::vec3(0.0, 0.0, 0.0),

                    glm::vec3(0.0, 1.0, 0.0));

          glm::mat4 projection = glm::perspective(45.0f,

                    1.0f * screen_width / screen_height, 0.1f, 10.0f);

          glm::vec4 viewport = glm::vec4(0, 0, screen_width, screen_height);



          glm::vec3 wincoord = glm::vec3(x, screen_height - y - 1, -1);

          glm::vec3 objcoord = glm::unProject(wincoord, view, projection,

                    viewport);



          /* Which box is nearest to those object coordinates? */

          int closest_i = 0;





     }

     glDisableVertexAttribArray(attribute_coord3d);

     glDisableVertexAttribArray(attribute_texcoord);

     return true;

}

#6

Hi David,

The glReadPixels calls you are making for depth and stencil values are not valid. The formats supported by OpenGL ES 2.0 are GL_ALPHA, GL_RGB and GL_RGBA.
You can find out more from the OpenGL ES 2.0 reference pages here and/or by reading the OpenGL ES 2.0 spec here




#7


Helo JOE,



Thanks , i see :

type

Specifies the data type of the pixel data. Must be one of GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, or GL_UNSIGNED_SHORT_5_5_5_1.



so it is set now but i still cannot get the depth and stencil value , how concretly will you do that ?



thanks



dave

#8

It’s not possible to retrieve the depth and stencil buffers with glReadPixels() in OpenGL ES 2.0.

As a work around for retrieving depth values, you could bind a depth texture to an FBO render pass, blit the depth texture to a colour buffer of the same resolution (e.g. a second FBO) and then use glReadPixels() to retrieve the colour buffer that contains your depth values.

There are workarounds to retrieve stencil buffer values, but they are non-trivial (it would involve multiple render passes and stencil mask tricks, among other complexities)




#9

Thank you very much for your help, i will select then standard ray picking ;))))