1.vtkVolume
vtkVolume類似於幾何渲染中的vtkActor,用於表示渲染場景中的對象。除了存儲基本變換信息(平移、旋轉、縮放等),其內部還存儲了兩個重要對象。這兩個對象分別是vtkAbstractVolumeMapper對象和vtkVolumeProperty對象。
1.1 void SetMapper(vtkAbstractVolumeMapper* mapper);
該函數用於連接vtkAbstractVolumeMapper對象,並根據不同的體繪制算法獲取其內部生成的圖元數據。具體的體繪制Mapper如下所示:
1.2 void SetProperty(vtkVolumeProperty* property)
該函數用於設置VTKVolumeProperty對象。其中vtkVolumeProperty用來設置體繪制的顏色、不透明度函數、陰影等信息。在體繪制中,顏色和不透明度設置至關重要,決定了最終的顯示結果。
2.VTKVolumeProperty——不透明度傳輸函數
不透明度傳輸函數是一個分段線性標量映射函數,利用該函數可將光線投影過程中的采樣點灰度值映射為不同的不透明度值,已決定最終顏色值。一個標准的不透明度設置代碼如下:
VTKVolumeProperty類中通過如下函數設置和獲取不透明度函數:1 //添加灰度不透明度屬性 2 vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = 3 vtkSmartPointer<vtkPiecewiseFunction>::New(); 4 compositeOpacity->AddPoint(70, 0.0); 5 compositeOpacity->AddPoint(90, 0.4); 6 compositeOpacity->AddPoint(180, 0.6); 7 volumeProperty->SetScalarOpacity(compositeOpacity);
vtkPiecewiseFunction類定義標量線性分段函數,其支持兩種設置方式,第一種方式是直接添加斷點;第二種是直接添加一條線段,即添加兩個斷點。1 void SetScalarOpacity(vtkPiecewiseFuntion* function); 2 vtkPiecewiseFunction* GetScalarOpacity(int Index);
2.1 直接添加斷點
該函數驅動如下:第一個參數x為自變量,這里是指灰度值;y則是映射值,這里指不同明度。執行成功后,返回當前添加的斷點的index索引值(從0開始),否則返回-1.int AddPoint(double x,double y);
2.2 直接添加一條線段
其核心就是添加兩個斷點。其函數設置如下:添加兩個斷點(x1,y1)/(x2,y2),組成一條線段。 注意添加一條線段時,如果改線段內已經存在斷點,則該斷點會被清除。如果采用這種方式設置不透明度傳輸函數,則上面代碼要重寫為:int AddPoint(double x,double y);
1 compositeOpacity->AddSegment(70, 0, 90, 0.4); 2 compositeOpacity->AddSegment(90, 0.4, 180, 0.6); 3 compositeOpacity->AddSegment(180, 0.6, 255, 1.0); 4 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.不同不透明度傳輸函數對應的體繪制實驗
代碼如下:
1 #include <vtkAutoInit.h> 2 VTK_MODULE_INIT(vtkRenderingOpenGL); 3 VTK_MODULE_INIT(vtkRenderingVolumeOpenGL); 4 VTK_MODULE_INIT(vtkRenderingFreeType); 5 VTK_MODULE_INIT(vtkInteractionStyle); 6 7 #include <vtkSmartPointer.h> 8 #include <vtkStructuredPointsReader.h> 9 #include <vtkStructuredPoints.h> 10 #include <vtkGPUVolumeRayCastMapper.h> 11 #include <vtkVolumeProperty.h> 12 #include <vtkPiecewiseFunction.h> 13 #include <vtkColorTransferFunction.h> 14 #include <vtkVolume.h> 15 #include <vtkRenderer.h> 16 #include <vtkRenderWindow.h> 17 #include <vtkRenderWindowInteractor.h> 18 #include <vtkCamera.h> 19 20 int main() 21 { 22 vtkSmartPointer<vtkStructuredPointsReader> reader = 23 vtkSmartPointer<vtkStructuredPointsReader>::New(); 24 reader->SetFileName("mummy.128.vtk"); 25 reader->Update(); 26 27 vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper1 = 28 vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New(); 29 volumeMapper1->SetInputData(reader->GetOutput()); 30 31 vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper2 = 32 vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New(); 33 volumeMapper2->SetInputData(reader->GetOutput()); 34 /****************************************************************/ 35 vtkSmartPointer<vtkVolumeProperty> volumeProperty1 = 36 vtkSmartPointer<vtkVolumeProperty>::New(); 37 volumeProperty1->SetInterpolationTypeToLinear(); //設置線性插值 38 volumeProperty1->ShadeOn();//開啟陰影功能 39 volumeProperty1->SetAmbient(0.4);//設置環境溫度系數 40 volumeProperty1->SetDiffuse(0.6);//設置漫反射系數 41 volumeProperty1->SetSpecular(0.2);//設置鏡面反射系數 42 43 vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity1 = 44 vtkSmartPointer<vtkPiecewiseFunction>::New(); 45 compositeOpacity1->AddPoint(70, 0.0); 46 compositeOpacity1->AddPoint(90, 0.4); 47 compositeOpacity1->AddPoint(180, 0.6); 48 volumeProperty1->SetScalarOpacity(compositeOpacity1); 49 50 vtkSmartPointer<vtkVolumeProperty> volumeProperty2 = 51 vtkSmartPointer<vtkVolumeProperty>::New(); 52 volumeProperty2->SetInterpolationTypeToLinear(); //設置線性插值 53 volumeProperty2->ShadeOn();//開啟陰影功能 54 volumeProperty2->SetAmbient(0.4);//設置環境溫度系數 55 volumeProperty2->SetDiffuse(0.6);//設置漫反射系數 56 volumeProperty2->SetSpecular(0.2);//設置鏡面反射系數 57 58 vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity2 = 59 vtkSmartPointer<vtkPiecewiseFunction>::New(); 60 compositeOpacity2->AddPoint(100, 0.0); 61 compositeOpacity2->AddPoint(140, 0.4); 62 compositeOpacity2->AddPoint(180, 0.6); 63 volumeProperty2->SetScalarOpacity(compositeOpacity2); 64 / 65 vtkSmartPointer<vtkPiecewiseFunction> gradientOpacity = 66 vtkSmartPointer<vtkPiecewiseFunction>::New(); 67 gradientOpacity->AddPoint(10, 0.0); 68 gradientOpacity->AddPoint(90, 0.5); 69 gradientOpacity->AddPoint(100, 1.0); 70 volumeProperty1->SetGradientOpacity(gradientOpacity); 71 volumeProperty2->SetGradientOpacity(gradientOpacity); 72 73 vtkSmartPointer<vtkColorTransferFunction> color = 74 vtkSmartPointer<vtkColorTransferFunction>::New(); 75 color->AddRGBPoint(0, 0, 0, 0); 76 color->AddRGBPoint(64, 1.0, 0.52, 0.3); 77 color->AddRGBPoint(190.0, 1.00, 1.00, 1.00); 78 color->AddRGBPoint(220.0, 0.20, 0.20, 0.20); 79 volumeProperty1->SetColor(color); 80 volumeProperty2->SetColor(color); 81 /****************************************************************/ 82 vtkSmartPointer<vtkVolume> volume1 = 83 vtkSmartPointer<vtkVolume>::New(); 84 volume1->SetMapper(volumeMapper1); 85 volume1->SetProperty(volumeProperty1); 86 87 vtkSmartPointer<vtkVolume> volume2 = 88 vtkSmartPointer<vtkVolume>::New(); 89 volume2->SetMapper(volumeMapper2); 90 volume2->SetProperty(volumeProperty2); 91 // 92 double View1[4] = { 0, 0, 0.5, 1 }; 93 double View2[4] = { 0.5, 0, 1, 1 }; 94 vtkSmartPointer<vtkRenderer> render1 = 95 vtkSmartPointer<vtkRenderer>::New(); 96 render1->AddVolume(volume1); 97 render1->SetViewport(View1); 98 render1->SetBackground(1, 1, 0); 99 100 vtkSmartPointer<vtkRenderer> render2 = 101 vtkSmartPointer<vtkRenderer>::New(); 102 render2->AddVolume(volume2); 103 render2->SetViewport(View2); 104 render2->SetBackground(0, 1, 0); 105 106 vtkSmartPointer<vtkRenderWindow> rw = 107 vtkSmartPointer<vtkRenderWindow>::New(); 108 rw->AddRenderer(render1); 109 rw->AddRenderer(render2); 110 rw->SetSize(640, 320); 111 rw->SetWindowName("Differ Gray Opacity Function"); 112 113 vtkSmartPointer<vtkRenderWindowInteractor> rwi = 114 vtkSmartPointer<vtkRenderWindowInteractor>::New(); 115 rwi->SetRenderWindow(rw); 116 117 render1->GetActiveCamera()->SetPosition(0, -1, 0); 118 render1->GetActiveCamera()->SetFocalPoint(0, 0, 0); 119 render1->GetActiveCamera()->SetViewUp(0, 0, 1); 120 render1->GetActiveCamera()->Azimuth(30); 121 render1->GetActiveCamera()->Elevation(30); 122 render1->ResetCamera(); 123 render2->SetActiveCamera(render1->GetActiveCamera()); 124 125 rw->Render(); 126 rwi->Start(); 127 return 0; 128 }
利用不透明度傳輸函數,可以有選擇的對圖像中的對象進行顯示。對於不想看到的圖像部分,只需將其對應的灰度范圍的不透明度映射為0即可。下圖即為該程序的輸出成果:
左視圖采用的不透明度設置參數如下:
1 vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity1 = 2 vtkSmartPointer<vtkPiecewiseFunction>::New(); 3 compositeOpacity1->AddPoint(70, 0.0); 4 compositeOpacity1->AddPoint(90, 0.4); 5 compositeOpacity1->AddPoint(180, 0.6); 6 volumeProperty1->SetScalarOpacity(compositeOpacity1);
右視圖采用的不透明度設置參數如下:
1 vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity2 = 2 vtkSmartPointer<vtkPiecewiseFunction>::New(); 3 compositeOpacity2->AddPoint(100, 0.0); 4 compositeOpacity2->AddPoint(140, 0.4); 5 compositeOpacity2->AddPoint(180, 0.6); 6 volumeProperty2->SetScalarOpacity(compositeOpacity2);