1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: TestGPURayCastBlendModes.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15
16 /**
17 * Tests support for blend modes with translucent geometry (similar to
18 * TestGPURayCastBlendModes).
19 *
20 * Maximum, Minimum, Additive and Average blend modes are only partially
21 * correct when using translucent geometry given that vtkDualDepthPeelingPass
22 * renders volumes through various intermediate passes and composites the
23 * intermediate results using under and over blending. Hence, Max, Min,
24 * Additive and Average values are only locally correct in areas overlapping
25 * with translucent geometry.
26 */
27
28 #include "vtkCamera.h"
29 #include "vtkColorTransferFunction.h"
30 #include "vtkGPUVolumeRayCastMapper.h"
31 #include "vtkImageData.h"
32 #include "vtkNew.h"
33 #include "vtkOpenGLRenderer.h"
34 #include "vtkPiecewiseFunction.h"
35 #include "vtkPolyDataMapper.h"
36 #include "vtkProperty.h"
37 #include "vtkRegressionTestImage.h"
38 #include "vtkRenderWindow.h"
39 #include "vtkRenderWindowInteractor.h"
40 #include "vtkRenderer.h"
41 #include "vtkSphereSource.h"
42 #include "vtkTestingObjectFactory.h"
43 #include "vtkVolume.h"
44 #include "vtkVolumeProperty.h"
45
TestGPURayCastDepthPeelingBlendModes(int argc,char * argv[])46 int TestGPURayCastDepthPeelingBlendModes(int argc, char* argv[])
47 {
48 // Volume peeling is only supported through the dual depth peeling algorithm.
49 // If the current system only supports the legacy peeler, skip this test:
50 vtkNew<vtkRenderWindow> renWin;
51 vtkNew<vtkRenderWindowInteractor> iren;
52 iren->SetRenderWindow(renWin);
53
54 vtkNew<vtkRenderer> ren;
55 renWin->Render(); // Create the context
56 renWin->AddRenderer(ren);
57 vtkOpenGLRenderer* oglRen = vtkOpenGLRenderer::SafeDownCast(ren);
58 assert(oglRen); // This test should only be enabled for OGL2 backend.
59 // This will print details about why depth peeling is unsupported:
60 oglRen->SetDebug(true);
61 bool supported = oglRen->IsDualDepthPeelingSupported();
62 oglRen->SetDebug(false);
63 if (!supported)
64 {
65 std::cerr << "Skipping test; volume peeling not supported.\n";
66 return VTK_SKIP_RETURN_CODE;
67 }
68 renWin->RemoveRenderer(ren);
69
70 cout << "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)" << endl;
71
72 int dims[3] = { 100, 100, 100 };
73 int boundary[3] = { 10, 10, 10 };
74
75 // Create a vtkImageData with two components
76 vtkNew<vtkImageData> image;
77 image->SetDimensions(dims[0], dims[1], dims[2]);
78 image->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
79
80 // Fill the first half rectangular parallelopiped along X with the
81 // first component values and the second half with second component values
82 unsigned char* ptr = static_cast<unsigned char*>(image->GetScalarPointer(0, 0, 0));
83
84 for (int z = 0; z < dims[2]; ++z)
85 {
86 for (int y = 0; y < dims[1]; ++y)
87 {
88 for (int x = 0; x < dims[0]; ++x)
89 {
90 if ((z < boundary[2] || z > (dims[2] - boundary[2] - 1)) ||
91 (y < boundary[1] || y > (dims[1] - boundary[1] - 1)) ||
92 (x < boundary[0] || x > (dims[0] - boundary[0] - 1)))
93 {
94 *ptr++ = 255;
95 }
96 else
97 {
98 *ptr++ = 0;
99 }
100 }
101 }
102 }
103
104 vtkNew<vtkColorTransferFunction> color;
105 color->AddRGBPoint(0.0, 0.2, 0.3, 0.6);
106 color->AddRGBPoint(255.0, 0.2, 0.6, 0.3);
107
108 vtkNew<vtkPiecewiseFunction> opacity;
109 opacity->AddPoint(0.0, 0.0);
110 opacity->AddPoint(255.0, 0.8);
111
112 vtkNew<vtkVolumeProperty> property;
113 property->SetScalarOpacity(opacity);
114 property->SetColor(color);
115
116 vtkNew<vtkVolume> volume[4];
117
118 vtkNew<vtkGPUVolumeRayCastMapper> mapper[4];
119 mapper[0]->SetBlendModeToMaximumIntensity();
120 mapper[1]->SetBlendModeToMinimumIntensity();
121 mapper[2]->SetBlendModeToAdditive();
122 mapper[3]->SetBlendModeToAverageIntensity();
123
124 renWin->SetMultiSamples(0);
125 renWin->SetSize(301, 300); // Intentional NPOT size
126
127 vtkNew<vtkRenderer> renderer[4];
128 renderer[0]->SetViewport(0.0, 0.0, 0.5, 0.5);
129 renderer[1]->SetViewport(0.5, 0.0, 1.0, 0.5);
130 renderer[2]->SetViewport(0.0, 0.5, 0.5, 1.0);
131 renderer[3]->SetViewport(0.5, 0.5, 1.0, 1.0);
132
133 // Translucent geometry
134 vtkNew<vtkSphereSource> sphereSource;
135 sphereSource->SetCenter(90.0, 90.0, 15.0);
136 sphereSource->SetRadius(30.0);
137
138 vtkNew<vtkActor> sphereActor;
139 vtkProperty* sphereProperty = sphereActor->GetProperty();
140 sphereProperty->SetColor(1., 0.9, 1);
141 sphereProperty->SetOpacity(0.4);
142
143 vtkNew<vtkPolyDataMapper> sphereMapper;
144 sphereMapper->SetInputConnection(sphereSource->GetOutputPort());
145 sphereActor->SetMapper(sphereMapper);
146
147 for (int i = 0; i < 4; ++i)
148 {
149 mapper[i]->SetInputData(image);
150 volume[i]->SetMapper(mapper[i]);
151 volume[i]->SetProperty(property);
152
153 renderer[i]->AddVolume(volume[i]);
154 renderer[i]->AddActor(sphereActor);
155
156 renderer[i]->SetUseDepthPeeling(1);
157 renderer[i]->SetOcclusionRatio(0.0);
158 renderer[i]->SetMaximumNumberOfPeels(5);
159 renderer[i]->SetUseDepthPeelingForVolumes(true);
160 renderer[i]->SetBackground(0.3, 0.3, 0.3);
161 renderer[i]->GetActiveCamera()->Yaw(20.0);
162 renderer[i]->ResetCamera();
163
164 renWin->AddRenderer(renderer[i]);
165 }
166
167 renWin->Render();
168
169 int retVal = vtkTesting::Test(argc, argv, renWin, 15);
170 if (retVal == vtkRegressionTester::DO_INTERACTOR)
171 {
172 iren->Start();
173 }
174
175 if ((retVal == vtkTesting::PASSED) || (retVal == vtkTesting::DO_INTERACTOR))
176 {
177 return EXIT_SUCCESS;
178 }
179 else
180 {
181 return EXIT_FAILURE;
182 }
183 }
184