VTK随笔十二:体绘制(体绘制管线、vtkVolumeMapper、vtkVolume、不规则网格数据体绘制技术 )

        体绘制,有时又称作三维重建(区别于投影图像的三维重建),是一种直接利用体数据来生成二维图像的绘制技术。与面绘制不同,体绘制技术不需要提取体数据内部的等值面,它是一个对三维体数据进行采样和合成的过程。体绘制能够通过设置不透明度值来显示体数据内部的不同成分和细节,例如显示人体 CT图像的不同器官和组织。

一、体绘制管线 

从可视化管线的组成上来讲,体绘制的渲染管线与几何渲染管线基本一致。

1、首先定义vtkVolumeRayCastMapper 对象。定义了一个光线投射体绘制 Mapper。

2、定义 vtkVolumeProperty 体绘制属性对象,并设置标量不透明度传输函数、梯度不透
明度函数和颜色传输函数以及阴影。

3、定义 vtkVolume 对象。vtkVolume 与几何渲染中的 vtkActor 作用一致。

4、定义vtkRenderer 对象,建立可视化管线。

示例代码:

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkStructuredPointsReader.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkVolumeProperty.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkStructuredPointsReader> reader = vtkSmartPointer<vtkStructuredPointsReader>::New();
    reader->SetFileName("D:/data/mummy.128.vtk");
    reader->Update();

    vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
    volumeMapper->SetInputConnection(reader->GetOutputPort());

    // //设置光线采样距离
    // volumeMapper->SetSampleDistance(volumeMapper->GetSampleDistance()*4);
    // //设置图像采样步长
    // volumeMapper->SetAutoAdjustSampleDistances(0);
    // volumeMapper->SetImageSampleDistance(4);

    vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
    volumeProperty->SetInterpolationTypeToLinear();
    volumeProperty->ShadeOn();  //打开或者关闭阴影测试
    volumeProperty->SetAmbient(0.4);
    volumeProperty->SetDiffuse(0.6);
    volumeProperty->SetSpecular(0.2);

    vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    compositeOpacity->AddPoint(70,   0.00);
    compositeOpacity->AddPoint(90,   0.40);
    compositeOpacity->AddPoint(180,  0.60);
    volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数

    //测试隐藏部分数据,对比不同的设置
    // compositeOpacity->AddPoint(120,  0.00);
    // compositeOpacity->AddPoint(180,  0.60);
    // volumeProperty->SetScalarOpacity(compositeOpacity);

    vtkSmartPointer<vtkPiecewiseFunction> volumeGradientOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    volumeGradientOpacity->AddPoint(10,  0.0);
    volumeGradientOpacity->AddPoint(90,  0.5);
    volumeGradientOpacity->AddPoint(100, 1.0);
    //volumeProperty->SetGradientOpacity(volumeGradientOpacity);//设置梯度不透明度效果对比

    vtkSmartPointer<vtkColorTransferFunction> color = vtkSmartPointer<vtkColorTransferFunction>::New();
    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);

    vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
    volume->SetMapper(volumeMapper);
    volume->SetProperty(volumeProperty);

    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->SetBackground(1.0, 1.0, 1.0);
    renderer->AddVolume( volume );

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(renderer);

    QVTKOpenGLNativeWidget w;
    w.resize(640, 480);
    w.setRenderWindow(renderWindow);
    w.setWindowTitle("VolumeRendering");
    w.show();

    return a.exec();
}

运行效果:

二、vtkVolumeMapper

        vtkVolumeMapper 是所有体绘制 Mapper 类的虚基类,提供接口函数,并由其子类实现具体的功能。

1、vtkFixedPointVolumeRayCastMapper

        该类能够实现基于 Alpha 合成的体绘制方法和最大密度投影体绘制方法,能够支持任意类型的一元或者独立多元数据。例如,当输入数据的二元独立数据时,第一元数据用于颜色映射而第二元用于不透明度映射;对于四元的unsigned char 类型数据,则前三元数据作为颜色值而第四元作为不透明度使用。该类使用了空间跳跃技术来加速体绘制渲染过程,而且在内部计算时统一使用了 float 数据类型。

