Commit e94653c8 authored by lassoan's avatar lassoan
Browse files

ENH: Added new volume rendering quality option: Normal

SetLockSampleDistanceToInputSpacing usually provides good quality rendering at acceptable speed, but on slow computers or in virtual reality views (where very high frame rate is needed), it is still necessary to allow choose between volume rendering speed and quality.

Added a new option to clearly distinguish between quality settings:
- adaptive: sampling computed from desired fps
- normal: sampling computed from input volume
- maximum quality: sampling computed from input volume, with 10x oversampling

git-svn-id: http://svn.slicer.org/Slicer4/trunk@27153 3bd1e089-480b-0410-8dfb-8563597acbee
parent 66b152bc
......@@ -34,8 +34,7 @@ vtkMRMLNodeNewMacro(vtkMRMLGPURayCastVolumeRenderingDisplayNode);
vtkMRMLGPURayCastVolumeRenderingDisplayNode::vtkMRMLGPURayCastVolumeRenderingDisplayNode()
{
this->RaycastTechnique = vtkMRMLGPURayCastVolumeRenderingDisplayNode::Composite;
this->UseJittering = 0;
this->LockSampleDistanceToInputSpacing = 1;
this->SurfaceSmoothing = false;
}
//----------------------------------------------------------------------------
......@@ -50,8 +49,7 @@ void vtkMRMLGPURayCastVolumeRenderingDisplayNode::ReadXMLAttributes(const char**
vtkMRMLReadXMLBeginMacro(atts);
vtkMRMLReadXMLIntMacro(raycastTechnique, RaycastTechnique);
vtkMRMLReadXMLIntMacro(useJittering, UseJittering);
vtkMRMLReadXMLIntMacro(lockSampleDistanceToInputSpacing, LockSampleDistanceToInputSpacing);
vtkMRMLReadXMLIntMacro(surfaceSmoothing, SurfaceSmoothing);
vtkMRMLReadXMLEndMacro();
}
......@@ -62,8 +60,7 @@ void vtkMRMLGPURayCastVolumeRenderingDisplayNode::WriteXML(ostream& of, int nInd
vtkMRMLWriteXMLBeginMacro(of);
vtkMRMLWriteXMLIntMacro(raycastTechnique, RaycastTechnique);
vtkMRMLWriteXMLIntMacro(useJittering, UseJittering);
vtkMRMLWriteXMLIntMacro(lockSampleDistanceToInputSpacing, LockSampleDistanceToInputSpacing);
vtkMRMLWriteXMLIntMacro(surfaceSmoothing, SurfaceSmoothing);
vtkMRMLWriteXMLEndMacro();
}
......@@ -75,8 +72,7 @@ void vtkMRMLGPURayCastVolumeRenderingDisplayNode::Copy(vtkMRMLNode *anode)
vtkMRMLCopyBeginMacro(anode);
vtkMRMLCopyIntMacro(RaycastTechnique);
vtkMRMLCopyIntMacro(UseJittering);
vtkMRMLCopyIntMacro(LockSampleDistanceToInputSpacing);
vtkMRMLCopyIntMacro(SurfaceSmoothing);
vtkMRMLCopyEndMacro();
this->EndModify(wasModifying);
......@@ -89,7 +85,6 @@ void vtkMRMLGPURayCastVolumeRenderingDisplayNode::PrintSelf(ostream& os, vtkInde
vtkMRMLPrintBeginMacro(os, indent);
vtkMRMLPrintIntMacro(RaycastTechnique);
vtkMRMLPrintIntMacro(UseJittering);
vtkMRMLPrintIntMacro(LockSampleDistanceToInputSpacing);
vtkMRMLPrintIntMacro(SurfaceSmoothing);
vtkMRMLPrintEndMacro();
}
......@@ -59,14 +59,10 @@ public:
vtkSetMacro(RaycastTechnique, int);
// Description:
// Jittering
vtkGetMacro(UseJittering, int);
vtkSetMacro(UseJittering, int);
// Description:
// Lock sample distance to volume spacing
vtkGetMacro(LockSampleDistanceToInputSpacing, int);
vtkSetMacro(LockSampleDistanceToInputSpacing, int);
// Reduce wood grain artifact to make surfaces appear smoother.
// For example, by applying jittering on casted rays.
vtkGetMacro(SurfaceSmoothing, bool);
vtkSetMacro(SurfaceSmoothing, bool);
protected:
vtkMRMLGPURayCastVolumeRenderingDisplayNode();
......@@ -81,14 +77,8 @@ protected:
* */
int RaycastTechnique;
/// Use jittering to reduce the wood-grain effect if on. Off by default
int UseJittering;
/// Compute sample distance from volume spacing if on. Off by default
/// If turned on, then AutoAdjustSampleDistances and explicit SampleDistance
/// will be ignored, and only the internal auto-calculation will determine
/// the sampling distance.
int LockSampleDistanceToInputSpacing;
/// Make surface appearance smoother. Off by default
bool SurfaceSmoothing;
};
#endif
......
......@@ -76,7 +76,7 @@ vtkMRMLVolumeRenderingDisplayNode::vtkMRMLVolumeRenderingDisplayNode()
this->WindowLevel[0] = 0.0;
this->WindowLevel[1] = 0.0;
this->PerformanceControl = 0;
this->PerformanceControl = vtkMRMLVolumeRenderingDisplayNode::AdaptiveQuality;
}
//----------------------------------------------------------------------------
......
......@@ -73,8 +73,10 @@ public:
/// Quality used for PerformanceControl
enum Quality
{
Adaptative = 0,
MaximumQuality
AdaptiveQuality = 0, ///< quality determined from desired update rate
NormalQuality = 1, ///< good image quality at reasonable speed
MaximumQuality = 2, ///< high image quality, rendering time is not considered
Adaptative = 0 ///< deprecated (kept for backward compatibility only, same as AdaptiveQuality)
};
vtkSetMacro(PerformanceControl,int);
vtkGetMacro(PerformanceControl,int);
......
......@@ -389,12 +389,27 @@ void vtkMRMLVolumeRenderingDisplayableManager
vtkMRMLCPURayCastVolumeRenderingDisplayNode* vspNode)
{
this->UpdateMapper(mapper, vspNode);
const bool maximumQuality = vspNode->GetPerformanceControl() ==
vtkMRMLVolumeRenderingDisplayNode::MaximumQuality;
mapper->SetAutoAdjustSampleDistances(maximumQuality ? 0 : 1);
switch (vspNode->GetPerformanceControl())
{
case vtkMRMLVolumeRenderingDisplayNode::AdaptiveQuality:
mapper->SetAutoAdjustSampleDistances(true);
mapper->SetLockSampleDistanceToInputSpacing(false);
mapper->SetImageSampleDistance(1.0);
break;
case vtkMRMLVolumeRenderingDisplayNode::NormalQuality:
mapper->SetAutoAdjustSampleDistances(false);
mapper->SetLockSampleDistanceToInputSpacing(true);
mapper->SetImageSampleDistance(1.0);
break;
case vtkMRMLVolumeRenderingDisplayNode::MaximumQuality:
mapper->SetAutoAdjustSampleDistances(false);
mapper->SetLockSampleDistanceToInputSpacing(false);
mapper->SetImageSampleDistance(0.5);
break;
}
mapper->SetSampleDistance(this->GetSampleDistance(vspNode));
mapper->SetInteractiveSampleDistance(this->GetSampleDistance(vspNode));
mapper->SetImageSampleDistance(maximumQuality ? 0.5 : 1.);
switch(vspNode->GetRaycastTechnique())
{
......@@ -417,25 +432,27 @@ void vtkMRMLVolumeRenderingDisplayableManager
vtkMRMLGPURayCastVolumeRenderingDisplayNode* vspNode)
{
this->UpdateMapper(mapper, vspNode);
const bool maximumQuality = vspNode->GetPerformanceControl() ==
vtkMRMLVolumeRenderingDisplayNode::MaximumQuality;
if (maximumQuality)
switch (vspNode->GetPerformanceControl())
{
mapper->SetAutoAdjustSampleDistances(0);
mapper->SetLockSampleDistanceToInputSpacing(0);
mapper->SetUseJittering(0);
}
else
{
const bool lockSampleDistance = (bool)vspNode->GetLockSampleDistanceToInputSpacing();
// AutoAdjustSampleDistances disables LockSampleDistanceToInputSpacing, so if
// LockSampleDistanceToInputSpacing is on then disable AutoAdjustSampleDistances
mapper->SetAutoAdjustSampleDistances(maximumQuality || lockSampleDistance ? 0 : 1);
mapper->SetLockSampleDistanceToInputSpacing(lockSampleDistance);
mapper->SetUseJittering(vspNode->GetUseJittering());
case vtkMRMLVolumeRenderingDisplayNode::AdaptiveQuality:
mapper->SetAutoAdjustSampleDistances(true);
mapper->SetLockSampleDistanceToInputSpacing(false);
mapper->SetUseJittering(vspNode->GetSurfaceSmoothing());
break;
case vtkMRMLVolumeRenderingDisplayNode::NormalQuality:
mapper->SetAutoAdjustSampleDistances(false);
mapper->SetLockSampleDistanceToInputSpacing(true);
mapper->SetLockSampleDistanceToInputSpacing(true);
mapper->SetUseJittering(vspNode->GetSurfaceSmoothing());
break;
case vtkMRMLVolumeRenderingDisplayNode::MaximumQuality:
mapper->SetAutoAdjustSampleDistances(false);
mapper->SetLockSampleDistanceToInputSpacing(false);
mapper->SetUseJittering(vspNode->GetSurfaceSmoothing());
break;
}
mapper->SetSampleDistance(this->GetSampleDistance(vspNode));
mapper->SetImageSampleDistance(1.0);
mapper->SetMaxMemoryInBytes(this->GetMaxMemoryInBytes(mapper, vspNode));
switch(vspNode->GetRaycastTechnique())
......
......@@ -41,7 +41,7 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="JitteringLabel">
<widget class="QLabel" name="SurfaceSmoothingLabel">
<property name="toolTip">
<string>Option for removing wood-grain artifacts by applying random noise to raycasting</string>
</property>
......@@ -51,7 +51,7 @@
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="JitteringCheckBox">
<widget class="QCheckBox" name="SurfaceSmoothingCheckBox">
<property name="toolTip">
<string>Option for removing wood-grain artifacts by applying random noise to raycasting</string>
</property>
......
......@@ -356,6 +356,11 @@
<string>Adaptive</string>
</property>
</item>
<item>
<property name="text">
<string>Normal Quality</string>
</property>
</item>
<item>
<property name="text">
<string>Maximum Quality</string>
......
......@@ -63,8 +63,8 @@ void qSlicerGPURayCastVolumeRenderingPropertiesWidgetPrivate
this->populateRenderingTechniqueComboBox();
QObject::connect(this->RenderingTechniqueComboBox, SIGNAL(currentIndexChanged(int)),
widget, SLOT(setRenderingTechnique(int)));
QObject::connect(this->JitteringCheckBox, SIGNAL(toggled(bool)),
widget, SLOT(setJittering(bool)));
QObject::connect(this->SurfaceSmoothingCheckBox, SIGNAL(toggled(bool)),
widget, SLOT(setSurfaceSmoothing(bool)));
}
// --------------------------------------------------------------------------
......@@ -128,9 +128,9 @@ void qSlicerGPURayCastVolumeRenderingPropertiesWidget::updateWidgetFromMRML()
d->RenderingTechniqueComboBox->setCurrentIndex(index);
d->RenderingTechniqueComboBox->blockSignals(wasBlocked);
wasBlocked = d->JitteringCheckBox->blockSignals(true);
d->JitteringCheckBox->setChecked(displayNode->GetUseJittering());
d->JitteringCheckBox->blockSignals(wasBlocked);
wasBlocked = d->SurfaceSmoothingCheckBox->blockSignals(true);
d->SurfaceSmoothingCheckBox->setChecked(displayNode->GetSurfaceSmoothing());
d->SurfaceSmoothingCheckBox->blockSignals(wasBlocked);
}
//-----------------------------------------------------------------------------
......@@ -147,7 +147,7 @@ void qSlicerGPURayCastVolumeRenderingPropertiesWidget::setRenderingTechnique(int
}
//-----------------------------------------------------------------------------
void qSlicerGPURayCastVolumeRenderingPropertiesWidget::setJittering(bool on)
void qSlicerGPURayCastVolumeRenderingPropertiesWidget::setSurfaceSmoothing(bool on)
{
Q_D(qSlicerGPURayCastVolumeRenderingPropertiesWidget);
vtkMRMLGPURayCastVolumeRenderingDisplayNode* displayNode = this->mrmlGPURayCastDisplayNode();
......@@ -155,5 +155,5 @@ void qSlicerGPURayCastVolumeRenderingPropertiesWidget::setJittering(bool on)
{
return;
}
displayNode->SetUseJittering(on);
displayNode->SetSurfaceSmoothing(on);
}
......@@ -40,7 +40,7 @@ public:
public slots:
void setRenderingTechnique(int index);
void setJittering(bool on);
void setSurfaceSmoothing(bool on);
protected slots:
virtual void updateWidgetFromMRML();
......
......@@ -416,7 +416,7 @@ void qSlicerVolumeRenderingModuleWidget::updateFromMRMLDisplayNode()
d->FramerateSliderWidget->setValue(d->DisplayNode->GetExpectedFPS());
}
d->FramerateSliderWidget->setEnabled(
d->DisplayNode && d->DisplayNode->GetPerformanceControl() == vtkMRMLVolumeRenderingDisplayNode::Adaptative );
d->DisplayNode && d->DisplayNode->GetPerformanceControl() == vtkMRMLVolumeRenderingDisplayNode::AdaptiveQuality);
// Opacity/color
bool follow = d->DisplayNode ? d->DisplayNode->GetFollowVolumeDisplayNode() != 0 : false;
if (follow)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment