背景:
多个面数据(例如obj数据等)使用同一个Renderer通过增加多个Actor的方式是可以映射到一起的,但是如果透明度不是1的话深度层次会发生错乱。可以使用Renderer的UseDepthPeelingOn进行深度剥离,来使深度关系是正确的。
但是体数据通过这种方式是达不到深度关系正确的,类似于这种,是按照加入actor的顺序来排序的。
解决方案:
使用vtkMultiVolume来达到多个体数据在同一个空间映射的方案。
vtkNew<vtkMultiVolume> overlappingVol;
vtkNew<vtkGPUVolumeRayCastMapper> mapper;
mapper->SetUseJittering(0);
overlappingVol->SetMapper(mapper);
//一个数据对应一个映射端口
mapper->SetInputConnection(0, Source1->GetOutputPort());
overlappingVol->SetVolume(vol, 0);
mapper->SetInputConnection(1, Source2->GetOutputPort());
overlappingVol->SetVolume(vol1, 1);
下图中左边与中间的体数据成功映射到了一起,深度关系也是正确的。
注意:
1、vtk-8.2.0版本中对volume开启阴影等效果是不起作用的。需要使用vtk-9.1.0以上的版本。
2、vtk-9.1.0版本使用的时候必须对volume设置梯度透明参数,哪怕不用从直接将插入的点透明度设置成1也要设置梯度透明参数,不然会报着色器错误。8.2.0版本不需要设置梯度透明也不会报错。
代码:
#include "vtkAxesActor.h"
#include "vtkCamera.h"
#include "vtkColorTransferFunction.h"
#include "vtkCommand.h"
#include "vtkConeSource.h"
#include "vtkGPUVolumeRayCastMapper.h"
#include "vtkImageResample.h"
#include "vtkImageResize.h"
#include "vtkInteractorStyleTrackballCamera.h"
#include "vtkMultiVolume.h"
#include "vtkNew.h"
#include "vtkPiecewiseFunction.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkVolume16Reader.h"
#include "vtkVolumeProperty.h"
#include "vtkXMLImageDataReader.h"
#include "vtkAbstractMapper.h"
#include "vtkImageData.h"
#include "vtkOutlineFilter.h"
#include "vtkPolyDataMapper.h"
#include "vtkMath.h"
#include <chrono>
void CamereTrans(vtkCamera* cam) {
cam->SetFocalPoint(41.9596, -17.9662, 78.5903);
cam->SetPosition(373.891, 619.954, -53.5932);
cam->SetViewUp(-0.0358384, -0.184856, -0.982112);
}
int main(int argc, char* argv[])
{
double leftViewport[4] = { 0.0, 0.0, 0.33, 1.0 };
double middleViewport[4] = { 0.33, 0.0, 0.66, 1.0 };
double rightViewport[4] = { 0.66, 0.0, 1.0, 1.0 };
// Load data
vtkNew<vtkVolume16Reader> reader;
reader->SetDataDimensions(64, 64); //设置长和宽
reader->SetImageRange(1, 93); //设置切片张数
reader->SetDataByteOrderToLittleEndian();
reader->SetFilePrefix("headsq/quarter");
reader->SetDataSpacing(3.2, 3.2, 1.5);
vtkSmartPointer<vtkXMLImageDataReader> xmlReader = vtkSmartPointer<vtkXMLImageDataReader>::New();
xmlReader->SetFileName("hncma-atlas.vti");
xmlReader->Update();
// Volume 0 (upsampled headmr)
// ---------------------------
vtkNew<vtkImageResize> headmrSource;
headmrSource->SetInputConnection(reader->GetOutputPort());
headmrSource->SetResizeMethodToOutputDimensions();
headmrSource->SetOutputDimensions(128, 128, 128);
headmrSource->Update();
vtkNew<vtkVolumeProperty> volumeProperty;
volumeProperty->SetInterpolationType(VTK_LINEAR_INTERPOLATION);
volumeProperty->SetShade(0,1); //打开或者关闭阴影测试
volumeProperty->SetAmbient(0.8);
volumeProperty->SetDiffuse(0.3); //漫反射
volumeProperty->SetSpecular(0.2); //镜面反射
volumeProperty->SetSpecularPower(10);
vtkNew<vtkColorTransferFunction> ctf;
ctf->AddRGBPoint(0, 0.0, 0.0, 0.0);
ctf->AddRGBPoint(500, 1.0, 0.5, 0.3);
ctf->AddRGBPoint(1000, 1.0, 0.5, 0.3);
ctf->AddRGBPoint(1150, 1.0, 1.0, 0.9);
vtkNew<vtkPiecewiseFunction> pf;
pf->AddPoint(0, 0.00);
pf->AddPoint(500, 0.35);
pf->AddPoint(1000, 0.75);
pf->AddPoint(1150, 0.85);
vtkNew<vtkPiecewiseFunction> gf;
gf->AddPoint(0, 0.0);
gf->AddPoint(90, 0.1);
gf->AddPoint(100, 0.7);
volumeProperty->SetScalarOpacity(pf);
volumeProperty->SetColor(ctf);
volumeProperty->SetGradientOpacity(gf);
vtkNew<vtkVolume> vol;
vol->SetProperty(volumeProperty);
// Volume 1 (brain)
// -----------------------------
vtkNew<vtkVolumeProperty> volumeProperty1;
volumeProperty1->SetInterpolationType(VTK_LINEAR_INTERPOLATION);
vtkNew<vtkPiecewiseFunction> pf1;
pf1->AddPoint(0, 0.0);
pf1->AddPoint(2511, 0.5);
pf1->AddPoint(5022, 1);
vtkNew<vtkColorTransferFunction> ctf1;
ctf1->AddRGBPoint(0, 1.0, 0.3, 0.2);
ctf1->AddRGBPoint(2511, 0.3, 0.2, 0.9);
ctf1->AddRGBPoint(5022, 0.5, 0.6, 1.0);
vtkNew<vtkPiecewiseFunction> gf1;
gf1->AddPoint(0, 0.0);
gf1->AddPoint(550, 0.5);
volumeProperty1->SetScalarOpacity(pf1);
volumeProperty1->SetColor(ctf1);
volumeProperty1->SetGradientOpacity(gf1);
vtkNew<vtkVolume> vol1;
vol1->SetProperty(volumeProperty1);
vol1->SetScale(0.8, 0.8, 0.8);
vol1->SetPosition(210., 200., -90.);
vol1->RotateX(90.);
vol1->RotateY(-95.);
vol1->RotateZ(-5.);
// Multi volume instance
// ---------------------
vtkNew<vtkMultiVolume> overlappingVol;
vtkNew<vtkGPUVolumeRayCastMapper> mapper;
mapper->SetUseJittering(0);
overlappingVol->SetMapper(mapper);
mapper->SetInputConnection(0, headmrSource->GetOutputPort());
overlappingVol->SetVolume(vol, 0);
mapper->SetInputConnection(1, xmlReader->GetOutputPort());
overlappingVol->SetVolume(vol1, 1);
// Rendering context
vtkNew<vtkRenderer> ren;
ren->SetBackground(0.0, 0.0, 0.0);
ren->SetViewport(rightViewport);
ren->AddVolume(overlappingVol);
CamereTrans(ren->GetActiveCamera());
//left render
vtkNew<vtkGPUVolumeRayCastMapper> leftMapper;
leftMapper->SetInputConnection(headmrSource->GetOutputPort());
leftMapper->SetUseJittering(0);
vtkNew<vtkVolume> leftVol;
leftVol->SetProperty(volumeProperty);
leftVol->SetMapper(leftMapper);
vtkNew<vtkRenderer> leftren;
leftren->SetBackground(0.0, 0.0, 0.0);
leftren->SetViewport(leftViewport);
leftren->AddVolume(leftVol);
CamereTrans(leftren->GetActiveCamera());
//middle render
vtkNew<vtkGPUVolumeRayCastMapper> middleMapper;
middleMapper->SetInputConnection(xmlReader->GetOutputPort());
middleMapper->SetUseJittering(0);
vtkNew<vtkVolume> middleVol;
middleVol->SetProperty(volumeProperty1);
middleVol->SetMapper(middleMapper);
vtkNew<vtkRenderer> middleren;
middleren->SetBackground(0.0, 0.0, 0.0);
middleren->SetViewport(middleViewport);
middleren->AddVolume(middleVol);
vtkNew<vtkRenderWindow> renWin;
renWin->SetSize(1366, 512);
renWin->AddRenderer(ren);
renWin->AddRenderer(leftren);
renWin->AddRenderer(middleren);
renWin->SetMultiSamples(0);
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
vtkNew<vtkInteractorStyleTrackballCamera> style;
iren->SetInteractorStyle(style);
renWin->Render();
iren->Initialize();
iren->Start();
return 0;
}
数据:
多个体数据映射到一起进行渲染的demo数据-C++文档类资源-CSDN文库
或者留下邮箱。
版权声明:本文为qq_33598781原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。