2、vtkGPUVolumeRayCastMapper

        vtkGPUVolumeRayCastMapper 实现了基于GPU 加速的光线投射体绘制算法。该类可以利用下面的函数设置光线采样步长、图像采样距离、是否自动调节图像采样距离等。
void SetSampleDistance (float)
void SetlmageSampleDistance (float)
void SetAutoAdjustSampleDistances (int)

3、裁剪

        对于一些体积比较大、结构比较复杂的体数据进行体绘制的渲染效果难以展示其内部细节,需要用到裁剪技术来渲染部分数据。vtkVolumeMapper 类中提供了两种裁剪技术,分别是 Cropping 和 Clipping。 

        Cropping 技术只支持 vtkmageData 数据的裁剪。该方法在每个坐标轴上定义两个裁剪面,共6个裁剪平面将三维空间分割为 27 个可视区域。

示例代码:

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkStructuredPointsReader.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkVolumeProperty.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkStructuredPointsReader> reader = vtkSmartPointer<vtkStructuredPointsReader>::New();
    reader->SetFileName("D:/data/mummy.128.vtk");
    reader->Update();

    vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
    volumeMapper->SetInputConnection(reader->GetOutputPort());

    //cropping
    volumeMapper->SetCropping(1);
    volumeMapper->SetCroppingRegionPlanes(100,200, 100,200, 100,200);
    volumeMapper->SetCroppingRegionFlags(0x0002000);

    vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
    volumeProperty->SetInterpolationTypeToLinear();
    volumeProperty->ShadeOn();  //打开或者关闭阴影测试
    volumeProperty->SetAmbient(0.4);
    volumeProperty->SetDiffuse(0.6);
    volumeProperty->SetSpecular(0.2);

    vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    compositeOpacity->AddPoint(70,   0.00);
    compositeOpacity->AddPoint(90,   0.40);
    compositeOpacity->AddPoint(180,  0.60);
    //volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数

    vtkSmartPointer<vtkPiecewiseFunction> volumeGradientOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    volumeGradientOpacity->AddPoint(10,  0.0);
    volumeGradientOpacity->AddPoint(90,  0.5);
    volumeGradientOpacity->AddPoint(100, 1.0);
    volumeProperty->SetGradientOpacity(volumeGradientOpacity);//设置梯度不透明度效果对比

    vtkSmartPointer<vtkColorTransferFunction> color = vtkSmartPointer<vtkColorTransferFunction>::New();
    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);

    vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
    volume->SetMapper(volumeMapper);
    volume->SetProperty(volumeProperty);

    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->SetBackground(1.0, 1.0, 1.0);
    renderer->AddVolume( volume );

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(renderer);

    QVTKOpenGLNativeWidget w;
    w.resize(640, 480);
    w.setRenderWindow(renderWindow);
    w.setWindowTitle("VolumeRendering");
    w.show();

    return a.exec();
}

运行效果:

Clipping 技术支持 vtkImageData和 vtkUnstructuredGrid 数据类型。 

示例代码:

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkStructuredPointsReader.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkVolumeProperty.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>
#include <vtkPlane.h>

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkStructuredPointsReader> reader = vtkSmartPointer<vtkStructuredPointsReader>::New();
    reader->SetFileName("D:/data/mummy.128.vtk");
    reader->Update();

    vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
    volumeMapper->SetInputConnection(reader->GetOutputPort());

    //clipping
    vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
    plane->SetOrigin(100,100,0);
    plane->SetNormal(1,1,0);
    volumeMapper->AddClippingPlane(plane);

    vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
    volumeProperty->SetInterpolationTypeToLinear();
    volumeProperty->ShadeOn();  //打开或者关闭阴影测试
    volumeProperty->SetAmbient(0.4);
    volumeProperty->SetDiffuse(0.6);
    volumeProperty->SetSpecular(0.2);

    vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    compositeOpacity->AddPoint(70,   0.00);
    compositeOpacity->AddPoint(90,   0.40);
    compositeOpacity->AddPoint(180,  0.60);
    volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数

    vtkSmartPointer<vtkPiecewiseFunction> volumeGradientOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    volumeGradientOpacity->AddPoint(10,  0.0);
    volumeGradientOpacity->AddPoint(90,  0.5);
    volumeGradientOpacity->AddPoint(100, 1.0);
    volumeProperty->SetGradientOpacity(volumeGradientOpacity);//设置梯度不透明度效果对比

    vtkSmartPointer<vtkColorTransferFunction> color = vtkSmartPointer<vtkColorTransferFunction>::New();
    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);

    vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
    volume->SetMapper(volumeMapper);
    volume->SetProperty(volumeProperty);

    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->SetBackground(1.0, 1.0, 1.0);
    renderer->AddVolume( volume );

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(renderer);

    QVTKOpenGLNativeWidget w;
    w.resize(640, 480);
    w.setRenderWindow(renderWindow);
    w.setWindowTitle("Clipping");
    w.show();

    return a.exec();
}

