VTK:体绘制——体绘制管线&图形渲染管线-程序员宅基地

技术标签: 图形渲染  

1.几何渲染与体绘制

  1. 几何渲染:就是通过绘制几何图元(顶点、线段、面片等)来渲染数据,例如绘制图像需要在空间中建立一个四边图元,然后以纹理映射的方式将该图像贴图到该图元上进行渲染;而三维模型的绘制通常会分解为一系列的多边面片进行绘制。这种通过生成中间几何图元来进行渲染的方法称为几何渲染。几何渲染的速度比较快,但是不能显示数据的内部细节。例如:在渲染人的三维CT体数据时,通过几何渲染只能在切片图像之间进行切换,而不能进行切换,而不能对体数据内部细节进行立体观察。
  2. 体绘制:又称为三维重建(区别于投影图像的三维重建),是一种直接利用体数据来生成二维图像的绘制技术。与面绘制不同,体绘制不需要提取提数据内部的等值面,他是对三维数据进行采样和合成的过程。体数据能通过设置不透明度值来显示体数据内部不同成分和细节,例如显示人体CT图像的不同器官和组织。

2.图形渲染管线

在进行体绘制管线学习之前,很有必要回顾一下前面的VTK可视化管线的基本组成。习惯把渲染窗口vtkRenderWindow看做一个剧院,剧院中一般需要灯光(vtkLight)、相机(vtkCamera)和舞台(vtkRenderer)来呈现精彩的演出。舞台上负责表演的自然就是演员(vtk Actor),而且演员的个数不唯一,可以根据需要为舞台加入更多的演员(vtkActor)。
每个演员又具有特色,而用来表示其特色的则是vtkProperty(负责控制值颜色、材质和不透明度等)。
每个演员的数据和渲染信息存储在一个vtkMapper对象中,负责将原始的数据转换为渲染所需要的图元数据。

3.体绘制管线

体绘制管线的渲染管线与几何渲染管线基本一致,下面的实例:

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2); //错误:no override found for 'vtkRayCastImageDisplayHelper'.
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkInteractionStyle);


#include <vtkSmartPointer.h>
#include <vtkStructuredPoints.h>
#include <vtkStructuredPointsReader.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVolumeProperty.h>
#include <vtkAxesActor.h>
#include <vtkOrientationMarkerWidget.h>

int main(int argc, char* argv[])
{
    
	vtkSmartPointer<vtkStructuredPointsReader> reader =
		vtkSmartPointer<vtkStructuredPointsReader>::New();
	reader->SetFileName("data/mummy.128.vtk");
	reader->Update();


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

	//设置光线采样距离
	//volumeMapper->SetSampleDistance(volumeMapper->GetSampleDistance()*4);
	//设置图像采样步长
	//volumeMapper->SetAutoAdjustSampleDistances(0);
	//volumeMapper->SetImageSampleDistance(4);
	/*************************************************************************/
	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); //设置不透明度传输函数
	//compositeOpacity->AddPoint(120,  0.00);//测试隐藏部分数据,对比不同的设置
	//compositeOpacity->AddPoint(180,  0.60);
	//volumeProperty->SetScalarOpacity(compositeOpacity);
	//设置梯度不透明属性
	vtkSmartPointer<vtkPiecewiseFunction> volumeGradientOpacity =
		vtkSmartPointer<vtkPiecewiseFunction>::New();
	volumeGradientOpacity->AddPoint(10, 0.0);
	volumeGradientOpacity->AddPoint(90, 0.5);
	volumeGradientOpacity->AddPoint(100, 1.0);
	volumeProperty->SetGradientOpacity(volumeGradientOpacity);//设置梯度不透明度效果对比
	//设置颜色属性
	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(0, 1, 0);
	ren->AddVolume(volume);

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

	vtkSmartPointer<vtkRenderWindowInteractor> rwi =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	rwi->SetRenderWindow(rw);
	/********************************************************************************/
	//vtkSmartPointer<vtkAxesActor> axes = vtkSmartPointer<vtkAxesActor>::New();
	//axes->SetScale(10);
	//vtkSmartPointer<vtkOrientationMarkerWidget> widget =
	//	vtkSmartPointer<vtkOrientationMarkerWidget>::New();
	//widget->SetOutlineColor(1, 1, 1);
	//widget->SetViewport(0, 0, 0.2, 0.2);
	//widget->SetOrientationMarker(axes);
	//widget->SetInteractor(rwi);
	//widget->SetEnabled(1);
	//widget->InteractiveOn();

	ren->ResetCamera();
	rw->Render();
	rwi->Start();

	return 0;
}

在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_45306991/article/details/124740881

智能推荐

python find() 和 index() 方法_python find index-程序员宅基地

