1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    TestGPURayCastCompositeShadeMask.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 #include "vtkTestUtilities.h"
16 #include "vtkRegressionTestImage.h"
17 #include "vtkXMLImageDataReader.h"
18 #include "vtkImageData.h"
19 #include "vtkGPUVolumeRayCastMapper.h"
20 #include "vtkVolume.h"
21 #include "vtkVolumeProperty.h"
22 #include "vtkColorTransferFunction.h"
23 #include "vtkPiecewiseFunction.h"
24 #include "vtkImageGridSource.h"
25 #include "vtkImageCheckerboard.h"
26 #include "vtkRenderWindowInteractor.h"
27 #include "vtkRenderWindow.h"
28 #include "vtkRenderer.h"
29 #include "vtkOpenGLRenderWindow.h"
30 #include "vtkOpenGLExtensionManager.h"
31 #include "vtkCamera.h"
32 
TestGPURayCastCompositeShadeMask(int argc,char * argv[])33 int TestGPURayCastCompositeShadeMask(int argc, char *argv[])
34 {
35   cout << "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)" << endl;
36   char *cfname=
37     vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/vase_1comp.vti");
38 
39   vtkXMLImageDataReader *reader=vtkXMLImageDataReader::New();
40   reader->SetFileName(cfname);
41   delete [] cfname;
42 
43   reader->Update();
44   vtkImageData *input=reader->GetOutput();
45 
46   int dim[3];
47   double spacing[3];
48   input->GetSpacing(spacing);
49   input->GetDimensions(dim);
50 
51   vtkGPUVolumeRayCastMapper *mapper=vtkGPUVolumeRayCastMapper::New();
52   vtkVolume *volume=vtkVolume::New();
53   mapper->SetInputConnection(reader->GetOutputPort());
54   mapper->SetAutoAdjustSampleDistances(0);
55 
56    // assume the scalar field is a set of samples taken from a
57   // contiguous band-limited volumetric field.
58   // assume max frequency is present:
59   // min spacing divided by 2. Nyquist-Shannon theorem says so.
60   // sample distance could be bigger if we compute the actual max frequency
61   // in the data.
62   double distance=spacing[0];
63   if(distance>spacing[1])
64     {
65     distance=spacing[1];
66     }
67   if(distance>spacing[2])
68     {
69     distance=spacing[2];
70     }
71   distance=distance/2.0;
72 
73   cout << "spacing[3]=" << spacing[0] << ", " << spacing[1] << "," << spacing[2] << endl;
74 
75   // This does not take the screen size of a cell into account.
76   // distance has to be smaller: min(nyquis,screensize)
77 
78 //  distance=distance/4.0; // hack
79 //  distance=distance/4.0; // hack
80 
81   cout << "demo sample distance="<< distance<<endl;
82   mapper->SetSampleDistance(static_cast<float>(distance));
83 
84   vtkColorTransferFunction *colorFun=vtkColorTransferFunction::New();
85   vtkPiecewiseFunction *opacityFun=vtkPiecewiseFunction::New();
86 
87   // Create the property and attach the transfer functions
88   vtkVolumeProperty *property=vtkVolumeProperty::New();
89   property->SetIndependentComponents(true);
90   property->SetColor(colorFun);
91   property->SetScalarOpacity(opacityFun);
92   property->SetInterpolationTypeToLinear();
93 
94   // connect up the volume to the property and the mapper
95   volume->SetProperty(property);
96   volume->SetMapper(mapper);
97 
98   double opacityLevel=120;
99   double opacityWindow=240;
100 
101   colorFun->AddRGBSegment(opacityLevel - 0.5*opacityWindow, 0.0, 0.0, 0.0,
102                           opacityLevel + 0.5*opacityWindow, 1.0, 1.0, 1.0);
103   opacityFun->AddSegment(opacityLevel - 0.5*opacityWindow, 0.0, // 0.0, 0.01
104                          opacityLevel + 0.5*opacityWindow, 1.0); // 1.0, 0.01
105   mapper->SetBlendModeToComposite();
106   property->ShadeOn();
107 
108 
109   // Make the mask
110   vtkImageGridSource *grid = vtkImageGridSource::New();
111   grid->SetDataScalarTypeToUnsignedChar();
112   grid->SetDataExtent(0, dim[0]-1,
113                       0, dim[1]-1,
114                       0, dim[2]-1);
115   grid->SetLineValue(1); // mask value
116   grid->SetFillValue(0);
117   grid->SetGridSpacing(5,5,5);
118   grid->Update();
119   mapper->SetMaskInput(grid->GetOutput());
120 
121   vtkImageGridSource *grid2 = vtkImageGridSource::New();
122   grid2->SetDataScalarTypeToUnsignedChar();
123   grid2->SetDataExtent(0, dim[0]-1,
124                        0, dim[1]-1,
125                        0, dim[2]-1);
126   grid2->SetLineValue(2); // mask value
127   grid2->SetFillValue(0);
128   grid2->SetGridSpacing(6,6,6);
129   grid2->Update();
130 //    mapper->SetMaskInput(grid2->GetOutput());
131 //    grid2->Delete();
132 
133 
134   vtkImageCheckerboard *checkerboard=vtkImageCheckerboard::New();
135   checkerboard->SetInputConnection(0,grid->GetOutputPort());
136   grid->Delete();
137 
138   checkerboard->SetInputConnection(1,grid2->GetOutputPort());
139   grid2->Delete();
140   checkerboard->Update();
141   mapper->SetMaskInput(checkerboard->GetOutput());
142   checkerboard->Delete();
143 
144 
145   // Add color transfer functions for the masks
146   vtkColorTransferFunction *mask1colorFun=vtkColorTransferFunction::New();
147   property->SetColor(1,mask1colorFun);
148   mask1colorFun->Delete();
149 
150   // yellow.
151   mask1colorFun->AddRGBSegment(opacityLevel-0.5*opacityWindow,0.0,1.0,0.0,
152                                opacityLevel+0.5*opacityWindow,1.0,1.0,0.0);
153 
154 
155   vtkColorTransferFunction *mask2colorFun=vtkColorTransferFunction::New();
156   property->SetColor(2,mask2colorFun);
157   mask2colorFun->Delete();
158 
159   // red
160   mask2colorFun->AddRGBSegment(opacityLevel-0.5*opacityWindow,0.5,0.0,0.0,
161                                opacityLevel+0.5*opacityWindow,1.0,0.0,0.0);
162 
163 
164   vtkRenderWindowInteractor *iren=vtkRenderWindowInteractor::New();
165 
166   vtkOpenGLRenderWindow *renWin
167     = vtkOpenGLRenderWindow::SafeDownCast(vtkRenderWindow::New());
168 
169   renWin->SetSize(300,300);
170   iren->SetRenderWindow(renWin);
171 
172   vtkRenderer *ren1=vtkRenderer::New();
173   renWin->AddRenderer(ren1);
174 
175   renWin->Render();
176 
177   bool mapper_support = mapper->IsRenderSupported(renWin,property)!=0;
178 
179   // Workaround for Mesa bug
180   vtkOpenGLExtensionManager *extensions = renWin->GetExtensionManager();
181   bool driver_support
182     = (!extensions->DriverGLRendererIsOSMesa()
183     || extensions->DriverGLRendererHasToken("llvmpipe"))
184     || extensions->GetIgnoreDriverBugs("OS Mesa GPURayCastCompositeShadeMask bug");
185 
186   int retVal;
187   if(mapper_support && driver_support)
188     {
189     ren1->AddViewProp(volume);
190     iren->Initialize();
191     ren1->SetBackground(0.1,0.4,0.2);
192     ren1->ResetCamera();
193     ren1->GetActiveCamera()->Zoom(1.5);
194     renWin->Render();
195 
196     retVal = vtkTesting::Test(argc, argv, renWin, 75);
197     if (retVal == vtkRegressionTester::DO_INTERACTOR)
198       {
199       iren->Start();
200       }
201     }
202   else
203     {
204     retVal=vtkTesting::PASSED;
205     cout << "Required extensions not supported." << endl;
206     }
207 
208   volume->Delete();
209   mapper->Delete();
210   colorFun->Delete();
211   opacityFun->Delete();
212   property->Delete();
213   ren1->Delete();
214   renWin->Delete();
215   iren->Delete();
216   reader->Delete();
217 
218   if ((retVal == vtkTesting::PASSED) || (retVal == vtkTesting::DO_INTERACTOR))
219     {
220     return 0;
221     }
222   else
223     {
224     return 1;
225     }
226 }
227