VTK修炼之道67:体绘制讨论_不透明度传输函数
1.vtkVolume
vtkVolume類似于幾何渲染中的vtkActor,用于表示渲染場景中的對象。除了存儲基本變換信息(平移、旋轉、縮放等),其內部還存儲了兩個重要對象。這兩個對象分別是vtkAbstractVolumeMapper對象和vtkVolumeProperty對象。
1.1 void SetMapper(vtkAbstractVolumeMapper* mapper);
該函數用于連接vtkAbstractVolumeMapper對象,并根據不同的體繪制算法獲取其內部生成的圖元數據。具體的體繪制Mapper如下所示:
1.2 void SetProperty(vtkVolumeProperty* property)
該函數用于設置VTKVolumeProperty對象。其中vtkVolumeProperty用來設置體繪制的顏色、不透明度函數、陰影等信息。在體繪制中,顏色和不透明度設置至關重要,決定了最終的顯示結果。
2.VTKVolumeProperty——不透明度傳輸函數
不透明度傳輸函數是一個分段線性標量映射函數,利用該函數可將光線投影過程中的采樣點灰度值映射為不同的不透明度值,已決定最終顏色值。一個標準的不透明度設置代碼如下:
//添加灰度不透明度屬性 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類中通過如下函數設置和獲取不透明度函數:
void SetScalarOpacity(vtkPiecewiseFuntion* function); vtkPiecewiseFunction* GetScalarOpacity(int Index);vtkPiecewiseFunction類定義標量線性分段函數,其支持兩種設置方式,第一種方式是直接添加斷點;第二種是直接添加一條線段,即添加兩個斷點。
2.1 直接添加斷點
該函數驅動如下:int AddPoint(double x,double y);第一個參數x為自變量,這里是指灰度值;y則是映射值,這里指不同明度。執行成功后,返回當前添加的斷點的index索引值(從0開始),否則返回-1.
2.2 直接添加一條線段
其核心就是添加兩個斷點。其函數設置如下:void AddSegment(double x1,double y1,double x2, double y2);添加兩個斷點(x1,y1)/(x2,y2),組成一條線段。注意添加一條線段時,如果改線段內已經存在斷點,則該斷點會被清除。如果采用這種方式設置不透明度傳輸函數,則上面代碼要重寫為:
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 刪除斷點操作
vtkPiecewiseFunction類中也包括了刪除斷點函數。具體如下:int RemovePoint(double x); //將自變量值為x的斷點刪除;
void RemoveAllPoints(); //刪除所有斷點;
2.4 實際意義
上面代碼中設置了三個不透明度斷點(70,0.00)、(90,0.40)、(180,0.60)。其意義是,當灰度值小于70時,不透明導讀應設置為0;當灰度值介于70~90時,通過線性映射到0.0~0.40之間;當灰度值介于90~180時,現行映射至0.40~0.60;當灰度值大于180度時,不透明度映射到0.60~1.00的一個值。如果圖像的灰度范圍為0~255,那么上述代碼利用三個斷點將整個灰度范圍分為四段處理。2.5 Clamping標志
vtkPiecewiseFunction中有個Clamping標志,當Clamping標志為真時,對于小于所有斷點最小灰度值的灰度值,其映射為最小灰度值斷點對應的映射值;對于大于所有斷點最大灰度值的灰度值,其映射值為最大灰度值斷點對應的映射值。如下圖所示:
當Clamping標志為假時,所有位于斷點灰度值范圍之外的灰度對應映射值都為零。如下圖所示:
3.不同不透明度傳輸函數對應的體繪制實驗
代碼如下:
#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(); //設置線性插值volumeProperty1->ShadeOn();//開啟陰影功能 volumeProperty1->SetAmbient(0.4);//設置環境溫度系數volumeProperty1->SetDiffuse(0.6);//設置漫反射系數volumeProperty1->SetSpecular(0.2);//設置鏡面反射系數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(); //設置線性插值volumeProperty2->ShadeOn();//開啟陰影功能 volumeProperty2->SetAmbient(0.4);//設置環境溫度系數volumeProperty2->SetDiffuse(0.6);//設置漫反射系數volumeProperty2->SetSpecular(0.2);//設置鏡面反射系數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; }
利用不透明度傳輸函數,可以有選擇的對圖像中的對象進行顯示。對于不想看到的圖像部分,只需將其對應的灰度范圍的不透明度映射為0即可。下圖即為該程序的輸出成果:
左視圖采用的不透明度設置參數如下:
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<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圖形圖像開發進階[M]. 機械工業出版社, 2015.
總結
以上是生活随笔為你收集整理的VTK修炼之道67:体绘制讨论_不透明度传输函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 飞鸽传书2007绿色版的发展
- 下一篇: VTK修炼之道68:体绘制讨论_梯度不透