vtk等值面体绘制|纹理映射体绘制 附:不透明传输函数,颜色传输函数光照与阴影

Posted MissZhou要努力

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vtk等值面体绘制|纹理映射体绘制 附:不透明传输函数,颜色传输函数光照与阴影相关的知识,希望对你有一定的参考价值。

等值面体绘制:

#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkStructuredPoints.h>
#include <vtkStructuredPointsReader.h>
#include <vtkVolumeRayCastIsosurfaceFunction.h>
#include <vtkVolumeRayCastMapper.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVolumeProperty.h>
#include <vtkAxesActor.h>
#include <vtkImageShiftScale.h>
#include <vtkImageCast.h>


//等值面体绘制效果
int main(int argc, char *argv[])



	vtkSmartPointer<vtkStructuredPointsReader> reader =
		vtkSmartPointer<vtkStructuredPointsReader>::New();
	reader->SetFileName("../mummy.128.vtk");
	reader->Update();

	//等值面绘制函数用来渲染体数据中的特定等值面
	vtkSmartPointer<vtkVolumeRayCastIsosurfaceFunction> rayCastFun =
		vtkSmartPointer<vtkVolumeRayCastIsosurfaceFunction>::New();
	rayCastFun->SetIsoValue(100);//用于设置等值面的值 小于该值的小于该像素的不透明度都设置为0

	//定义一个光线投影体绘制
	vtkSmartPointer<vtkVolumeRayCastMapper> volumeMapper =
		vtkSmartPointer<vtkVolumeRayCastMapper>::New();
	volumeMapper->SetInputData(reader->GetOutput());//接受输入数据
	volumeMapper->SetVolumeRayCastFunction(rayCastFun);//必须设置,否则出错 设置光线投影函数类型

	vtkSmartPointer<vtkVolumeProperty> volumeProperty =
		vtkSmartPointer<vtkVolumeProperty>::New();
	volumeProperty->SetInterpolationTypeToLinear();//设置线性插值类型
	volumeProperty->ShadeOn();
	volumeProperty->SetAmbient(0.2);//阴影色
	volumeProperty->SetDiffuse(0.6);//弥漫性
	volumeProperty->SetSpecular(0.4);//高光 这个属性到0.8有一种“铜”制的效果~~

	透明度映射函数定义
	//给数据点赋不透明值。体绘制中,需要显示三维数据场的内部结构,因而需要生成具有透明度的图像。
	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);

	// vtkVolume掌管映射器和属性对象,可控制体数据的位置和朝向   
	vtkSmartPointer<vtkVolume> volume =
		vtkSmartPointer<vtkVolume>::New();
	volume->SetMapper(volumeMapper);//生成体对象
	volume->SetProperty(volumeProperty);//设置体对象属型

	vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
	ren->SetBackground(1.0, 1.0, 1.0);
	ren->AddVolume(volume);

	vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
	renWin->AddRenderer(ren);
	renWin->SetSize(640, 480);
	renWin->Render();
	renWin->SetWindowName("IsoSurfaceVolRenderingApp");

	vtkSmartPointer<vtkRenderWindowInteractor> iren =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	iren->SetRenderWindow(renWin);
	ren->ResetCamera();

	renWin->Render();
	iren->Start();

	return EXIT_SUCCESS;

忽略掉上面的红字,本来是想做表情包的==

二维纹理映射:

渲染速度快于光线投影体绘制,但是只支持alpha合成技术,而且切片上使用双线性插值实现纹理映射,切片之间不存在插值,渲染质量有所下降;且需要在三个方向上保存相应的纹理图像堆栈,占用内存大

#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkStructuredPoints.h>
#include <vtkStructuredPointsReader.h>
#include <vtkVolumeTextureMapper2D.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVolumeProperty.h>
#include <vtkAxesActor.h>
#include <vtkImageShiftScale.h>
#include <vtkImageCast.h>


int main(int argc, char *argv[])



	vtkSmartPointer<vtkStructuredPointsReader> reader =
		vtkSmartPointer<vtkStructuredPointsReader>::New();
	reader->SetFileName("../mummy.128.vtk");
	reader->Update();

	//上一份代码的mapper(现查了一下是制图的意思==)叫做vtkVolumeRayCastMapper
	vtkSmartPointer<vtkVolumeTextureMapper2D> volumeMapper =
		vtkSmartPointer<vtkVolumeTextureMapper2D>::New();
	volumeMapper->SetInputData(reader->GetOutput());

	//这部分设置体绘制属性的写法和上一份一样==
	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<vtkVolume> volume =
		vtkSmartPointer<vtkVolume>::New();
	volume->SetMapper(volumeMapper);
	volume->SetProperty(volumeProperty);

	vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
	ren->SetBackground(1.0, 1.0, 1.0);
	ren->AddVolume(volume);

	vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
	renWin->AddRenderer(ren);
	renWin->SetSize(640, 480);
	renWin->Render();
	renWin->SetWindowName("Texture2DVolRenderingApp");

	vtkSmartPointer<vtkRenderWindowInteractor> iren =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	iren->SetRenderWindow(renWin);
	ren->ResetCamera();

	renWin->Render();
	iren->Start();

	return EXIT_SUCCESS;

(配字怎么样

三维纹理映射:

三维映射是将体数据映射到一组与视图平面平行的四边形,避免二维纹理映射方法中因为纹理图像切换产生的瑕疵现象。除了类变成了~3D,其他都一样,注释省略==

vtkSmartPointer<vtkStructuredPointsReader> reader =
		vtkSmartPointer<vtkStructuredPointsReader>::New();
	reader->SetFileName("../mummy.128.vtk");
	reader->Update();

	vtkSmartPointer<vtkVolumeTextureMapper3D> volumeMapper =
		vtkSmartPointer<vtkVolumeTextureMapper3D>::New();
	volumeMapper->SetInputData(reader->GetOutput());

	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<vtkVolume> volume =
		vtkSmartPointer<vtkVolume>::New();
	volume->SetMapper(volumeMapper);
	volume->SetProperty(volumeProperty);

	vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
	ren->SetBackground(1.0, 1.0, 1.0);
	ren->AddVolume(volume);

	vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
	renWin->AddRenderer(ren);
	renWin->SetSize(640, 480);
	renWin->Render();
	renWin->SetWindowName("Texture3DVolRenderingApp");

	int valid = volumeMapper->IsRenderSupported(volumeProperty, ren);
	if (!valid) return EXIT_SUCCESS;//判断是否支持当前渲染

	vtkSmartPointer<vtkRenderWindowInteractor> iren =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	iren->SetRenderWindow(renWin);
	ren->ResetCamera();

	renWin->Render();
	iren->Start();

	return EXIT_SUCCESS;

下面好好说说不透明度传输函数,颜色传输函数、光照与阴影

不透明度传输函数

就是这段文字

vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = 
		vtkSmartPointer<vtkPiecewiseFunction>::New();
	compositeOpacity->AddPoint(70,   0.00);
	compositeOpacity->AddPoint(90,   0.40);
	compositeOpacity->AddPoint(180,  0.60);
	volumeProperty->SetScalarOpacity(compositeOpacity);

AddPoint只是其中一种定义标量线性分段函数的方法。第一个参数x是自变量,这里指灰度值;y是映射值,这里指不透明度

addsegment是另一种,直接添加一条线段,即添加两个断点x1,y1,x2,y2

梯度不透明函数添加方法是 SetGradientOpacity()

颜色传输函数

将一个标量映射成一个颜色值,可以是rgb也可以是hsv  rgb换成HSV就可以啦

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);

光线与阴影

之前的注释这里有点不准确QAQ

        volumeProperty->ShadeOn();//开启阴影效果
	volumeProperty->SetAmbient(0.4);//设置环境光系数
	volumeProperty->SetDiffuse(0.6);//设置散射光系数
	volumeProperty->SetSpecular(0.2);//设置反射光系数
一般情况下,三个系数和=1,为提高亮度,之和可能大于1

在这三个系数中,当环境光占主导时,阴影效果不明显;散射光系数占主导时,显示效果比较粗糙;反射光占主导时,显示效果比较光滑。阴影效果关闭时,等同于环境光系数=1.0,其他两个系数=0

以上是关于vtk等值面体绘制|纹理映射体绘制 附:不透明传输函数,颜色传输函数光照与阴影的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 半球纹理映射

VTK切割功能汇总

基于 2D 纹理的体绘制

OpenGL:渲染具有大量纹理透明度的模型,没有绘制顺序?

FBO:渲染到纹理,绘制渲染纹理时纹理映射错误

我的OpenGL学习进阶之旅解决OpenGL绘制带透明通道的png纹理时出现黑边问题,并彻底了解其原理