您的位置:首页 > 其它

VTK修炼之道63:纹理映射体绘制_二维纹理映射

2017-02-06 23:03 309 查看

1.纹理映射体绘制

基于软件实现的光线投影体绘制算法计算量非常大,不利于进行实时渲染。因此,目前体绘制经常使用图形硬件利用纹理映射来加速
其主要原理是将三维体数据作为纹理装载入硬件缓存中,利用硬件来实现插值以及图像合成操作,以提高绘制效率。
基于图形硬件三维纹理功能的体绘制技术,主要是利用硬件的三线性过滤插值能力,通过渲染多个与视线垂直的面片来重建整个三维结构。每个面片利用三维纹理来决定颜色和透明度。这种方法得到的效果从本质上讲与光线投影的效果相同。最新的方法可以直接利用三维纹理在图形硬件上实现光线投影的算法。

2.二维纹理映射

早期受到硬件技术的限制,显卡只能支持二维纹理映射。其基本思路是将每个坐标轴方向的切片作为二维纹理保存到图形硬件缓冲中,在光线投影时,选择与当前视线方向垂直的一组纹理图像,在硬件中进行插值和合成运算以实现体绘制。
VTK中的vtkVolumeTextureMapper2D类可用于实现基于二维纹理映射的体绘制方法。
具体代码如下所示:
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkStructuredPoints.h>
#include <vtkStructuredPointsReader.h>
#include <vtkVolumeTextureMapper2D.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVolumeProperty.h>
#include <vtkVolumeRayCastIsosurfaceFunction.h>

int main(int argc, char *argv[])
{
vtkSmartPointer<vtkStructuredPointsReader> reader =
vtkSmartPointer<vtkStructuredPointsReader>::New();
reader->SetFileName("mummy.128.vtk");
reader->Update();

vtkSmartPointer<vtkVolumeTextureMapper2D> volumeMapper =
vtkSmartPointer<vtkVolumeTextureMapper2D>::New();
volumeMapper->SetInputData(reader->GetOutput());;

/*************************************************************************/
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<vtkVolume> volume =
vtkSmartPointer<vtkVolume>::New();
volume->SetMapper(volumeMapper);
volume->SetProperty(volumeProperty);

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

vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New();
rw->AddRenderer(ren);
rw->SetSize(480, 480);
rw->Render();
rw->SetWindowName("VolumeRendering by Texture2D");

vtkSmartPointer<vtkRenderWindowInteractor> rwi =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
rwi->SetRenderWindow(rw);

ren->ResetCamera();
rw->Render();
rwi->Start();

return 0;
}
输出结果图像为:





通过对比2D纹理体绘制程序与光线投影法体绘制程序,会发现两者基本是一样的,仅仅是vtkVolumeMapper不同。这充分证明了VTK体渲染管线的易用性与通用性。当从一种体绘制方法变换到另一种时,只需要更换相应的vtkVolumeMapper即可。

3.vtkVolumeTexture2D类说明

vtkVolumeTexture2D勒种有两个重要的函数:

SetTargetTextureSize(int _ arg1, int _arg2);该函数用于设置纹理图像的大小 默认为512*512。其大小必须为2的幂。
SetMaximumNumberOfPlanes(int _arg);该函数用于设置纹理映射的平面数目。当视线垂直方向上的像素数目大于该值时,平面会自动跳跃进行合理的映射。

基于vtkVolumeTexture2D类的二维纹理映射体绘制渲染仅支持合成方式生成渲染图像。

4.与光线投影体绘制算法的对比

基于二维纹理映射的体绘制渲染速度要优于光线投影体绘制。
但是vtkVolumeTexture2D仅支持Alpha合成技术,并且切片上使用双线性插值实现纹理映射,为切片之间不进行任何处理,因此,该方法的体绘制渲染效果是低于光线投影算法的。
此外该方法需要在三个方向上保存相应的纹理图像堆栈,占用内存也比较大。
还有一点需要注意的就是,该方法在渲染过程中会根据视线方向选择当前最垂直(会是最优吗?)的一组纹理,因此在进行两组纹理切换时,会长生瑕疵,从而造成渲染质量的下降。

5.参看资料

1.《C++ primer》

2.《The VTK User’s Guide – 11thEdition》

3.  张晓东, 罗火灵. VTK图形图像开发进阶[M]. 机械工业出版社, 2015.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: