In my model, a mostly static large terrain in perspective view, I want to achieve two things:
a) Camera movement: change its speed depending on distance to closest point in view. Perhaps better pixel than vertex, I don’t know yet. It’s not the same to move walking (slow) than flying (fast).
b) Object selection with mouse.
I think that the best strategy is using a Framebuffer Object, because the fragment shader can output color and vertexID (passed from vertex shader) at the same time. I can use glBlitFramebuffer for the window and glReadPixels for the object selection. By the way, gl_VertexID is reset with every glDraw[XXX] command, right?
I could also calculate closest point to the camera in the fragment shader. But, where do I store it? I can’t set a 1x1 framebuffer because then the other fragment outputs (color, ID) would also be sent to a 1x1 buffer instead of a windowWidth x windowHeight. If possible, I want to avoid rendering in a second pass.
Can you help me with a good strategy?
First, camera control. Have you tried just using terrain height queried just below (and right around the camera) using CPU computations to drive your camera control? That should be both fast and efficient, particularly if you have some spatial acceleration data structure you can use for terrain lookups.
Second, picking. Since you’re only interested in points directly in-line with the pick position, would it make more sense and be faster to just intersect a ray against the scene (on the CPU), and return the closest object/primitive intersected?
While you could use the GPU to do intersection, you have the problem of 1) identifying in the readback which object/primitive was selected, and 2) dealing with the problem that readbacks if not done carefully will stall your pipeline and cause frame breakage (i.e. exceed your 60Hz frame time interval). #2 can be dealt with. However, what did you have in mind for #1? No, gl_VertexID isn’t typically unique across all of your draw calls. It’s the index you explicitly or implicitly pass into DrawElements or DrawArrays draw calls, respectively. So you could make it unique, but it could be quite a bit of trouble to do so on your part. Also, it of course identifies vertices and not fragments/pixels. So if (let’s say) you hit a large triangle, you won’t necessarily know very closely where you got a hit in space.