diff --git a/Documentation/release/dev/fix-OSPRayVolumeParallel.md b/Documentation/release/dev/fix-OSPRayVolumeParallel.md new file mode 100644 index 0000000000000000000000000000000000000000..18813a0b3b2bd579bee7d32405a89278d7249451 --- /dev/null +++ b/Documentation/release/dev/fix-OSPRayVolumeParallel.md @@ -0,0 +1 @@ +fixes compositing artifacts when volume rendering in parallel with the OSPRay raycaster. The fix was by reintroducing adaptive sampling rates based on volume size. Path tracing still has artifacts with parallel rendering due to lack of required data/ray communication between nodes to support that renderer. diff --git a/Rendering/RayTracing/vtkOSPRayRendererNode.cxx b/Rendering/RayTracing/vtkOSPRayRendererNode.cxx index 252d23a7d1731ade24767298d4c33d52b9cec6cc..2c86f6edefdbe5879e414391bd77190e1644e348 100644 --- a/Rendering/RayTracing/vtkOSPRayRendererNode.cxx +++ b/Rendering/RayTracing/vtkOSPRayRendererNode.cxx @@ -187,6 +187,7 @@ vtkInformationKeyMacro(vtkOSPRayRendererNode, VOLUME_ANISOTROPY, Double); vtkInformationKeyMacro(vtkOSPRayRendererNode, VARIANCE_THRESHOLD, Double); vtkInformationKeyMacro(vtkOSPRayRendererNode, MAX_FRAMES, Integer); vtkInformationKeyMacro(vtkOSPRayRendererNode, AMBIENT_SAMPLES, Integer); +vtkInformationKeyMacro(vtkOSPRayRendererNode, VOLUME_SAMPLING_RATE, Double); vtkInformationKeyMacro(vtkOSPRayRendererNode, COMPOSITE_ON_GL, Integer); vtkInformationKeyMacro(vtkOSPRayRendererNode, RENDERER_TYPE, String); vtkInformationKeyMacro(vtkOSPRayRendererNode, NORTH_POLE, DoubleVector); @@ -800,6 +801,32 @@ int vtkOSPRayRendererNode::GetAmbientSamples(vtkRenderer* renderer) return 0; } +//------------------------------------------------------------------------------ +void vtkOSPRayRendererNode::SetVolumeSamplingRate(double value, vtkRenderer* renderer) +{ + if (!renderer) + { + return; + } + vtkInformation* info = renderer->GetInformation(); + info->Set(vtkOSPRayRendererNode::VOLUME_SAMPLING_RATE(), value); +} + +//------------------------------------------------------------------------------ +double vtkOSPRayRendererNode::GetVolumeSamplingRate(vtkRenderer* renderer) +{ + if (!renderer) + { + return 1.0; + } + vtkInformation* info = renderer->GetInformation(); + if (info && info->Has(vtkOSPRayRendererNode::VOLUME_SAMPLING_RATE())) + { + return (info->Get(vtkOSPRayRendererNode::VOLUME_SAMPLING_RATE())); + } + return 1.0; +} + //------------------------------------------------------------------------------ void vtkOSPRayRendererNode::SetCompositeOnGL(int value, vtkRenderer* renderer) { @@ -1211,6 +1238,7 @@ void vtkOSPRayRendererNode::Render(bool prepass) ospSetFloat(this->ORenderer, "rouletteDepth", this->GetRouletteDepth(ren)); ospSetFloat(this->ORenderer, "varianceThreshold", this->GetVarianceThreshold(ren)); // ospSetInt(oRenderer, "geometryLights", 0); //avoid a crash in ospray 2.1.0 + ospSetFloat(this->ORenderer, "volumeSamplingRate", this->GetVolumeSamplingRate(ren)); ospCommit(this->ORenderer); if (ren->GetUseShadows()) diff --git a/Rendering/RayTracing/vtkOSPRayRendererNode.h b/Rendering/RayTracing/vtkOSPRayRendererNode.h index d96688e4d01339578cb343362aac96f42bde7318..fa16d13940c833d7512d4870705b8d0e8093b9c5 100644 --- a/Rendering/RayTracing/vtkOSPRayRendererNode.h +++ b/Rendering/RayTracing/vtkOSPRayRendererNode.h @@ -242,6 +242,19 @@ public: static int GetAmbientSamples(vtkRenderer* renderer); ///@} + /** + * the rate of sampling for volumes, higher numbers increase + * the number of samples. Defaults to 1.0. + */ + static vtkInformationDoubleKey* VOLUME_SAMPLING_RATE(); + ///@{ + /** + * Convenience method VOLUME_SAMPLING_RATE on a vtkRenderer. + */ + static void SetVolumeSamplingRate(double, vtkRenderer* renderer); + static double GetVolumeSamplingRate(vtkRenderer* renderer); + ///@} + /** * used to make the renderer add ospray's content onto GL rendered * content on the window diff --git a/Rendering/RayTracing/vtkOSPRayVolumeMapperNode.cxx b/Rendering/RayTracing/vtkOSPRayVolumeMapperNode.cxx index df1259284f4cf31a228c4be12248ebc45511e838..97786d488ea7e67e815043fae9a73555af76f0cf 100644 --- a/Rendering/RayTracing/vtkOSPRayVolumeMapperNode.cxx +++ b/Rendering/RayTracing/vtkOSPRayVolumeMapperNode.cxx @@ -227,6 +227,29 @@ void vtkOSPRayVolumeMapperNode::Render(bool prepass) scale[1] = (bds[3] - bds[2]) / double(dim[1] - 1); scale[2] = (bds[5] - bds[4]) / double(dim[2] - 1); + float samplingRate = 1.f; + // automatically determine sampling rate + // smaller volumes are sampled at higher rates to reduce edge artifacts + int minBound = std::min(std::min(dim[0], dim[1]), dim[2]); + float minSamplingRate = 0.075f; // lower for min adaptive sampling step + if (minBound < 100) + { + float s = (100.0f - minBound) / 100.0f; + samplingRate = s * 6.f + 1.f; + } + else if (minBound < 1000) + { + float s = std::min((900.0f - minBound) / 1000.0f, 1.f); + samplingRate = (s * s * s * (0.5f - minSamplingRate) + minSamplingRate); + } + else + { + samplingRate = minSamplingRate; + } + + vtkOSPRayRendererNode::SetVolumeSamplingRate( + samplingRate, vtkRenderer::SafeDownCast(orn->GetRenderable())); + ospSetVec3f(this->OSPRayVolume, "gridOrigin", origin[0], origin[1], origin[2]); ospSetVec3f(this->OSPRayVolume, "gridSpacing", scale[0], scale[1], scale[2]); this->SamplingStep = std::min(scale[0], std::min(scale[1], scale[2]));