// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkActor.h" #include "vtkCamera.h" #include "vtkColorTransferFunction.h" #include "vtkImageData.h" #include "vtkNew.h" #include "vtkOpenGLGPUVolumeRayCastMapper.h" #include "vtkPiecewiseFunction.h" #include "vtkPolyDataMapper.h" #include "vtkRegressionTestImage.h" #include "vtkRenderStepsPass.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkSSAOPass.h" #include "vtkSphereSource.h" #include "vtkTestUtilities.h" #include "vtkVolume.h" #include "vtkVolume16Reader.h" #include "vtkVolumeProperty.h" //------------------------------------------------------------------------------ vtkSmartPointer loadImage(int argc, char* argv[]) { char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/headsq/quarter"); vtkNew volumeReader; volumeReader->SetDataDimensions(64, 64); volumeReader->SetDataByteOrderToLittleEndian(); volumeReader->SetImageRange(1, 93); volumeReader->SetDataSpacing(3.2, 3.2, 1.5); volumeReader->SetFilePrefix(fname); volumeReader->Update(); delete[] fname; return volumeReader->GetOutput(); } //------------------------------------------------------------------------------ int TestGPURayCastSSAO(int argc, char* argv[]) { vtkSmartPointer volumeData = loadImage(argc, argv); vtkNew renderer; renderer->SetBackground(0.3, 0.4, 0.6); vtkNew renderWindow; renderWindow->SetSize(600, 600); renderWindow->AddRenderer(renderer); vtkNew iren; iren->SetRenderWindow(renderWindow); const double* bounds = volumeData->GetBounds(); vtkNew volumeMapper; volumeMapper->SetInputData(volumeData); volumeMapper->AutoAdjustSampleDistancesOff(); volumeMapper->LockSampleDistanceToInputSpacingOn(); vtkNew volume; volume->SetMapper(volumeMapper); renderer->AddActor(volume); // Shading must be turned on to enable SSAO on volumes volume->GetProperty()->ShadeOn(); // Linear interpolation produces smoother results volume->GetProperty()->SetInterpolationTypeToLinear(); const double* range = volumeData->GetScalarRange(); vtkNew ctf; ctf->AddRGBPoint(range[0], 0, 0, 0); ctf->AddRGBPoint(0.5 * (range[0] + range[1]), 1, 1, 1); ctf->AddRGBPoint(range[1], 1, 1, 1); volume->GetProperty()->SetColor(ctf); vtkNew pwf; pwf->AddPoint(range[0], 0); pwf->AddPoint(0.3 * (range[0] + range[1]), 0); pwf->AddPoint(0.4 * (range[0] + range[1]), 1); volume->GetProperty()->SetScalarOpacity(pwf); vtkNew source; source->SetRadius(0.25 * (bounds[1] - bounds[0])); source->SetCenter(bounds[0], 0.25 * (bounds[2] + bounds[3]), 0.25 * (bounds[4] + bounds[5])); vtkNew mapper; mapper->SetInputConnection(source->GetOutputPort()); vtkNew actor; actor->SetMapper(mapper); renderer->AddActor(actor); renderWindow->SetMultiSamples(0); // Render passes setup vtkNew basicPasses; vtkNew ssao; ssao->SetRadius(40); ssao->SetKernelSize(128); ssao->SetBias(0.01); ssao->BlurOn(); // The depth format must be Fixed32 for the volume mapper to successfully copy the depth texture ssao->SetDepthFormat(vtkTextureObject::Fixed32); ssao->SetVolumeOpacityThreshold(0.95); ssao->SetDelegatePass(basicPasses); renderer->SetPass(ssao); // Camera setup renderer->GetActiveCamera()->SetViewUp(0, 0, -1); renderer->GetActiveCamera()->SetPosition(0, 10, 0); renderer->GetActiveCamera()->OrthogonalizeViewUp(); renderer->GetActiveCamera()->Yaw(-40); renderer->ResetCamera(); renderer->GetActiveCamera()->Zoom(1.5); renderWindow->Render(); int retVal = vtkRegressionTestImage(renderWindow); if (retVal == vtkRegressionTester::DO_INTERACTOR) { iren->Start(); } return !retVal; }