// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #ifndef vtkRenderTimingTests_h #define vtkRenderTimingTests_h /* To add a test you must define a subclass of vtkRTTest and implement the pure virtual functions. Then in the main section at the bottom of this file add your test to the tests to be run and rebuild. See some of the existing tests to get an idea of what to do. */ #include "vtkRenderTimings.h" #include "vtkActor.h" #include "vtkAutoInit.h" #include "vtkCamera.h" #include "vtkCellArray.h" #include "vtkCullerCollection.h" #include "vtkNew.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkRenderingOpenGLConfigure.h" /*========================================================================= Define a test for simple triangle mesh surfaces =========================================================================*/ #include "vtkParametricBoy.h" #include "vtkParametricFunctionSource.h" #include "vtkParametricTorus.h" VTK_ABI_NAMESPACE_BEGIN class surfaceTest : public vtkRTTest { public: surfaceTest(const char* name, bool withColors, bool withNormals) : vtkRTTest(name) { this->WithColors = withColors; this->WithNormals = withNormals; } const char* GetSummaryResultName() override { return "Mtris/sec"; } const char* GetSecondSummaryResultName() override { return "Mtris"; } vtkRTTestResult Run(vtkRTTestSequence* ats, int /*argc*/, char* /* argv */[]) override { int ures, vres; ats->GetSequenceNumbers(ures, vres); // ------------------------------------------------------------ // Create surface // ------------------------------------------------------------ // vtkNew PB; vtkNew PB; vtkNew PFS; PFS->SetParametricFunction(PB.Get()); if (this->WithColors) { PFS->SetScalarModeToPhase(); } else { PFS->SetScalarModeToNone(); } if (this->WithNormals == false) { PFS->GenerateNormalsOff(); } PFS->SetUResolution(ures * 50); PFS->SetVResolution(vres * 100); PFS->Update(); vtkNew mapper; mapper->SetInputConnection(PFS->GetOutputPort()); mapper->SetScalarRange(0.0, 360.0); vtkNew actor; actor->SetMapper(mapper.Get()); // create a rendering window and renderer vtkNew ren1; vtkNew renWindow; renWindow->AddRenderer(ren1.Get()); ren1->AddActor(actor.Get()); // set the size/color of our window renWindow->SetSize(this->GetRenderWidth(), this->GetRenderHeight()); ren1->SetBackground(0.2, 0.3, 0.5); // draw the resulting scene double startTime = vtkTimerLog::GetUniversalTime(); renWindow->Render(); double firstFrameTime = vtkTimerLog::GetUniversalTime() - startTime; ren1->GetActiveCamera()->Azimuth(90); ren1->ResetCameraClippingRange(); int frameCount = 80; for (int i = 0; i < frameCount; i++) { renWindow->Render(); ren1->GetActiveCamera()->Azimuth(1); ren1->GetActiveCamera()->Elevation(1); if ((vtkTimerLog::GetUniversalTime() - startTime - firstFrameTime) > this->TargetTime * 1.5) { frameCount = i + 1; break; } } double subsequentFrameTime = (vtkTimerLog::GetUniversalTime() - startTime - firstFrameTime) / frameCount; double numTris = PFS->GetOutput()->GetPolys()->GetNumberOfCells(); vtkRTTestResult result; result.Results["first frame time"] = firstFrameTime; result.Results["subsequent frame time"] = subsequentFrameTime; result.Results["Mtris"] = 1.0e-6 * numTris; result.Results["Mtris/sec"] = 1.0e-6 * numTris / subsequentFrameTime; result.Results["triangles"] = numTris; return result; } protected: bool WithNormals; bool WithColors; }; /*========================================================================= Define a test for glyphing =========================================================================*/ VTK_ABI_NAMESPACE_END #include "vtkElevationFilter.h" #include "vtkGlyph3DMapper.h" #include "vtkPlaneSource.h" #include "vtkSphereSource.h" VTK_ABI_NAMESPACE_BEGIN class glyphTest : public vtkRTTest { public: glyphTest(const char* name) : vtkRTTest(name) { } const char* GetSummaryResultName() override { return "Mtris/sec"; } const char* GetSecondSummaryResultName() override { return "triangles"; } vtkRTTestResult Run(vtkRTTestSequence* ats, int /*argc*/, char* /* argv */[]) override { int res1, res2, res3, res4; ats->GetSequenceNumbers(res1, res2, res3, res4); // create vtkNew plane; plane->SetResolution(res1 * 10, res2 * 10); plane->SetOrigin(-res1 * 5.0, -res2 * 5.0, 0.0); plane->SetPoint1(res1 * 5.0, -res2 * 5.0, 0.0); plane->SetPoint2(-res1 * 5.0, res2 * 5.0, 0.0); vtkNew colors; colors->SetInputConnection(plane->GetOutputPort()); colors->SetLowPoint(plane->GetOrigin()); colors->SetHighPoint(res1 * 5.0, res2 * 5.0, 0.0); // create simple poly data so we can apply glyph vtkNew sphere; sphere->SetPhiResolution(5 * res3 + 2); sphere->SetThetaResolution(10 * res4); sphere->SetRadius(0.7); vtkNew mapper; mapper->SetInputConnection(colors->GetOutputPort()); mapper->SetSourceConnection(sphere->GetOutputPort()); mapper->SetScalarRange(0.0, 2.0); // vtkNew mapper; // mapper->SetInputConnection(colors->GetOutputPort()); // mapper->SetScalarRange(0.0,2.0); vtkNew actor; actor->SetMapper(mapper.Get()); // create a rendering window and renderer vtkNew ren1; vtkNew renWindow; renWindow->AddRenderer(ren1.Get()); ren1->AddActor(actor.Get()); // set the size/color of our window renWindow->SetSize(this->GetRenderWidth(), this->GetRenderHeight()); ren1->SetBackground(0.2, 0.3, 0.5); // draw the resulting scene double startTime = vtkTimerLog::GetUniversalTime(); renWindow->Render(); double firstFrameTime = vtkTimerLog::GetUniversalTime() - startTime; int frameCount = 80; for (int i = 0; i < frameCount; i++) { renWindow->Render(); ren1->GetActiveCamera()->Azimuth(0.5); ren1->GetActiveCamera()->Elevation(0.5); ren1->GetActiveCamera()->Zoom(1.01); ren1->ResetCameraClippingRange(); if ((vtkTimerLog::GetUniversalTime() - startTime - firstFrameTime) > this->TargetTime * 1.5) { frameCount = i + 1; break; } } double subsequentFrameTime = (vtkTimerLog::GetUniversalTime() - startTime - firstFrameTime) / frameCount; double numTris = 100.0 * res1 * res2 * sphere->GetOutput()->GetPolys()->GetNumberOfCells(); vtkRTTestResult result; result.Results["first frame time"] = firstFrameTime; result.Results["subsequent frame time"] = subsequentFrameTime; result.Results["Mtris"] = 1.0e-6 * numTris; result.Results["Mtris/sec"] = 1.0e-6 * numTris / subsequentFrameTime; result.Results["triangles"] = numTris; return result; } protected: }; /*========================================================================= Define a test for molecules =========================================================================*/ VTK_ABI_NAMESPACE_END #include "vtkBoxMuellerRandomSequence.h" #include "vtkMath.h" #include "vtkMolecule.h" #include "vtkMoleculeMapper.h" #include "vtkPointLocator.h" VTK_ABI_NAMESPACE_BEGIN class moleculeTest : public vtkRTTest { public: moleculeTest(const char* name, bool atomsOnly = false) : vtkRTTest(name) { this->AtomsOnly = atomsOnly; } const char* GetSummaryResultName() override { return this->AtomsOnly ? "Atoms/sec" : "Atoms+Bonds/sec"; } const char* GetSecondSummaryResultName() override { return this->AtomsOnly ? "Atoms" : "Atoms+Bonds"; } vtkRTTestResult Run(vtkRTTestSequence* ats, int /*argc*/, char* /* argv */[]) override { int res1; ats->GetSequenceNumbers(res1); vtkNew rs; vtkNew mol; vtkNew pl; // build a molecule float scale = 3.0 * pow(static_cast(res1), 0.33); double pos[3]; vtkNew pointSet; vtkNew pts; pointSet->SetPoints(pts.GetPointer()); double bounds[6]; bounds[0] = 0.0; bounds[2] = 0.0; bounds[4] = 0.0; bounds[1] = scale; bounds[3] = scale; bounds[5] = scale; pl->SetDataSet(pointSet.GetPointer()); pl->InitPointInsertion(pointSet->GetPoints(), bounds, 10 * res1); for (int i = 0; i < res1 * 100; i++) { pos[0] = scale * rs->GetValue(); rs->Next(); pos[1] = scale * rs->GetValue(); rs->Next(); pos[2] = scale * rs->GetValue(); rs->Next(); pl->InsertPoint(i, pos); int molType = i % 9 > 5 ? i % 9 : 1; // a lot of H, some N O CA mol->AppendAtom(molType, pos[0], pos[1], pos[2]); } // now add some bonds if (!this->AtomsOnly) { vtkNew ids; int bondCount = 0; while (bondCount < res1 * 60) { pos[0] = scale * rs->GetValue(); rs->Next(); pos[1] = scale * rs->GetValue(); rs->Next(); pos[2] = scale * rs->GetValue(); rs->Next(); pl->FindClosestNPoints(2, pos, ids.GetPointer()); // are the atoms close enough? if (vtkMath::Distance2BetweenPoints(mol->GetAtomPosition(ids->GetId(0)).GetData(), mol->GetAtomPosition(ids->GetId(1)).GetData()) < 4.0) { int bondType = bondCount % 10 == 9 ? 3 : (bondCount % 10) / 7 + 1; mol->AppendBond(ids->GetId(0), ids->GetId(1), bondType); bondCount++; } } } vtkNew mapper; mapper->SetInputData(mol.GetPointer()); mapper->UseBallAndStickSettings(); vtkNew actor; actor->SetMapper(mapper.GetPointer()); // create a rendering window and renderer vtkNew ren1; vtkNew renWindow; renWindow->AddRenderer(ren1.GetPointer()); ren1->AddActor(actor.GetPointer()); // set the size/color of our window renWindow->SetSize(this->GetRenderWidth(), this->GetRenderHeight()); ren1->SetBackground(0.2, 0.3, 0.5); // draw the resulting scene double startTime = vtkTimerLog::GetUniversalTime(); renWindow->Render(); double firstFrameTime = vtkTimerLog::GetUniversalTime() - startTime; ren1->GetActiveCamera()->Zoom(1.5); int frameCount = 80; for (int i = 0; i < frameCount; i++) { renWindow->Render(); ren1->GetActiveCamera()->Azimuth(0.5); ren1->GetActiveCamera()->Elevation(0.5); ren1->GetActiveCamera()->Zoom(1.01); // ren1->ResetCameraClippingRange(); if ((vtkTimerLog::GetUniversalTime() - startTime - firstFrameTime) > this->TargetTime * 1.5) { frameCount = i + 1; break; } } double subsequentFrameTime = (vtkTimerLog::GetUniversalTime() - startTime - firstFrameTime) / frameCount; double numAtoms = mol->GetNumberOfAtoms(); vtkRTTestResult result; result.Results["first frame time"] = firstFrameTime; result.Results["subsequent frame time"] = subsequentFrameTime; result.Results["Atoms"] = numAtoms; result.Results["Bonds"] = mol->GetNumberOfBonds(); result.Results["Atoms+Bonds"] = (numAtoms + mol->GetNumberOfBonds()); result.Results["Atoms+Bonds/sec"] = (numAtoms + mol->GetNumberOfBonds()) / subsequentFrameTime; result.Results["Atoms/sec"] = numAtoms / subsequentFrameTime; return result; } protected: bool AtomsOnly; }; /*========================================================================= Define a test for volume rendering =========================================================================*/ VTK_ABI_NAMESPACE_END #include "vtkColorTransferFunction.h" #include "vtkGPUVolumeRayCastMapper.h" #include "vtkPiecewiseFunction.h" #include "vtkRTAnalyticSource.h" #include "vtkVolume.h" #include "vtkVolumeMapper.h" #include "vtkVolumeProperty.h" VTK_ABI_NAMESPACE_BEGIN class volumeTest : public vtkRTTest { public: volumeTest(const char* name, bool withShading) : vtkRTTest(name) { this->WithShading = withShading; } const char* GetSummaryResultName() override { return "Mvoxels/sec"; } const char* GetSecondSummaryResultName() override { return "Mvoxels"; } vtkRTTestResult Run(vtkRTTestSequence* ats, int /*argc*/, char* /* argv */[]) override { int res1, res2, res3; ats->GetSequenceNumbers(res1, res2, res3); vtkNew wavelet; wavelet->SetWholeExtent( -50 * res1 - 1, 50 * res1, -50 * res2 - 1, 50 * res2, -50 * res3 - 1, 50 * res3); wavelet->Update(); vtkNew volumeMapper; volumeMapper->SetInputConnection(wavelet->GetOutputPort()); volumeMapper->AutoAdjustSampleDistancesOff(); volumeMapper->SetSampleDistance(0.9); vtkNew volumeProperty; vtkNew ctf; ctf->AddRGBPoint(33.34, 0.23, 0.3, 0.75); ctf->AddRGBPoint(72.27, 0.79, 0.05, 0.22); ctf->AddRGBPoint(110.3, 0.8, 0.75, 0.82); ctf->AddRGBPoint(134.19, 0.78, 0.84, 0.04); ctf->AddRGBPoint(159.84, 0.07, 0.87, 0.43); ctf->AddRGBPoint(181.96, 0.84, 0.31, 0.48); ctf->AddRGBPoint(213.803, 0.73, 0.62, 0.8); ctf->AddRGBPoint(255.38, 0.75, 0.19, 0.05); ctf->AddRGBPoint(286.33, 0.7, 0.02, 0.15); ctf->SetColorSpaceToHSV(); vtkNew pwf; pwf->AddPoint(33.35, 0.0); pwf->AddPoint(81.99, 0.01); pwf->AddPoint(128.88, 0.02); pwf->AddPoint(180.19, 0.03); pwf->AddPoint(209.38, 0.04); pwf->AddPoint(286.33, 0.05); volumeProperty->SetColor(ctf.GetPointer()); volumeProperty->SetScalarOpacity(pwf.GetPointer()); vtkNew volume; volume->SetMapper(volumeMapper.GetPointer()); volume->SetProperty(volumeProperty.GetPointer()); if (this->WithShading) { volumeProperty->ShadeOn(); } // create a rendering window and renderer vtkNew ren1; vtkNew renWindow; renWindow->AddRenderer(ren1.GetPointer()); ren1->AddActor(volume.GetPointer()); // set the size/color of our window renWindow->SetSize(this->GetRenderWidth(), this->GetRenderHeight()); ren1->SetBackground(0.2, 0.3, 0.4); // draw the resulting scene double startTime = vtkTimerLog::GetUniversalTime(); renWindow->Render(); double firstFrameTime = vtkTimerLog::GetUniversalTime() - startTime; ren1->GetActiveCamera()->Zoom(1.2); ren1->ResetCameraClippingRange(); int frameCount = 80; for (int i = 0; i < frameCount; i++) { renWindow->Render(); ren1->GetActiveCamera()->Azimuth(0.5); ren1->GetActiveCamera()->Elevation(0.5); ren1->ResetCameraClippingRange(); if ((vtkTimerLog::GetUniversalTime() - startTime - firstFrameTime) > this->TargetTime * 1.5) { frameCount = i + 1; break; } } double subsequentFrameTime = (vtkTimerLog::GetUniversalTime() - startTime - firstFrameTime) / frameCount; vtkRTTestResult result; result.Results["first frame time"] = firstFrameTime; result.Results["subsequent frame time"] = subsequentFrameTime; result.Results["Mvoxels/sec"] = static_cast(res1 * res2 * res3) / subsequentFrameTime; result.Results["Mvoxels"] = res1 * res2 * res3; return result; } protected: bool WithShading; }; /*========================================================================= Define a test for depth peeling transluscent geometry. =========================================================================*/ VTK_ABI_NAMESPACE_END #include "vtkProperty.h" #include "vtkTransform.h" VTK_ABI_NAMESPACE_BEGIN class depthPeelingTest : public vtkRTTest { public: depthPeelingTest(const char* name, bool withNormals) : vtkRTTest(name) , WithNormals(withNormals) { } const char* GetSummaryResultName() override { return "subsequent frame time"; } const char* GetSecondSummaryResultName() override { return "first frame time"; } vtkRTTestResult Run(vtkRTTestSequence* ats, int /*argc*/, char* /* argv */[]) override { int ures, vres; ats->GetSequenceNumbers(ures, vres); // ------------------------------------------------------------ // Create surface // ------------------------------------------------------------ vtkNew PB; vtkNew PFS; PFS->SetParametricFunction(PB.Get()); if (this->WithNormals == false) { PFS->GenerateNormalsOff(); } PFS->SetUResolution(ures * 50); PFS->SetVResolution(vres * 100); PFS->Update(); vtkNew mapper; mapper->SetInputConnection(PFS->GetOutputPort()); mapper->SetScalarRange(0.0, 360.0); // create a rendering window and renderer vtkNew ren1; vtkNew renWindow; renWindow->SetMultiSamples(0); renWindow->SetAlphaBitPlanes(1); renWindow->AddRenderer(ren1.Get()); // Setup depth peeling to render an exact scene: ren1->UseDepthPeelingOn(); ren1->SetMaximumNumberOfPeels(100); ren1->SetOcclusionRatio(0.); // Create a set of 10 colored translucent actors at slight offsets: const int NUM_ACTORS = 10; const unsigned char colors[NUM_ACTORS][4] = { { 255, 0, 0, 32 }, { 0, 255, 0, 32 }, { 0, 0, 255, 32 }, { 128, 128, 0, 32 }, { 0, 128, 128, 32 }, { 128, 0, 128, 32 }, { 128, 64, 64, 32 }, { 64, 128, 64, 32 }, { 64, 64, 128, 32 }, { 64, 64, 64, 32 }, }; for (int i = 0; i < NUM_ACTORS; ++i) { vtkNew actor; actor->SetMapper(mapper.Get()); actor->GetProperty()->SetColor(colors[i][0] / 255., colors[i][1] / 255., colors[i][2] / 255.); actor->GetProperty()->SetOpacity(colors[i][3] / 255.); vtkNew xform; xform->Identity(); xform->RotateX(i * (180. / static_cast(NUM_ACTORS))); actor->SetUserTransform(xform.Get()); ren1->AddActor(actor.Get()); } // set the size/color of our window renWindow->SetSize(this->GetRenderWidth(), this->GetRenderHeight()); ren1->SetBackground(0.2, 0.3, 0.5); // draw the resulting scene double startTime = vtkTimerLog::GetUniversalTime(); renWindow->Render(); double firstFrameTime = vtkTimerLog::GetUniversalTime() - startTime; ren1->GetActiveCamera()->Azimuth(90); ren1->ResetCameraClippingRange(); int frameCount = 80; for (int i = 0; i < frameCount; i++) { renWindow->Render(); ren1->GetActiveCamera()->Azimuth(1); ren1->GetActiveCamera()->Elevation(1); if ((vtkTimerLog::GetUniversalTime() - startTime - firstFrameTime) > this->TargetTime * 1.5) { frameCount = i + 1; break; } } double subsequentFrameTime = (vtkTimerLog::GetUniversalTime() - startTime - firstFrameTime) / frameCount; double numTris = PFS->GetOutput()->GetPolys()->GetNumberOfCells(); numTris *= NUM_ACTORS; vtkRTTestResult result; result.Results["first frame time"] = firstFrameTime; result.Results["subsequent frame time"] = subsequentFrameTime; result.Results["FPS"] = 1. / subsequentFrameTime; result.Results["triangles"] = numTris; return result; } protected: bool WithNormals; }; /*========================================================================= Define a test for simple triangle mesh surfaces =========================================================================*/ VTK_ABI_NAMESPACE_END VTK_ABI_NAMESPACE_BEGIN class manyActorTest : public vtkRTTest { public: manyActorTest(const char* name) : vtkRTTest(name) { } const char* GetSummaryResultName() override { return "actors"; } const char* GetSecondSummaryResultName() override { return "frames/sec"; } vtkRTTestResult Run(vtkRTTestSequence* ats, int /*argc*/, char* /* argv */[]) override { int ures, vres; ats->GetSequenceNumbers(ures, vres); // ------------------------------------------------------------ // Create surface // ------------------------------------------------------------ // vtkNew PB; vtkNew PB; vtkNew PFS; PFS->SetParametricFunction(PB.Get()); // PFS->SetScalarModeToPhase(); PFS->SetScalarModeToNone(); // PFS->GenerateNormalsOff(); PFS->SetUResolution(10); PFS->SetVResolution(20); PFS->Update(); // create a rendering window and renderer vtkNew ren1; // ren1->RemoveCuller(ren1->GetCullers()->GetLastItem()); vtkNew renWindow; renWindow->AddRenderer(ren1.Get()); // create many actors for (int u = 0; u < ures * 10; ++u) { for (int v = 0; v < vres * 10; ++v) { vtkNew mapper; mapper->SetInputConnection(PFS->GetOutputPort()); mapper->SetScalarRange(0.0, 360.0); mapper->StaticOn(); vtkNew actor; actor->SetMapper(mapper.Get()); actor->ForceOpaqueOn(); ren1->AddActor(actor.Get()); } } // set the size/color of our window renWindow->SetSize(this->GetRenderWidth(), this->GetRenderHeight()); ren1->SetBackground(0.2, 0.3, 0.5); // draw the resulting scene double startTime = vtkTimerLog::GetUniversalTime(); renWindow->Render(); double firstFrameTime = vtkTimerLog::GetUniversalTime() - startTime; ren1->GetActiveCamera()->Azimuth(90); ren1->GetActiveCamera()->Zoom(0.3); ren1->ResetCameraClippingRange(); int frameCount = 80; for (int i = 0; i < frameCount; i++) { renWindow->Render(); ren1->GetActiveCamera()->Azimuth(1); ren1->GetActiveCamera()->Elevation(1); if ((vtkTimerLog::GetUniversalTime() - startTime - firstFrameTime) > this->TargetTime * 1.5) { frameCount = i + 1; break; } } double subsequentFrameTime = (vtkTimerLog::GetUniversalTime() - startTime - firstFrameTime) / frameCount; vtkRTTestResult result; result.Results["first frame time"] = firstFrameTime; result.Results["subsequent frame time"] = subsequentFrameTime; result.Results["frames/sec"] = 1.0 / subsequentFrameTime; result.Results["actors"] = 100 * ures * vres; return result; } protected: }; VTK_ABI_NAMESPACE_END #endif // VTK-HeaderTest-Exclude: vtkRenderTimingTests.h