VTK修炼之道70:体绘制讨论_光照阴影、VTKLODProp3D
生活随笔
收集整理的這篇文章主要介紹了
VTK修炼之道70:体绘制讨论_光照阴影、VTKLODProp3D
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.光照與陰影
通過VTKVolumeProperty可以設置體繪制陰影效果(Shading)。陰影效果主要受環境光系數、散射光系數、反射光系數和高光強度四個參數影響。- vtkVolumeProperty::SetAmbient()設置環境光系數
- vtkVolumeProperty::SetDiffuse()設置散射光系數
- vtkVolumeProperty::SetSpecular()設置反射光系數
代碼中,設置了環境光系數為0.4,散射光系數為0.6,反射光系數為0.2。 在這三個系數中,當環境光系數占主導時,陰影效果不明顯。當散射光系數占主導時,顯示效果會比較粗燥;但反射光系數占主導時,顯示效果會比較光滑。 當陰影效果關閉時,等同于環境光系數為1.0,其他兩個系數為零。 當然陰影效果還與光源的數目、位置和顏色有關。
左視圖是開啟陰影后的效果;右視圖是關閉陰影后的效果。通過比較我們可以發現:開啟陰影后體繪制效果會更加清晰逼真。 需要注意的是,開啟陰影效果對vtkUnstructuredGrid數據類型是無效的;此外,對vtkImageData的最大密度投影也是無效的。而且對于多元數據,雖然可以為每一個組分開啟陰影以及設置相應的系數,但是,現有VTK的vtkVolumeMapper類并不支持該類型數據體數據中的渲染效果。
2. 體繪制加速:vtkLODProp3D
對于一個大數據來講,體繪制是一個計算量非常龐大、非常耗時的操作。尤其是在用戶交互過程,需要不斷對數據進行渲染,這樣就造成了交互不流暢,用戶體驗差。 可以使用VTKLODProp3D來解決這個問題,提高繪制速度。vtkLODProp3D類的用法與vtkVolume類似,兩者都繼承自vtkProp3D。不同的是,vtkLODProp3D類能夠支持多個Mapper、Property和Texture對象,并由他選擇Mapper對象實現繪制。 例如,當繪制一個數據量非常大的不規則網格數據時,可以添加一個vtkPolyDataMapper渲染一個表面模型,作為最低級別分辨率的渲染;然后將數據采樣為VTKImageDataMapper數據,并添加一個vtkVolumeTextureMapper3D進行體繪制,作為一個中間級別渲染;左后可以通過ZSweep技術(vtkUnstructuredGridVolumeZSweepMapper)渲染原始數據,作為最高級別的渲染。 vtkLODProp3D在渲染過程中,會為每個Mapper估計一個渲染時間,并選擇一個最優的實現渲染。2.1 使用vtkLODProp3D提高渲染速度和交互體驗
示例代碼如下: #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 <vtkVolumeProperty.h> #include <vtkPiecewiseFunction.h> #include <vtkColorTransferFunction.h> #include <vtkGPUVolumeRayCastMapper.h> #include <vtkVolume.h> #include <vtkLODProp3D.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkCamera.h>int main(int argc, char *argv[]) {vtkSmartPointer<vtkStructuredPointsReader> reader =vtkSmartPointer<vtkStructuredPointsReader>::New();reader->SetFileName("mummy.128.vtk");reader->Update();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->SetInputData(reader->GetOutput());hiresMapper->SetAutoAdjustSampleDistances(0); //關閉自動調整功能vtkSmartPointer<vtkGPUVolumeRayCastMapper> lowresMapper =vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();lowresMapper->SetInputData(reader->GetOutput());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(hiresMapper);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<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();renWin->AddRenderer(volumeRender);renWin->AddRenderer(propRender);renWin->SetSize(640, 320);renWin->Render();renWin->SetWindowName("Volume By vtkLODProp3D");vtkSmartPointer<vtkRenderWindowInteractor> rwi =vtkSmartPointer<vtkRenderWindowInteractor>::New();rwi->SetRenderWindow(renWin);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());renWin->Render();rwi->Start();return 0; }輸出結果:2.2 討論
上面的例子定義了兩個光線投影Mapper對象。由于vtkVolumeRayCastMapper中默認開始自動調整采樣距離來提高效率,因此首先關閉自動調節采樣距離。 對于lowresMapper,程序中設定光線采樣步長和圖像采樣距離為hiresMapper的四倍。Mapper定義完畢后,我們就可以調用vtkLODProp3D進行渲染顯示。 vtkLODProp3D類添加Mapper的函數原型為:int AddLOD(vtkMapper* m, vtkProperty* p, double time); 該函數有三個參數,前兩個定義了Mapper對象及Property屬性。第三個參數為一個時間大小,表示當前Mapper渲染時間的初始值。如果該時間設置為0,表示開始時立即渲染對象而不用估計當前Mapper的渲染時間。 完成初試渲染后,可以得到各種Mapper的渲染時間。在vtkLODProp3D對象渲染時,會首先選擇那些渲染時間為0的Mapper來渲染場景。 當然,一般來說,渲染時間為零的情況比較少見。在上個例子中,因為兩個Mapper渲染時間的初始值均設為0,所以程序一開始便會渲染兩次。
2.3 vtkLODProp3D的應用前景
實際中,經常會應用LOD技術來使用各種方法來實現體繪制,在滿足精度的要求下提高交互體驗。 我們知道,vtkVolume負責組合體繪制管線,除了包含一個Mapper對象外,還需要用VTKVolumeProperty對象來設置體繪制的顏色映射,如不透明度傳輸函數、梯度不透明度傳輸函數、顏色傳輸函數和設置陰影效果。vtkLODProp3D最大的優勢在于提供了一種LOD技術來集成多種Mapper對象,能夠有效提高渲染效率的交互體驗。3.參看資料
1.《C++ primer》2.《The VTK User’s Guide – 11thEdition》
3. ?張曉東, 羅火靈. VTK圖形圖像開發進階[M]. 機械工業出版社, 2015.
總結
以上是生活随笔為你收集整理的VTK修炼之道70:体绘制讨论_光照阴影、VTKLODProp3D的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VTK修炼之道69:体绘制讨论_颜色传输
- 下一篇: 【飞秋】网络的基础-域名篇