CustusX  22.04-rc5
An IGT application
CorrectlyRenderTranslucentGeometry.cxx
Go to the documentation of this file.
1 /*
2  * CorrectlyRenderTranslucentGeometry.cxx
3  *
4  * Copied from http://www.vtk.org/Wiki/VTK/Examples/Cxx/Visualization/CorrectlyRenderingTranslucentGeometry
5  *
6  * Created on: Sep 10, 2012
7  * Author: olevs
8  */
9 
10 #include <vtkSphereSource.h>
11 #include <vtkSmartPointer.h>
12 #include <vtkAppendPolyData.h>
13 #include <vtkCamera.h>
14 #include <vtkPolyDataMapper.h>
15 #include <vtkActor.h>
16 #include <vtkRenderer.h>
17 #include <vtkRenderWindow.h>
18 #include <vtkProperty.h>
19 #include <vtkRenderWindowInteractor.h>
20 #include <vtkTimerLog.h>
21 #include <vtkTransform.h>
22 #include <vtkDepthSortPolyData.h>
23 
32 vtkSmartPointer<vtkAppendPolyData> GenerateOverlappingBunchOfSpheres(int theta,
33  int phi)
34 {
35  vtkSmartPointer<vtkAppendPolyData> appendData =
36  vtkSmartPointer<vtkAppendPolyData>::New();
37 
38  for (int i = 0; i < 5; i++)
39  {
40  vtkSmartPointer<vtkSphereSource> sphereSource =
41  vtkSmartPointer<vtkSphereSource>::New();
42  sphereSource->SetThetaResolution(theta);
43  sphereSource->SetPhiResolution(phi);
44  sphereSource->SetRadius(0.5); // all spheres except the center
45  // one should have radius = 0.5
46  switch (i)
47  {
48  case 0:
49  sphereSource->SetRadius(1);
50  sphereSource->SetCenter(0, 0, 0); break;
51  case 1:
52  sphereSource->SetCenter(1, 0, 0); break;
53  case 2:
54  sphereSource->SetCenter(-1, 0, 0); break;
55  case 3:
56  sphereSource->SetCenter(0, 1, 0); break;
57  case 4:
58  sphereSource->SetCenter(0, -1, 0); break;
59  }
60  sphereSource->Update();
61  appendData->AddInputConnection(sphereSource->GetOutputPort());
62  }
63 
64  return appendData;
65 }
66 
79  vtkSmartPointer<vtkRenderWindow> renderWindow,
80  vtkSmartPointer<vtkRenderer> renderer, int maxNoOfPeels,
81  double occlusionRatio)
82 {
83  if (!renderWindow || !renderer)
84  return false;
85 
86  // 1. Use a render window with alpha bits (as initial value is 0 (false)):
87  renderWindow->SetAlphaBitPlanes(true);
88 
89  // 2. Force to not pick a framebuffer with a multisample buffer
90  // (as initial value is 8):
91  renderWindow->SetMultiSamples(0);
92 
93  // 3. Choose to use depth peeling (if supported) (initial value is 0 (false)):
94  renderer->SetUseDepthPeeling(true);
95 
96  // 4. Set depth peeling parameters
97  // - Set the maximum number of rendering passes (initial value is 4):
98  renderer->SetMaximumNumberOfPeels(maxNoOfPeels);
99  // - Set the occlusion ratio (initial value is 0.0, exact image):
100  renderer->SetOcclusionRatio(occlusionRatio);
101 
102  return true;
103 }
104 
116 bool IsDepthPeelingSupported(vtkSmartPointer<vtkRenderWindow> renderWindow,
117  vtkSmartPointer<vtkRenderer> renderer,
118  bool doItOffScreen)
119 {
120  if (!renderWindow || !renderer)
121  {
122  return false;
123  }
124 
125  bool success = true;
126 
127  // Save original renderer / render window state
128  bool origOffScreenRendering = renderWindow->GetOffScreenRendering() == 1;
129  bool origAlphaBitPlanes = renderWindow->GetAlphaBitPlanes() == 1;
130  int origMultiSamples = renderWindow->GetMultiSamples();
131  bool origUseDepthPeeling = renderer->GetUseDepthPeeling() == 1;
132  int origMaxPeels = renderer->GetMaximumNumberOfPeels();
133  double origOcclusionRatio = renderer->GetOcclusionRatio();
134 
135  // Activate off screen rendering on demand
136  renderWindow->SetOffScreenRendering(doItOffScreen);
137 
138  // Setup environment for depth peeling (with some default parametrization)
139  success = success && SetupEnvironmentForDepthPeeling(renderWindow, renderer,
140  100, 0.1);
141 
142  // Do a test render
143  renderWindow->Render();
144 
145  // Check whether depth peeling was used
146  success = success && renderer->GetLastRenderingUsedDepthPeeling();
147 
148  // recover original state
149  renderWindow->SetOffScreenRendering(origOffScreenRendering);
150  renderWindow->SetAlphaBitPlanes(origAlphaBitPlanes);
151  renderWindow->SetMultiSamples(origMultiSamples);
152  renderer->SetUseDepthPeeling(origUseDepthPeeling);
153  renderer->SetMaximumNumberOfPeels(origMaxPeels);
154  renderer->SetOcclusionRatio(origOcclusionRatio);
155 
156  return success;
157 }
158 
180 int main (int argc, char *argv[])
181 {
182  if (argc != 7)
183  {
184  cerr << "Usage: " << argv[0] << " Theta Phi MaximumPeels " <<
185  "OcclusionRatio ForceDepthSortingFlag " <<
186  "DoNotUseAnyDepthRelatedAlgorithmFlag" << std::endl;
187  return EXIT_FAILURE;
188  }
189 
190  int theta = atoi(argv[1]);
191  int phi = atoi(argv[2]);
192  int maxPeels = atoi(argv[3]);
193  double occulusionRatio = atof(argv[4]);
194  bool forceDepthSort = atoi(argv[5]) == 1;
195  bool withoutAnyDepthThings = atoi(argv[6]) == 1;
196 
197  // Generate a translucent sphere poly data set that partially overlaps:
198  vtkSmartPointer<vtkAppendPolyData> translucentGeometry =
200 
201  // generate a basic Mapper and Actor
202  vtkSmartPointer<vtkPolyDataMapper> mapper =
203  vtkSmartPointer<vtkPolyDataMapper>::New();
204  mapper->SetInputConnection(translucentGeometry->GetOutputPort());
205 
206  vtkSmartPointer<vtkActor> actor =
207  vtkSmartPointer<vtkActor>::New();
208  actor->SetMapper(mapper);
209  actor->GetProperty()->SetOpacity(0.5); // translucent !!!
210  actor->GetProperty()->SetColor(1, 0, 0);
211  actor->RotateX(-72); // put the objects in a position where it is easy to see
212  // different overlapping regions
213 
214  // Create the RenderWindow, Renderer and RenderWindowInteractor
215  vtkSmartPointer<vtkRenderer> renderer =
216  vtkSmartPointer<vtkRenderer>::New();
217  vtkSmartPointer<vtkRenderWindow> renderWindow =
218  vtkSmartPointer<vtkRenderWindow>::New();
219  renderWindow->AddRenderer(renderer);
220  vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
221  vtkSmartPointer<vtkRenderWindowInteractor>::New();
222  renderWindowInteractor->SetRenderWindow(renderWindow);
223 
224  // Add the actors to the renderer, set the background and size
225  renderer->AddActor(actor);
226  renderer->SetBackground(1, 1, 1);
227  renderWindow->SetSize(600, 400);
228 
229  // Setup view geometry
230  renderer->ResetCamera();
231  renderer->GetActiveCamera()->Zoom(2.2); // so the object is larger
232 
233  // Answer the key question: Does this box support GPU Depth Peeling?
234  bool useDepthPeeling = IsDepthPeelingSupported(renderWindow, renderer, true);
235  std::cout << "DEPTH PEELING SUPPORT: " << (useDepthPeeling ? "YES" : "NO") << std::endl;
236 
237  int success = EXIT_SUCCESS;
238 
239  // Use depth peeling if available and not explicitly prohibited, otherwise we
240  // use manual depth sorting
241  std::cout << std::endl << "CHOSEN MODE: ";
242  if (useDepthPeeling && !forceDepthSort && !withoutAnyDepthThings) // GPU
243  {
244  std::cout << "*** DEPTH PEELING ***" << std::endl;
245  // Setup GPU depth peeling with configured parameters
246  success = !SetupEnvironmentForDepthPeeling(renderWindow, renderer,
247  maxPeels, occulusionRatio);
248  }
249  else if (!withoutAnyDepthThings) // CPU
250  {
251  std::cout << "*** DEPTH SORTING ***" << std::endl;
252  // Setup CPU depth sorting filter
253  vtkSmartPointer<vtkDepthSortPolyData> depthSort =
254  vtkSmartPointer<vtkDepthSortPolyData>::New();
255  depthSort->SetInputConnection(translucentGeometry->GetOutputPort());
256  depthSort->SetDirectionToBackToFront();
257  depthSort->SetVector(1, 1, 1);
258  depthSort->SetCamera(renderer->GetActiveCamera());
259  depthSort->SortScalarsOff(); // do not really need this here
260  // Bring it to the mapper's input
261  mapper->SetInputConnection(depthSort->GetOutputPort());
262  depthSort->Update();
263  }
264  else
265  {
266  std::cout << "*** NEITHER DEPTH PEELING NOR DEPTH SORTING ***" << std::endl;
267  }
268 
269  // Initialize interaction
270  renderWindowInteractor->Initialize();
271 
272  // Check the average frame rate when rotating the actor
273  int endCount = 100;
274  vtkSmartPointer<vtkTimerLog> clock =
275  vtkSmartPointer<vtkTimerLog>::New();
276  // Set a user transform for successively rotating the camera position
277  vtkSmartPointer<vtkTransform> transform =
278  vtkSmartPointer<vtkTransform>::New();
279  transform->Identity();
280  transform->RotateY(2.0); // rotate 2 degrees around Y-axis at each iteration
281  vtkSmartPointer<vtkCamera> camera = renderer->GetActiveCamera();
282  double camPos[3]; // camera position
283  // Start test
284  clock->StartTimer();
285  for (int i = 0; i < endCount; i++)
286  {
287  camera->GetPosition(camPos);
288  transform->TransformPoint(camPos, camPos);
289  camera->SetPosition(camPos);
290  renderWindow->Render();
291  }
292  clock->StopTimer();
293  double frameRate = (double)endCount / clock->GetElapsedTime();
294  std::cout << "AVERAGE FRAME RATE: " << frameRate << " fps" << std::endl;
295 
296  // Start interaction
297  // renderWindowInteractor->Start();
298 
299 
300  return success;
301 }
bool SetupEnvironmentForDepthPeeling(vtkSmartPointer< vtkRenderWindow > renderWindow, vtkSmartPointer< vtkRenderer > renderer, int maxNoOfPeels, double occlusionRatio)
vtkSmartPointer< vtkAppendPolyData > GenerateOverlappingBunchOfSpheres(int theta, int phi)
int main(int argc, char *argv[])
bool IsDepthPeelingSupported(vtkSmartPointer< vtkRenderWindow > renderWindow, vtkSmartPointer< vtkRenderer > renderer, bool doItOffScreen)
float4 transform(float16 matrix, float4 voxel)