Hardware Selector with transparency returning wrong attribute ID/prop ID

Hello, I am looking for some help to make hardware selector return correct attributeID and propID in the presence of opacity.

Very basically, I am trying to select faces of a polydata using the hardware selector, but am finding that when actors have opacity < 1, the attributeID and propID returned (often, but not always) refer to the furthest away objects instead of the one I am clicking on (i.e., my pick appears to go through to the other side… as if the order was reversed…). This applies to faces in a single object (i.e., I pick faces on the other side of the transparent object), as well as when making a pick when another transparent object is behind (faces from the other object are selected). The really odd thing is that the xyz position is correct, its just the attributeID and propID that point to the wrong thing.

The behavior is demonstrated in this screengrab, and in the js-fiddle that follows:

picking-hw-opacity

I am wondering if there is something clearly wrong being done in this example? Most of the logic is borrowed from the Hardware Selector example on the vtk-js docs.

Thanks in advance!

My understanding is the following:

  • the XYZ coordinates are calculated from the depth buffer
  • the attributeID and propID are calculated from the color buffer.
    For each attribute and prop, a unique color is given. Due to translucency, colors may be merged, hence the odd results ?

I think the best would be to dig into the code to understand what’s going on.
I wonder if it would make sense to temporarily turn off translucency for picking…

Thank you for the reply! I added:

  const opacities = renderer.getActors().map(a =>  [a.getProperty(), a.getProperty().getOpacity()]);
  renderer.getActors().forEach((a) => a.getProperty().setOpacity(1));

before the hardwareSelector.getSourceDataAsync call, then

opacities.map(([p, o]) => p.setOpacity(o));

after … this seems to have had the desired effect… I have not evaluated this on a “real” sized dataset… I am wondering if performance will suffer if I apply this tweak? Would this also be the prescribed way to ensure the pick is what I am actually clicking on with HW selector?

Glad to hear it works.
This is indeed NOT the correct way to fix it.
It should be handled automatically at mapper/shader level.
But that requires digging into the code to make sure it is done correctly.

Does this warrant a report on the main VTKjs repo?

Does this warrant a report on the main VTKjs repo?

I meant that what I suggested was a “hack”. Ideally, it should be fixed properly in VTK.js repo.
However this is a time-consuming task. If you have such time, feel free to dig into the code and make a PR, otherwise if you have funding we can look at it.

Just wanted to report - even though this is a hack, it is MUUUUCH faster than relying on the raycast pickers for large, complex transparent actors, with no perceptible flicker in the render window during the pick.

I’d like to log this as a bug in the VTKjs repo, at least for tracking purposes, and if time (and skill) allows will open a PR to resolve.

Thanks for reporting the issue.

BTW, you can simplify your hack a little more by doing the following since vtkObject use closures:

const opacities = renderer.getActors()
   .map(a => [
        a.getProperty().setOpacity, 
        a.getProperty().getOpacity()
    ]);

opacities.forEach(([s, o]) => s(1));
// hardware select
opacities.forEach(([s, o]) => s(o));

And ideally if you create and save those lambdas globally, you won’t hit any garbage collection.