文章浏览阅读3.8w次,点赞12次,收藏48次。1 find() 方法 字符串方法str.find(str, beg=0, end=len(string))检测字符串中是否包含子字符串 str ,如果指定 beg(开始) 和 end(结束) 范围,则检查是否包含在指定范围内,如果指定范围内如果包含指定索引值,返回的是索引值在字符串中的起始位置。如果不包含索引值,返回-1。a = 'Hello,World'print(a.fi..._python find index

跟Android初学者分享几点经验:该如何自学Android开发?-程序员宅基地

文章浏览阅读656次,点赞22次,收藏26次。很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从哪里入手去学习,对此我整理了一些资料如果你熟练掌握以下列出的知识点,相信将会大大增加你通过前两轮技术面试的几率!这些内容都供大家参考,互相学习。①「Android面试真题解析大全」PDF完整高清版+②「Android面试知识体系」学习思维导图压缩包一个人可以走的很快,但一群人才能走的更远。

Seaborn:一个样式更好看的Python数据可视化库_seaborn库-程序员宅基地

文章浏览阅读1.6k次,点赞48次,收藏23次。Seaborn 是一个基于 Matplotlib 的 Python 数据可视化库,它提供了更高级别的界面和更优雅的默认样式,使得用户能够更轻松地创建各种各样的统计图形。Seaborn 的全名是 “Statistical Data Visualization”,它的目标是使数据可视化更加简单、直观和有效。高度易用:Seaborn 提供了一组高级 API,使得用户可以轻松地创建各种统计图形,而无需关心底层的实现细节。美观的默认样式:Seaborn 提供了一套美观的默认样式,使得生成的图形更具视觉吸引力。_seaborn库

前端代码复用学习笔记:整洁架构与清晰架构_后端复用前端代码-程序员宅基地

文章浏览阅读1.3k次。UI 设计师的最终产出由少部分 视觉要素约定 +设计师个人 主观设计倾向 决定,也就是说,设计师的心情好坏和人员更替会直接影响每次产出设计稿的呈现,这对设计师来说很正常,但对前端工程师来说是致命的基于此,我们需要在工具上。_后端复用前端代码

grib中数据读取并导出到文本文件中_grib格式转换成txt-程序员宅基地

文章浏览阅读1.1w次。最近忙着赶项目加上家里的事比较多,就没有来得及更新博客,今天主要讲解一下grib数据的查看方法和读取方法。grib数据没有找到好的可视化工具打开它,官网提供的一个可视化工具叫Metview,此工具的安装过程相当的复杂,搞了将近3个小时最后还是没有安装成功,由于项目比较紧就果断的先放弃啦。这种方法不行,还可以使用ecCodes提供的自带命令行方式把grib数据中的一条一条的消息导出到一个.txt文件..._grib格式转换成txt

QT常用编码转换_qt字符编码转换-程序员宅基地

文章浏览阅读381次。【代码】QT常用编码转换。_qt字符编码转换

随便推点

计算机导论各章节总结,计算机导论第十三周课后总结(示例代码)-程序员宅基地

文章浏览阅读199次。一.计算机网络定义:将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,实现资源共享和信息传递的计算机系统。网络分类:(1) 按网络的地理覆盖范围可分为局域网,城域网和广域网。(2)按照网络传输媒体划分可分为有线网和无线网3.计算机网络的硬件组成(1) 网络传输媒体:双绞线、同轴电缆,光纤及无线通信等。局部使用双绞线、同轴电缆,网速要求比较高的haul,使用光纤,..._计算机导论速成课笔记

Python replace()函数使用详解:字符串的艺术转换-程序员宅基地

文章浏览阅读745次,点赞31次,收藏13次。在本文中,我们将深入探讨Python中replace()函数的用法,探讨如何在字符串操作中灵活运用这一功能,使得字符串转换变得轻而易举。对于想要在Python中进行字符串替换的开发者来说,这将是一个极具价值的指南。替换方法优点缺点基本替换简单易懂,适用于一般场景无法限定替换次数限定替换次数可以精确控制替换的次数,灵活应用对于大规模替换可能略显繁琐链式替换代码简洁,逻辑清晰多次替换可能会降低代码的可读性通过本文的学习,我们深入了解了Python中replace()

PAT 甲级 1001(A+B Format)-程序员宅基地

文章浏览阅读81次。PAT 甲级 1001题目要求翻译代码思路题目要求Calculate a+b and output the sum in standard format – that is, the digits must be separated into groups of three by commas (unless there are less than four digits).Input Sp...

决策树后剪枝算法(一)代价复杂度剪枝CPP-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏36次。剪枝,是一个“用准确性换取简单性”的思想。它允许决策树对训练集过拟合,再通过删除对泛化精度无贡献的子分支,从而修剪出一颗较小的树。_代价复杂度剪枝

268道Go语言面试真题及详解+100例代码实例+DDD实践-程序员宅基地

文章浏览阅读1.2k次。Go最近动静挺大的,刚刚发布的1.18包含以下几大特性:1、泛型2、模糊测试(Fuzzing)3、工作空间(Workspaces)4、20% 性能提升:Apple M1、ARM64 和 PowerPC64 用户开心了!由于 Go 1.17 的寄存器 ABI 调用约定扩展到这些架构,Go 1.18 包括高达 20% 的 CPU 性能改进。没错,过往Go被诟病最多的泛型,现在..._go语言面试题

软考中级 软件设计师资料(考点分析+复习笔记+历年真题+电子版课本)_软件设计师中级资料-程序员宅基地

文章浏览阅读3.8w次,点赞755次,收藏1.2k次。软件设计师是软考中级职称,相比高级的难度而言,中级难度较低,每个人花些时间都能顺利通过的,考试分为上午的选择题和下午的综合题,这里跟大家分享一些自己备考时使用的资料和经验一、先对自己进行评估:因为每个人的知识点掌握情况和学校教学内容的不一致,这里以我个人情况进行说明,大家做个参考就行:大家先了解一下软件设计师的考纲:有些同学刚看到考纲会有一些迷茫,感觉很多东西都没学过,没关系,没关系,没学过的也没关系!大家要明白一点,软件设计师考察的内容广度比较高,也就是内容多、杂,但是深度很浅!,也就是没学过_软件设计师中级资料

推荐文章

热门文章

相关标签