运行效果:

三、vtkVolume 

        vtkVolume 类似于几何渲染中的 vtkActor,用于表示渲染场景中的对象。除了存储基本的变换信息(平移、旋转、放缩等),其内部还存储了两个重要对象。这两个对象分别是vtkAbstractVolumeMapper 对象和 vtkVolumeProperty 对象。

1、不透明度传输函数

         不透明度传输函数是一个分段线性标量映射函数,利用该函数可将光线投射过程中的采样点灰度值映射为不同的不透明度值,以决定最终的颜色值。

2、梯度不透明度函数

         将梯度模值映射为一个不透明度乘子,从而增强过渡区域的显示效果。该函数同样使用的是 vtkPiecewiseFunction类。例如,在不同材料的临界区域,如空气到软组织,或者软组织到骨头的临界区,梯度值会比较大,而材料的内部梯度值则会相对比较小。

3、颜色传输函数

        颜色传输函数与不透明度传输函数的使用类似,二者的不同之处在于颜色传输函数是将一个标量值映射为一个颜色值。这个颜色值既可以是RGB值,也可以是HSV值。VTK中颜色传输函数采用 vtkColorTransferFunction 类实现。

4、光照与阴影

        通过 vtkVolumeProperty可以设置体绘制的阴影效果(Shading)。阴影效果主要受环境光系数、散射光系数、反射光系数和高光强度四个参数影响。使用vkVolumeProperty::SetAmbient()设置环境光系数;使用vtkVolumeProperty::SetDiffuse()设置散射光系数;使用vtkVolumeProperty::SetSpecular()设置反射光系数。一般情况下,这三个系数之和为 1。但是有时在体绘制过程中为了提高亮度,三值之和会大于1。另外,还有一个参数是高光强度(Specular Power),用于控制体绘制的外观平滑程度。可使用vtkVolumeProperty::SetSpecularPower()设置该参数。

5、体绘制加速:vtkLODProp3D

        对于一个大数据来讲,体绘制是一个计算量非常庞大、非常耗时的操作。尤其是在用户交互过程,需要不断对数据进行渲染,这样就造成了交互不流畅,用户体验差。可以使用VTKLODProp3D来解决这个问题,提高绘制速度。vtkLODProp3D类的用法与vtkVolume类似,两者都继承自vtkProp3D。不同的是,vtkLODProp3D类能够支持多个Mapper、Property和Texture对象,并由他选择Mapper对象实现绘制。
        vtkLODProp3D在渲染过程中,会为每个Mapper估计一个渲染时间,并选择一个最优的实现渲染。 

