基本概念
vtkVolumeMapper是所有体绘制Mapper类虚基类,提供接口函数,并由其子类实现具体的功能。
光线投射法是最常用的体绘制方法。它是一种基于图像序列的直接体绘制方法,其基本原理是从投影图像平面(通常是平面)的每个像素沿着视线方向发射一条穿过体数据的射线,然后在射线上按照一定的步长进行等距采样,对每个采样点采用插值技术来计算其体素值,根据颜色传输函数和不透明传输函数来获取相应的颜色值和不透明度,最后利用光线吸收模型将颜色值进行累加直至光线穿过体数据,即可得当前平面像素的渲染颜色,生成最终的显示图像。在VTK中,vtkVolumeRayCastMapper类(在VTK8.x.x已被移除)可用于实现光线投射体数据算法,并生成渲染图元数据传递给vtkVolume对象进行渲染。vtkVolumeRayCastMapper类采用软件方法来实现光线投射算法,精度高但是计算量比较大。其内部两个最重要的函数:
SetVolumeRayCastMapper::SetInput(vtkImageData*) //该函数用于设置输入图像数据。
SetVolumeRayCastMapper::SetVolumeRay(vtkVolumeRayCastFunction*) //该函数用于设置光线投射函数。
vtkVolumeRayCastMapper中计算每条光线在通过体数据后的颜色是通过定义的vtkVolumeRayCastFunction对象实现的。vtkVolumeRayCastFunction是一个虚基类,它有三个子类。
1、vtkVolumeRayCastCompositeFunction该方式通过Alpha合成技术生成每个像素的颜色值。
2、vtkVolumeRayCastMIPFunction最大密度投影函数主要用于对体数据中高灰度值的结构进行可视化。
3、vtkVolumeRayCastIsosurfaceFunction等值面绘制函数能够渲染体数据中特定的等值面。
vtkFixedPointVolumeRayCastMapper是一个较好的vtkVolumeRayCastMapper的替代者。该类能够实现基于Alpha合成的体绘制和最大密度投影体绘制方法,能够支持任意类型的一元或独立多元数据。vtkFixedPointVolumeRayCastMapper的使用方法的使用方法与vtkVolumeRayCastMapper基本相同,如支持设置投射光线采样步长、设置图像采样距离、设置自动调节图像采样距离等。二者的区别:
-
vtkFixedPointVolumeRayCastFMapper只支持基于Alpha合成的体绘制方法和最大密度体绘制方法,可以通过基类vtkVolumeMapper的接口函数来设置。
void SetBlendModeToComposite();
void SetBlendModeToMaximumIntensity();
void SetBlendModeToMinimumIntensity();
void SetBlendModeToAddictive(); -
List item
对于Alpha合成体绘制方法,vtkFixedPointVolumeRayCastFMapper类仅支持先插值在分类操作;
vtkFixedPointVolumeRayCastFMapper类支持更多种数据类型。
示例演示
我们利用vtkFixedPointVolumeRayCastMapper类来显示基于Alpha合成的体绘制方法和最大密度体绘制方法的效果。
/**********************************************************************
Copyright (c) Mr.Bin. All rights reserved.
For more information visit: http://blog.csdn.net/webzhuce
**********************************************************************/
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkStructuredPoints.h>
#include <vtkStructuredPointsReader.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVolumeProperty.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
int main(int argc, char *argv[])
{
vtkNew<vtkStructuredPointsReader> reader;
reader->SetFileName("E:\\TestData\\mummy.128.vtk");
reader->Update();
vtkNew<vtkFixedPointVolumeRayCastMapper> volumeMapper0;
volumeMapper0->SetInputData(reader->GetOutput());
volumeMapper0->SetBlendModeToComposite();
vtkNew<vtkFixedPointVolumeRayCastMapper> volumeMapper1;
volumeMapper1->SetInputData(reader->GetOutput());
volumeMapper1->SetBlendModeToMaximumIntensity();
vtkNew<vtkVolumeProperty> volumeProperty;
volumeProperty->SetInterpolationTypeToLinear();
volumeProperty->SetAmbient(0.4);
volumeProperty->SetDiffuse(0.6);
volumeProperty->SetSpecular(0.2);
vtkNew<vtkPiecewiseFunction> compositeOpacity;
compositeOpacity->AddPoint(70, 0.00);
compositeOpacity->AddPoint(90, 0.40);
compositeOpacity->AddPoint(180, 0.60);
volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数
vtkNew<vtkPiecewiseFunction> volumeGradientOpacity;
volumeGradientOpacity->AddPoint(10, 0.0);
volumeGradientOpacity->AddPoint(90, 0.5);
volumeGradientOpacity->AddPoint(100, 1.0);
//volumeProperty->SetGradientOpacity(volumeGradientOpacity);//设置梯度不透明度效果对比
vtkNew<vtkColorTransferFunction> color;
color->AddRGBPoint(0.000, 0.00, 0.00, 0.00);
color->AddRGBPoint(64.00, 1.00, 0.52, 0.30);
color->AddRGBPoint(190.0, 1.00, 1.00, 1.00);
color->AddRGBPoint(220.0, 0.20, 0.20, 0.20);
volumeProperty->SetColor(color);
vtkNew<vtkVolume> volume0;
volume0->SetMapper(volumeMapper0);
volume0->SetProperty(volumeProperty);
vtkNew<vtkVolume> volume1;
volume1->SetMapper(volumeMapper1);
volume1->SetProperty(volumeProperty);
double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };
vtkNew<vtkRenderer> renderer0;
renderer0->SetBackground(1.0, 1.0, 1.0);
renderer0->SetViewport(leftViewport);
renderer0->AddVolume(volume0);
vtkNew<vtkRenderer> renderer1;
renderer1->SetBackground(1.0, 1.0, 1.0);
renderer1->SetViewport(rightViewport);
renderer1->AddVolume(volume1);
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(renderer0);
renWin->AddRenderer(renderer1);
renWin->SetSize(640, 480);
renWin->SetWindowName("VolumeMapper");
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
renWin->Render();
iren->Start();
return EXIT_SUCCESS;
}