VTK实现多个体数据映射到一起进行渲染

背景:

        多个面数据(例如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版权协议,转载请附上原文出处链接和本声明。