示例代码:

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkStructuredPointsReader.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkVolumeProperty.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>
#include <vtkGPUVolumeRayCastMapper.h>
#include <vtkLODProp3D.h>
#include <vtkCamera.h>

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkStructuredPointsReader> reader = vtkSmartPointer<vtkStructuredPointsReader>::New();
    reader->SetFileName("D:/data/mummy.128.vtk");
    reader->Update();

    vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
    volumeMapper->SetInputConnection(reader->GetOutputPort());

    vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
    volumeProperty->SetInterpolationTypeToLinear();
    volumeProperty->ShadeOn();  //打开或者关闭阴影测试
    volumeProperty->SetAmbient(0.4);
    volumeProperty->SetDiffuse(0.6);
    volumeProperty->SetSpecular(0.2);

    vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    compositeOpacity->AddPoint(70,   0.00);
    compositeOpacity->AddPoint(90,   0.40);
    compositeOpacity->AddPoint(180,  0.60);
    volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数

    vtkSmartPointer<vtkColorTransferFunction> color = vtkSmartPointer<vtkColorTransferFunction>::New();
    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);

    vtkSmartPointer<vtkGPUVolumeRayCastMapper> hiresMapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
    hiresMapper->SetInputConnection(reader->GetOutputPort());
    hiresMapper->SetAutoAdjustSampleDistances(0);

    vtkSmartPointer<vtkGPUVolumeRayCastMapper> lowresMapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
    lowresMapper->SetInputConnection(reader->GetOutputPort());
    lowresMapper->SetAutoAdjustSampleDistances(0);
    lowresMapper->SetSampleDistance(4*hiresMapper->GetSampleDistance());
    lowresMapper->SetImageSampleDistance(4*hiresMapper->GetImageSampleDistance());

    vtkSmartPointer<vtkLODProp3D> prop = vtkSmartPointer<vtkLODProp3D>::New();
    prop->AddLOD(lowresMapper, volumeProperty, 0.0);
    prop->AddLOD(hiresMapper,  volumeProperty, 0.0);

    vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
    volume->SetMapper(volumeMapper);
    volume->SetProperty(volumeProperty);

    double volumeView[4]={0, 0, 0.5, 1 };
    double lodpropView[4]={0.5,0, 1,1 };

    vtkSmartPointer<vtkRenderer> volumeRender = vtkSmartPointer<vtkRenderer>::New();
    volumeRender->SetBackground(1,1, 0);
    volumeRender->AddVolume(volume);
    volumeRender->SetViewport(volumeView);

    vtkSmartPointer<vtkRenderer> propRender = vtkSmartPointer<vtkRenderer>::New();
    propRender->SetBackground(0,1, 0);
    propRender->AddVolume(prop);
    propRender->SetViewport(lodpropView);

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(volumeRender);
    renderWindow->AddRenderer(propRender);

    QVTKOpenGLNativeWidget w;
    w.resize(640, 480);
    w.setRenderWindow(renderWindow);
    w.setWindowTitle("vtkLODProp3D");
    w.show();

    volumeRender->GetActiveCamera()->SetPosition(0, -1, 0);
    volumeRender->GetActiveCamera()->SetFocalPoint(0, 0, 0);
    volumeRender->GetActiveCamera()->SetViewUp(0, 0, 1);
    volumeRender->GetActiveCamera()->Azimuth(30);
    volumeRender->GetActiveCamera()->Elevation(30);
    volumeRender->ResetCamera();
    propRender->SetActiveCamera(volumeRender->GetActiveCamera());

    return a.exec();
}

 运行效果:

四、不规则网格数据体绘制技术 

        在 VTK中,不规则网格的体绘制渲染的流程与规则网格的体绘制流程一致。不同的是,
需要选择应用于不规则网格数据的 Mapper 对象。所有支持不规则网格体绘制的 Mapper 类都继承自vtkUnstructuredGridVolumeMapper。 

1、vtkUnstructuredGridVolumeRayCastMapper

        vtkUnstructuredGridVolumeRayCastMapper 实现了基于软件实现的不规则网格光线投射算法。该 Mapper 仅支持四面体数据,因此对于非四面体数据,需要借助四面体化Filter 进行数据转换。vtkUnstructuredGridVolumeRayCastMapper::SetRayCastFunction()函数可以设置光线投射函数的类型。该类型必须为vkUnstructuredGridVolumeRayCastFunction。目前 VTK 中仅有一个子类:vtkUnstructuredBunykRayCastFunction。该方法需要较大的内存,因此不适合大数据的渲染处理。

2、vtkUnstructuredGridVolumeZSweepMapper

        vtkUnstructuredGridVolumeZSweepMapper 实现了一种可以在任何平台下运行的体绘制方法。该方法是 VTK中不规则网格体绘制方法中最慢的一种,但相对于光线投射方法,该方法对内存的需求较小,因此可以用来渲染大数据。与光线投射Mapper类似,该类支持vtkUnstructuredGridVolumeZSweepMapper:SetRayIntegrator()函数,默认情况下 VTK 会自动为用户选择 Ray Integrator 类型。 

