Negative values in vtkCamera projection transform breaks GPU volume raycast mapper

Hi everyone,

I’m having issues with the vtkOpenGLGPUVolumeRayCastMapper class. What seems to work with the vtkFixedPointVolumeRaycastMapper doesn’t seem to work with the GPU variant.

To be more precise, I’m flipping the X and Y axis of the vtkCamera projection transform by setting the 0th and 5th values of the matrix to -1

Here are some screenshots of it working perfectly with the vtkFixedPointVolumeRaycastMapper:


Here are some screenshots of it breaking with the vtkOpenGLGPUVolumeRayCastMapper :


When only flipping X or Y we can see the tips of the model, so it’s almost working but not quite.
Seemingly the signs cancel when flipping both X and Y, which makes things work again?

On a probably related note, I’m also having issues with the lighting when reversing the Z axis.

I’ve taken a look at the shader of vtkOpenGLGPUVolumeRayCastMapper but did not manage to figure out why would this happen.

What I’m doing is similar to what’s being done in this thread:

What @lassoan says

It also works for CPU volume rendering (unfortunately, ray computation seem to be implemented with some custom logic in the GPU volume renderer, so that would need some fixes).

seems to imply that it would be possible to fix, if that’s the case what would be the potential fix or lead to explore?

Any help would be greatly appreciated !
Thank you

Yes, GPU volume rendering ray computation would need an update to allow reverse perspective rendering. This rendering mode is essential for fluoroscopy fusion applications, but not for much else, so waiting for some project to fund the development could take years. If you need it sooner then you can try to implement it yourself or give a small contract to Kitware or other developers experienced with VTK rendering to implement it for you.

Could you try to bypass the IsCameraInside() check in vtkOpenGLGPUVolumeRayCastMapper to see if it helps please?

Thank you for the prompt reply!

I’m willing to give it a go myself, if anyone has any resources regarding the implementation used that would be very helpful.

Sadly it didn’t change anything.
I also checked its return value and it seems to behave the same with the axis flipped.

Ok thanks for trying.
Then you might want to check the computation of rayOrigin and rayTermination as well as code involving g_skip.

Thank you for your help!

Regarding the computation of rayOrigin you pointed to, by default UseDepthPass is turned off so this part of the shader is not executed from my observations (I’m outputing the compiled shader to file inside the BuildShader method, I’m not sure this is the best method but I haven’t found another solution)

Simply enabling UseDepthPass seems to break the rendering. Barely anything renders:

The documentation points at the need to define contour values which I did, this is the result:
gpu_mapper_usedepthpass_contour_rotX90

However after removing the initial rotation I applied to the volume, the rendering seems mostly okay except for a weird artifact at the bottom:
gpu_mapper_usedepthpass_contour

Moreover, without the rotation, the X/Y axis flip seems to work!

So it seems that transformations applied to volumes are at cause?

Sorry for the late reply. I think the reason why it works better with the depth pass is because the ray origin is computed by taking the projection matrix into account in this case (see here). Maybe a similar approach can be implemented without using the depth pass, but then there will be probably other issues with lighting, clipping,…
Just to understand the use case, could flipping the image on the CPU with vtkImageFlip be an option? or does it really have to be done at the rendering step?

Flipping the image is not an option, as all the sizes are correct as they are (anterior part of the patient is farther from the generator, so magnification factor is smaller than for the posterior side), but the clinician usually wants to see the anterior part appear in the front (occluding the posterior side).

Everything (lighting, etc.) works well for surface rendering, and even for volume rendering with the CPU mapper. Only the GPU mapper is broken with reverse persepective projection.

1 Like