Sign in to follow this  
adam17

OpenGL object picking

Recommended Posts

ive been looking around the net for explanations on object picking in opengl. unfortunately they seem all a little too tedious (compared to what i came up with) or imprecise. some articles ive read mention that the selection buffer in opengl only offers 4bits for color. i came up with the idea to store a color index with each object i draw into the buffer. as im storing the objects i will increment a 24bit variable (or 3 ints). red would be first, then add green into the mix, and finally blue. this would give me up to 2^24 colors. i doubt ill be putting more than 16 million triangles into a scene at once, so color repetition doesnt seem to be a problem. when i go to point the cursor, i can do a real quick glReadPixels() of a 1x1 pixel to get the color that was found. using that color will give me the offset into the array of objects. i cant see any flaws in this plan. if anybody has experimented with this in the past, or has heard of flaws, could you let me know? id hate to spend a lot of time on this only to find out that its performance blows :P thanks -adam

Share this post


Link to post
Share on other sites
Yes, this works. I've done that before, but there are a few flaws.

Not all cards may render colors exact, meaning that say RGB(255,33,23) may be read back as RGB(255,34,23). Though in general, I've never had this problem as long as you disable texturing, lighting, multisample etc etc. Make sure to set the color with glColor3ub() instead of glColor3f().

Another issue is that when the user runs the OS in 16-bit color mode, it will be broken as colors will be modified.

Reading back stuff (glReadPixels) stalls the pipeline, so it may not be very fast compared to a raytest on the CPU, but if you only do the picking routine once every while when the user clicks inside the viewport and not constantly there should be performance issue. If you want something like a hover effect where the mouse cursor changes, you can keep a copy of the entire framebuffer on the application side (read back the framebuffer only if the scene changes).

Share this post


Link to post
Share on other sites
performance isnt much of an issue. im trying to design a terrain editor. i like the idea of saving a copy of the framebuffer whenever the scene changes. if that can let me get rid of using glReadPixels(), it will definitely help speed it up. i plan to disable everything but coloring, like texturing, lighting, multisampling and shaders.

i appreciate the help!

Share this post


Link to post
Share on other sites
Quote:
Original post by remdul
Reading back stuff (glReadPixels) stalls the pipeline, so it may not be very fast compared to a raytest on the CPU, but if you only do the picking routine once every while when the user clicks inside the viewport and not constantly there should be performance issue. If you want something like a hover effect where the mouse cursor changes, you can keep a copy of the entire framebuffer on the application side (read back the framebuffer only if the scene changes).


how exactly would i go about doing raytesting? do you know of any places i can read up on it?

Share this post


Link to post
Share on other sites
I'm personally not a huge fan of the item buffer method, for a number of reasons:

1) Along the lines of what remdul said, all but the latest graphics cards (namely the G80) work exclusive with floating-point values, meaning that there's a chance you won't get exact equality when comparing items or experience inconsistent behavior across hardware.

2) Any render-based method can potentially suffer from Z-fighting on distant objects.

3) You only get pixel-perfect selection. While this can be beneficial if there are many objects real close together or stacked on top of each other, if the object is really far away or at such an angle that only a tiny sliver is visible, it's difficult to select.

3) You'd need to either render your objects again in a second pass to the item buffer or require MRT support to do it in a single pass (which I hear can be real slow on some cards).

4) If you wanted to select multiple objects ala a selection rectangle, you'd have to iterate over each pixel in the returned item buffer and merge their values into a unique list. Also, it would be impossible to select completely hidden objects should that be something you want to add later.

The only real benefit is that it scales extremely well when you have a lot of objects in the scene. Instead of performing a ray-object intersection test for every object, you just render them and only the top-most ones are selectable. The graphics card can tear through simple flat-shaded triangles that have no special shaders or other processing like nobody's business. And I suppose you could always use depth peeling to get more objects underneath the selection.

You can probably just Google for more information on ray casting and ray-picking, or ray-sphere/ray-triangle/ray-object etc. intersection references. For selecting against a frustum (which is what you get when you back-project a selection rectangle), look up the SAT test.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Forum Statistics

    • Total Topics
      627736
    • Total Posts
      2978866
  • Similar Content

    • By DelicateTreeFrog
      Hello! As an exercise for delving into modern OpenGL, I'm creating a simple .obj renderer. I want to support things like varying degrees of specularity, geometry opacity, things like that, on a per-material basis. Different materials can also have different textures. Basic .obj necessities. I've done this in old school OpenGL, but modern OpenGL has its own thing going on, and I'd like to conform as closely to the standards as possible so as to keep the program running correctly, and I'm hoping to avoid picking up bad habits this early on.
      Reading around on the OpenGL Wiki, one tip in particular really stands out to me on this page:
      For something like a renderer for .obj files, this sort of thing seems almost ideal, but according to the wiki, it's a bad idea. Interesting to note!
      So, here's what the plan is so far as far as loading goes:
      Set up a type for materials so that materials can be created and destroyed. They will contain things like diffuse color, diffuse texture, geometry opacity, and so on, for each material in the .mtl file. Since .obj files are conveniently split up by material, I can load different groups of vertices/normals/UVs and triangles into different blocks of data for different models. When it comes to the rendering, I get a bit lost. I can either:
      Between drawing triangle groups, call glUseProgram to use a different shader for that particular geometry (so a unique shader just for the material that is shared by this triangle group). or
      Between drawing triangle groups, call glUniform a few times to adjust different parameters within the "master shader", such as specularity, diffuse color, and geometry opacity. In both cases, I still have to call glBindTexture between drawing triangle groups in order to bind the diffuse texture used by the material, so there doesn't seem to be a way around having the CPU do *something* during the rendering process instead of letting the GPU do everything all at once.
      The second option here seems less cluttered, however. There are less shaders to keep up with while one "master shader" handles it all. I don't have to duplicate any code or compile multiple shaders. Arguably, I could always have the shader program for each material be embedded in the material itself, and be auto-generated upon loading the material from the .mtl file. But this still leads to constantly calling glUseProgram, much more than is probably necessary in order to properly render the .obj. There seem to be a number of differing opinions on if it's okay to use hundreds of shaders or if it's best to just use tens of shaders.
      So, ultimately, what is the "right" way to do this? Does using a "master shader" (or a few variants of one) bog down the system compared to using hundreds of shader programs each dedicated to their own corresponding materials? Keeping in mind that the "master shaders" would have to track these additional uniforms and potentially have numerous branches of ifs, it may be possible that the ifs will lead to additional and unnecessary processing. But would that more expensive than constantly calling glUseProgram to switch shaders, or storing the shaders to begin with?
      With all these angles to consider, it's difficult to come to a conclusion. Both possible methods work, and both seem rather convenient for their own reasons, but which is the most performant? Please help this beginner/dummy understand. Thank you!
    • By JJCDeveloper
      I want to make professional java 3d game with server program and database,packet handling for multiplayer and client-server communicating,maps rendering,models,and stuffs Which aspect of java can I learn and where can I learn java Lwjgl OpenGL rendering Like minecraft and world of tanks
    • By AyeRonTarpas
      A friend of mine and I are making a 2D game engine as a learning experience and to hopefully build upon the experience in the long run.

      -What I'm using:
          C++;. Since im learning this language while in college and its one of the popular language to make games with why not.     Visual Studios; Im using a windows so yea.     SDL or GLFW; was thinking about SDL since i do some research on it where it is catching my interest but i hear SDL is a huge package compared to GLFW, so i may do GLFW to start with as learning since i may get overwhelmed with SDL.  
      -Questions
      Knowing what we want in the engine what should our main focus be in terms of learning. File managements, with headers, functions ect. How can i properly manage files with out confusing myself and my friend when sharing code. Alternative to Visual studios: My friend has a mac and cant properly use Vis studios, is there another alternative to it?  
    • By ferreiradaselva
      Both functions are available since 3.0, and I'm currently using `glMapBuffer()`, which works fine.
      But, I was wondering if anyone has experienced advantage in using `glMapBufferRange()`, which allows to specify the range of the mapped buffer. Could this be only a safety measure or does it improve performance?
      Note: I'm not asking about glBufferSubData()/glBufferData. Those two are irrelevant in this case.
    • By xhcao
      Before using void glBindImageTexture(    GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format), does need to make sure that texture is completeness. 
  • Popular Now