3、vtkProjectedTetrahedraMapper

        vtkProjectedTetrahedraMapper 类实现了经典的投影四面体法。该方法利用 OpenGL 在给定视点下将四面体转换为三角面片,通过硬件加速渲染这些三角面片,提高了染效率。但是,并非所有硬件都会支持该类中用到的OpenGL技术,可能会导致染失败。通常该类常与ZSweep方法或者光线投射法相结合,组成LOD(LevelofDetail),使得在交互过程中使用投影四面体方法能够快速地渲染,而交互完成后利用光线投射或者ZSweep技术生成更为精确的图像。 

示例代码:

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkStructuredPointsReader.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkVolumeProperty.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>
#include <vtkDataSetTriangleFilter.h>
#include <vtkThreshold.h>
#include <vtkUnstructuredGridVolumeRayCastMapper.h>
#include <vtkUnstructuredGridVolumeZSweepMapper.h>
#include <vtkProjectedTetrahedraMapper.h>

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
    ren->SetBackground(1.0, 1.0, 1.0);

    vtkSmartPointer<vtkStructuredPointsReader> reader = vtkSmartPointer<vtkStructuredPointsReader>::New();
    reader->SetFileName("D:/data/ironProt.vtk");
    reader->Update();

    vtkSmartPointer<vtkThreshold> thresh = vtkSmartPointer<vtkThreshold>::New();
    thresh->SetUpperThreshold(80);
    thresh->AllScalarsOff();
    thresh->SetInputConnection(reader->GetOutputPort());

    vtkSmartPointer<vtkDataSetTriangleFilter> trifilter = vtkSmartPointer<vtkDataSetTriangleFilter>::New();
    trifilter->SetInputConnection(thresh->GetOutputPort());

    vtkSmartPointer<vtkPiecewiseFunction> opacityTransferFunction = vtkSmartPointer<vtkPiecewiseFunction>::New();
    opacityTransferFunction->AddPoint(80.0,  0.0);
    opacityTransferFunction->AddPoint(120.0, 0.2);
    opacityTransferFunction->AddPoint(255.0, 0.2);

    vtkSmartPointer<vtkColorTransferFunction> colorTransferFunction = vtkSmartPointer<vtkColorTransferFunction>::New();
    colorTransferFunction->AddRGBPoint(80.0,  0.0, 0.0, 0.0);
    colorTransferFunction->AddRGBPoint(120.0, 0.0, 0.0, 1.0);
    colorTransferFunction->AddRGBPoint(160.0, 1.0, 0.0, 0.0);
    colorTransferFunction->AddRGBPoint(200.0, 0.0, 1.0, 0.0);
    colorTransferFunction->AddRGBPoint(255.0, 0.0, 1.0, 1.0);

    vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
    volumeProperty->SetColor(colorTransferFunction);
    volumeProperty->SetScalarOpacity(opacityTransferFunction);
    volumeProperty->ShadeOff();
    volumeProperty->SetInterpolationTypeToLinear();

    vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
    volume->SetProperty(volumeProperty);

    int RenderType = 3;
    if (RenderType == 1)
    {
        vtkSmartPointer<vtkUnstructuredGridVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkUnstructuredGridVolumeRayCastMapper>::New();
        volumeMapper->SetInputConnection(trifilter->GetOutputPort());
        volume->SetMapper(volumeMapper);
        ren->AddVolume(volume);
    }
    else if(RenderType == 2)
    {
        vtkSmartPointer<vtkUnstructuredGridVolumeZSweepMapper> volumeMapper = vtkSmartPointer<vtkUnstructuredGridVolumeZSweepMapper>::New();
        volumeMapper->SetInputConnection(trifilter->GetOutputPort());
        volume->SetMapper(volumeMapper);
        ren->AddVolume(volume);
    }
    else if(RenderType == 3)
    {
        vtkSmartPointer<vtkProjectedTetrahedraMapper> volumeMapper = vtkSmartPointer<vtkProjectedTetrahedraMapper>::New();
        volumeMapper->SetInputConnection(trifilter->GetOutputPort());
        volume->SetMapper(volumeMapper);
        ren->AddVolume(volume);
    }

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(ren);

    QVTKOpenGLNativeWidget w;
    w.resize(640, 480);
    w.setRenderWindow(renderWindow);
    w.setWindowTitle("UnstructuredGridVolumeRendering");
    w.show();

    return a.exec();
}

 运行效果:

  • 21
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值