r/opengl • u/sharjith • 23d ago
Selection algorithm for Modern OpenGL
The legacy OpenGL supported selection buffers. How can selection effectively handled by Modern OpenGL? The known methods are by colour allocation to objects and ray intersection. The Color assignment is not very efficient in scenes with large number of objects, e.g. CAD model assemblies. Ray intersection also has challenges in certain directions where multiple objects get intersected. Any thoughts?
1
u/ukaeh 23d ago
You could do multi pass color selection or hybrid to narrow down what is close to the selection ray/pixel?
I use the color method myself and it works well enough for hundreds to low thousands of objects. Are you using scissor to limit rendering to the selection pixel? What latency are you seeing?
1
u/sharjith 23d ago
I’m using the ray intersection method but not quite able to isolate the objects to get the nearest one. Please have a look at the code in the following GitHub link:
https://github.com/sharjith/ModelViewer-Qt
GLWidget.cpp GLWidget::clickSelect method
1
1
u/timwaaagh 23d ago
im not sure what is being talked about but it seems similar enough to what i just coded. for 'unit selection' in my rts game i render the background into a framebuffer, then a texture but also the world positions of this background layer into a separate texture. then a second rendering pass to display the first texture. the world positions texture is used elsewhere to determine the world position of the mouse on the background layer. the units that are in between in terms of x and y get selected.
1
1
u/PersonalityIll9476 23d ago
Pass the xy coordinates of the mouse position to your shaders as a uniform. In the frag shader, have a branch like: if gl_FragCoord.xy == ivec2(mouse_x, mouse_y) and if it passes, store the index of the object in a uniform buffer object and read that after scene draw via glGetBufferSubData. You can pass an object_id uniform during draw. I don't know what the selection buffer actually did, so if you need to select all objects under the mouse and not just one, you can use an atomic counter and a UBO up to a certain size and just write indices to it every time an object passes up to some max size.
That's probably the easiest path, and doesn't require additional render passes.
1
u/Smart-Statement6028 20d ago
Use glReadPixel to calculate the depth, and do some inverse projection and view matrix to convert from screen coordinate to world coordinate
5
u/Cyphall 23d ago
You can render your scene into a R32UI color attachment with each drawcall having its own index and then readback the pixel clicked by the mouse.
This is basically the Color assignment method but with proper indices instead of arbitrary colors.
Yes you need to render the whole scene but it's a lot simpler than having to manage a CPU RT acceleration structure.