VTK修炼之道67:体绘制讨论_不透明度传输函数
1.vtkVolume
vtkVolume類似于幾何渲染中的vtkActor,用于表示渲染場(chǎng)景中的對(duì)象。除了存儲(chǔ)基本變換信息(平移、旋轉(zhuǎn)、縮放等),其內(nèi)部還存儲(chǔ)了兩個(gè)重要對(duì)象。這兩個(gè)對(duì)象分別是vtkAbstractVolumeMapper對(duì)象和vtkVolumeProperty對(duì)象。
1.1 void SetMapper(vtkAbstractVolumeMapper* mapper);
該函數(shù)用于連接vtkAbstractVolumeMapper對(duì)象,并根據(jù)不同的體繪制算法獲取其內(nèi)部生成的圖元數(shù)據(jù)。具體的體繪制Mapper如下所示:
1.2 void SetProperty(vtkVolumeProperty* property)
該函數(shù)用于設(shè)置VTKVolumeProperty對(duì)象。其中vtkVolumeProperty用來(lái)設(shè)置體繪制的顏色、不透明度函數(shù)、陰影等信息。在體繪制中,顏色和不透明度設(shè)置至關(guān)重要,決定了最終的顯示結(jié)果。
2.VTKVolumeProperty——不透明度傳輸函數(shù)
不透明度傳輸函數(shù)是一個(gè)分段線性標(biāo)量映射函數(shù),利用該函數(shù)可將光線投影過程中的采樣點(diǎn)灰度值映射為不同的不透明度值,已決定最終顏色值。一個(gè)標(biāo)準(zhǔn)的不透明度設(shè)置代碼如下:
//添加灰度不透明度屬性 vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity =vtkSmartPointer<vtkPiecewiseFunction>::New(); compositeOpacity->AddPoint(70, 0.0); compositeOpacity->AddPoint(90, 0.4); compositeOpacity->AddPoint(180, 0.6); volumeProperty->SetScalarOpacity(compositeOpacity);VTKVolumeProperty類中通過如下函數(shù)設(shè)置和獲取不透明度函數(shù):
void SetScalarOpacity(vtkPiecewiseFuntion* function); vtkPiecewiseFunction* GetScalarOpacity(int Index);vtkPiecewiseFunction類定義標(biāo)量線性分段函數(shù),其支持兩種設(shè)置方式,第一種方式是直接添加斷點(diǎn);第二種是直接添加一條線段,即添加兩個(gè)斷點(diǎn)。
2.1 直接添加斷點(diǎn)
該函數(shù)驅(qū)動(dòng)如下:int AddPoint(double x,double y);第一個(gè)參數(shù)x為自變量,這里是指灰度值;y則是映射值,這里指不同明度。執(zhí)行成功后,返回當(dāng)前添加的斷點(diǎn)的index索引值(從0開始),否則返回-1.
2.2 直接添加一條線段
其核心就是添加兩個(gè)斷點(diǎn)。其函數(shù)設(shè)置如下:void AddSegment(double x1,double y1,double x2, double y2);添加兩個(gè)斷點(diǎn)(x1,y1)/(x2,y2),組成一條線段。注意添加一條線段時(shí),如果改線段內(nèi)已經(jīng)存在斷點(diǎn),則該斷點(diǎn)會(huì)被清除。如果采用這種方式設(shè)置不透明度傳輸函數(shù),則上面代碼要重寫為:
compositeOpacity->AddSegment(70, 0, 90, 0.4); compositeOpacity->AddSegment(90, 0.4, 180, 0.6); compositeOpacity->AddSegment(180, 0.6, 255, 1.0); volumeProperty->SetScalarOpacity(compositeOpacity)
2.3 刪除斷點(diǎn)操作
vtkPiecewiseFunction類中也包括了刪除斷點(diǎn)函數(shù)。具體如下:int RemovePoint(double x); //將自變量值為x的斷點(diǎn)刪除;
void RemoveAllPoints(); //刪除所有斷點(diǎn);
2.4 實(shí)際意義
上面代碼中設(shè)置了三個(gè)不透明度斷點(diǎn)(70,0.00)、(90,0.40)、(180,0.60)。其意義是,當(dāng)灰度值小于70時(shí),不透明導(dǎo)讀應(yīng)設(shè)置為0;當(dāng)灰度值介于70~90時(shí),通過線性映射到0.0~0.40之間;當(dāng)灰度值介于90~180時(shí),現(xiàn)行映射至0.40~0.60;當(dāng)灰度值大于180度時(shí),不透明度映射到0.60~1.00的一個(gè)值。如果圖像的灰度范圍為0~255,那么上述代碼利用三個(gè)斷點(diǎn)將整個(gè)灰度范圍分為四段處理。2.5 Clamping標(biāo)志
vtkPiecewiseFunction中有個(gè)Clamping標(biāo)志,當(dāng)Clamping標(biāo)志為真時(shí),對(duì)于小于所有斷點(diǎn)最小灰度值的灰度值,其映射為最小灰度值斷點(diǎn)對(duì)應(yīng)的映射值;對(duì)于大于所有斷點(diǎn)最大灰度值的灰度值,其映射值為最大灰度值斷點(diǎn)對(duì)應(yīng)的映射值。如下圖所示:
當(dāng)Clamping標(biāo)志為假時(shí),所有位于斷點(diǎn)灰度值范圍之外的灰度對(duì)應(yīng)映射值都為零。如下圖所示:
3.不同不透明度傳輸函數(shù)對(duì)應(yīng)的體繪制實(shí)驗(yàn)
代碼如下:
#include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL); VTK_MODULE_INIT(vtkRenderingVolumeOpenGL); VTK_MODULE_INIT(vtkRenderingFreeType); VTK_MODULE_INIT(vtkInteractionStyle);#include <vtkSmartPointer.h> #include <vtkStructuredPointsReader.h> #include <vtkStructuredPoints.h> #include <vtkGPUVolumeRayCastMapper.h> #include <vtkVolumeProperty.h> #include <vtkPiecewiseFunction.h> #include <vtkColorTransferFunction.h> #include <vtkVolume.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkCamera.h>int main() {vtkSmartPointer<vtkStructuredPointsReader> reader =vtkSmartPointer<vtkStructuredPointsReader>::New();reader->SetFileName("mummy.128.vtk");reader->Update();vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper1 =vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();volumeMapper1->SetInputData(reader->GetOutput());vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper2 =vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();volumeMapper2->SetInputData(reader->GetOutput()); /****************************************************************/vtkSmartPointer<vtkVolumeProperty> volumeProperty1 =vtkSmartPointer<vtkVolumeProperty>::New();volumeProperty1->SetInterpolationTypeToLinear(); //設(shè)置線性插值volumeProperty1->ShadeOn();//開啟陰影功能 volumeProperty1->SetAmbient(0.4);//設(shè)置環(huán)境溫度系數(shù)volumeProperty1->SetDiffuse(0.6);//設(shè)置漫反射系數(shù)volumeProperty1->SetSpecular(0.2);//設(shè)置鏡面反射系數(shù)vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity1 =vtkSmartPointer<vtkPiecewiseFunction>::New();compositeOpacity1->AddPoint(70, 0.0);compositeOpacity1->AddPoint(90, 0.4);compositeOpacity1->AddPoint(180, 0.6);volumeProperty1->SetScalarOpacity(compositeOpacity1);vtkSmartPointer<vtkVolumeProperty> volumeProperty2 =vtkSmartPointer<vtkVolumeProperty>::New();volumeProperty2->SetInterpolationTypeToLinear(); //設(shè)置線性插值volumeProperty2->ShadeOn();//開啟陰影功能 volumeProperty2->SetAmbient(0.4);//設(shè)置環(huán)境溫度系數(shù)volumeProperty2->SetDiffuse(0.6);//設(shè)置漫反射系數(shù)volumeProperty2->SetSpecular(0.2);//設(shè)置鏡面反射系數(shù)vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity2 =vtkSmartPointer<vtkPiecewiseFunction>::New();compositeOpacity2->AddPoint(100, 0.0);compositeOpacity2->AddPoint(140, 0.4);compositeOpacity2->AddPoint(180, 0.6);volumeProperty2->SetScalarOpacity(compositeOpacity2);/vtkSmartPointer<vtkPiecewiseFunction> gradientOpacity =vtkSmartPointer<vtkPiecewiseFunction>::New();gradientOpacity->AddPoint(10, 0.0);gradientOpacity->AddPoint(90, 0.5);gradientOpacity->AddPoint(100, 1.0);volumeProperty1->SetGradientOpacity(gradientOpacity);volumeProperty2->SetGradientOpacity(gradientOpacity);vtkSmartPointer<vtkColorTransferFunction> color =vtkSmartPointer<vtkColorTransferFunction>::New();color->AddRGBPoint(0, 0, 0, 0);color->AddRGBPoint(64, 1.0, 0.52, 0.3);color->AddRGBPoint(190.0, 1.00, 1.00, 1.00);color->AddRGBPoint(220.0, 0.20, 0.20, 0.20);volumeProperty1->SetColor(color);volumeProperty2->SetColor(color); /****************************************************************/vtkSmartPointer<vtkVolume> volume1 =vtkSmartPointer<vtkVolume>::New();volume1->SetMapper(volumeMapper1);volume1->SetProperty(volumeProperty1);vtkSmartPointer<vtkVolume> volume2 =vtkSmartPointer<vtkVolume>::New();volume2->SetMapper(volumeMapper2);volume2->SetProperty(volumeProperty2);//double View1[4] = { 0, 0, 0.5, 1 };double View2[4] = { 0.5, 0, 1, 1 };vtkSmartPointer<vtkRenderer> render1 =vtkSmartPointer<vtkRenderer>::New();render1->AddVolume(volume1);render1->SetViewport(View1);render1->SetBackground(1, 1, 0);vtkSmartPointer<vtkRenderer> render2 =vtkSmartPointer<vtkRenderer>::New();render2->AddVolume(volume2);render2->SetViewport(View2);render2->SetBackground(0, 1, 0);vtkSmartPointer<vtkRenderWindow> rw =vtkSmartPointer<vtkRenderWindow>::New();rw->AddRenderer(render1);rw->AddRenderer(render2);rw->SetSize(640, 320);rw->SetWindowName("Differ Gray Opacity Function");vtkSmartPointer<vtkRenderWindowInteractor> rwi =vtkSmartPointer<vtkRenderWindowInteractor>::New();rwi->SetRenderWindow(rw);render1->GetActiveCamera()->SetPosition(0, -1, 0);render1->GetActiveCamera()->SetFocalPoint(0, 0, 0);render1->GetActiveCamera()->SetViewUp(0, 0, 1);render1->GetActiveCamera()->Azimuth(30);render1->GetActiveCamera()->Elevation(30);render1->ResetCamera();render2->SetActiveCamera(render1->GetActiveCamera());rw->Render();rwi->Start();return 0; }
利用不透明度傳輸函數(shù),可以有選擇的對(duì)圖像中的對(duì)象進(jìn)行顯示。對(duì)于不想看到的圖像部分,只需將其對(duì)應(yīng)的灰度范圍的不透明度映射為0即可。下圖即為該程序的輸出成果:
左視圖采用的不透明度設(shè)置參數(shù)如下:
vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity1 =vtkSmartPointer<vtkPiecewiseFunction>::New(); compositeOpacity1->AddPoint(70, 0.0); compositeOpacity1->AddPoint(90, 0.4); compositeOpacity1->AddPoint(180, 0.6); volumeProperty1->SetScalarOpacity(compositeOpacity1);右視圖采用的不透明度設(shè)置參數(shù)如下:
vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity2 =vtkSmartPointer<vtkPiecewiseFunction>::New(); compositeOpacity2->AddPoint(100, 0.0); compositeOpacity2->AddPoint(140, 0.4); compositeOpacity2->AddPoint(180, 0.6); volumeProperty2->SetScalarOpacity(compositeOpacity2);
4.參看資料
1.《C++ primer》
2.《The VTK User’s Guide – 11thEdition》
3. ?張曉東, 羅火靈. VTK圖形圖像開發(fā)進(jìn)階[M]. 機(jī)械工業(yè)出版社, 2015.
總結(jié)
以上是生活随笔為你收集整理的VTK修炼之道67:体绘制讨论_不透明度传输函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 飞鸽传书2007绿色版的发展
- 下一篇: 下面的一堆文字为了说明一件事情---.N