I’ve tested this and you can get the correct reverse perspective by inverting the sign of the third column of the perspective projection matrix:
Surface rendering
Normal perspective:
Reverse perspective:
Volume rendering
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).
Normal perspective:
Reverse perspective:
Implementation
This is the change that would be needed in vtkCamera:
I used this change in 3D Slicer to create the screenshots above like this:
threeDViewNode = slicer.app.layoutManager().threeDWidget(0).threeDView().mrmlViewNode()
cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)
cameraNode.GetCamera().SetReversePerspective(True)
You could clone the perspective matrix computation in your code, insert the column sign inversion there, and set the matrix explicitly, which would require more code to maintain but then you would not need to modify VTK.