elect
elect

Reputation: 7190

Which mouse picking strategy for milions of primitives?

I am rendering models based on milions (up to ten) of triangles using VBOs and I need to detect which of these triangles the user may click on.

I try to read and understand how the "name stack" and the "unique-color" work. I found that the name stack can contain at max only 128 names, while the unique-color can have up to 2^(8+8+8) = 16777216 possible different colors, but sometimes there could be some approximations, so it can get modified..

Which is the best strategy for my case?

Upvotes: 3

Views: 2840

Answers (2)

El Marcel
El Marcel

Reputation: 1785

Basically, you have 2 classes of options:

  1. The "unique color way per triangle", which means you attach an id to every triangle, and render out the id's to a seperate render target. It can be 32 bit's (8 for rgb, 8 for a), but you could add a second one for even more ideas. It'll be fiddly to get the id's per triangle, but it's relatively easy to implement. Can be quite detrimental to performance though (fillrate).

  2. Proper ray tracing. You almost certainly want to have an acceleration structure (octree, kd,...), but you probably already have one for frustum culling. One ray really isn't a lot, this method should be very fast.

  3. Hybrid. probably the easiest to implement. Render out the vertex buffer id ("unique color per buffer:), and when you know which vertex buffer was selected", just trace a ray against all the triangles.

In the general case, I would say 2) is the best option. If you want to have something work quickly, go for 3). 1) is probably pretty useless.

Upvotes: 9

Hiep Vu
Hiep Vu

Reputation: 61

If your GPU card has OpenGL 4.2, you may use the function imageStore() in GLSL to mark the triangle Id in an image. In my case, I need to detect all triangles behind a predefined window on the screen. Picking (choosing rendered triangles on a window) works similarly. The selection runs in real-time for me.

The maximum size of an image (or texture) should >= 8192x8192 = 64 M. So it can be used up to 64 M primitives (and even more if we use 2, 3 images).

Saving all trianges Id behind the screen could be done with this fragment shader:

uniform  uimage2D id_image;

void main() 
{
    color_f = vec4(0)
    ivec2 p;
    p.x = gl_PrimitiveID % 2048;
    p.y = gl_PrimitiveID / 2048;
    imageStore(id_image, p, uvec4(255));
}

To save all trianges Id rendered on the screen: first, we precompute a depth buffer, then use a slightly different fragment shader:

uniform  uimage2D id_image;

**layout(early_fragment_tests) in;** //the shader does not run for fragment > depth

void main() 
{
    color_f = vec4(0)
    ivec2 p;
    p.x = gl_PrimitiveID % 2048;
    p.y = gl_PrimitiveID / 2048;
    imageStore(id_image, p, uvec4(255));
}

Upvotes: 6

Related Questions