赞
踩
一.Ray-Cast算法
1.※基于CPU编程时,往往不使用体纹理而是使用图像序列(可以理解为切片数据);在基于GPU 的着色程序中,必须使用体纹理。
2.光线投影法的优点是能够比较精确地模拟原始体数据,但计算量较大,实时体绘制对计算机硬件的要求比较高。
3.vtkVolumeRayCastMapper采用软件方法来实现光线投影算法,精度高但是计算量比较大,因此渲染速度相对比较慢。
该类内部实现了两个非常重要的函数:
•vtkVolumeRayCastMapper::SetInput(vtkImageData*):该函数用于设置输入图像数据;
•vtkVolumeRayCastMapper::SetVolumeRayCastFunction(vtkVolumeRayCastFunction*):该类用于设置光线投射函数。
4.插值优先是指对投射光线进行采样,计算采样点的颜色值时,先通过插值方式计算该采样点的标量值(灰度值),然后再根据颜色传输函数和不透明度传输函数计算该点的颜色值和不透明度 。 分类优先是指在计算采样点时,先根据颜色传输函数和不透明度传输函数计算包含该采样点的立方体的8个顶点颜色值和不透明度,然后通过插值方法获取当前采样点的颜色值与不透明度 。
从显示效果上来说,插值优先具有较好的显示效果,但在一些情况下也会存在问题。
5.光线投影体绘制中,投影光线上的采样点的步长是一个重要参数,决定了体绘制的精度和速度(
等值面绘制函数不需要进行采样,而其他另个绘制函数都需要进行采样。)
Void SetSampleDistance(float);
6.默认情况下,图像采样间距为1,即每个像素对应一条投影光线;如果设为0.5,那么每个像素对应4条投射光线;如果设置为2,则每四个像素对应一条投影光线。设置图像采样距离的函数:
voidSetImageSampleDistance(float);
需要格外注意的是,当使用这个函数的时候,必须先关闭自动调节采样距离功能,代码如下:
SetAutoAdjustSampleDistance(0); //关闭自动调整采样
默认的情况下,该函数的功能是开启的,以保证在图像旋转等交互时,能够自动调整采样距离保证实时性。如果关闭此功能,在旋转图像等交互过程中,体绘制渲染过程会变得很慢。
8.光线投射法用于非真实感渲染;光线跟踪法用于真实感渲染
<光学中的吸收模型>
•几乎每一个直接体绘制算法都将体数据当作“ 在某一密度条件下,光线穿越体时,每个体素对光线的吸收发射
的分布情况” 。这一思想来源于物理光学,并最终通过光学模型(Optical Models )进行分类描述。
•大多数在直接体绘制算法中使用的重要光学模型进行了描述,这里给出简要概述。
1.吸收模型(Absorption only ):将体数据当作由冷、黑的体素组成,这些体素对光线只是吸收,本身既不发射光线,也不反射、透射光线;
2.发射模型(Emission only ):体数据中的体素只是发射光线,不吸收光线;
3. 吸收和发射模型(Absorption plus emission ):这种光学模型使用最为广泛,体数据中的体素本身发射光线,并且可以吸收光线,但不对光线进行反射和透射。
4. 散射和阴影模型(Scattering and Shading/shadowing ):体素可以散射(反射和折射)外部光源的光线,并且由于体素之间的遮挡关系,可以产生阴影;
5. 多散射模型(Multiple Scattering ):光线在被眼睛观察之前,可以被多个体素散射。
通常我们使用吸收和发射模型(Absorption plus emission ),为了增强真实感,也可以加上阴影(包括自阴影)计算。
【光学吸收模型】
光线打到粒子上,被粒子遮挡(→吸收)的效果→不透明度
体绘制处理的是海量的数据,如何提高效率是难题。体绘制的加速技术可以分为:软件加速和硬件加速。
•软件加速技术有提前光线终止(early ray termination)、空间跳跃(empty space leaping)和延迟渲染(deferred shading)等。这里,空间跳跃的实现,需要对三维数据场进行数据结构管理,如八叉树、二叉树和k-d树,类似于场景管理技术。
•硬件加速技术有并行实现、专用硬件实现和GPU加速。其实说GPU加速也欠妥,因为这个概念是NVIDIA在1999年才提出来的。
<算法细节>
1. 光线如何穿越体纹理?
※体纹理并不是空间的模型数据,他只是描述了三维的数据(类似于编程时候用一维数组存储二维数组、三维数
组的思想)。
※空间体模型(通常是规则的立方体或圆柱体)和体纹理相互结合才能进行体渲染。比如二维的纹理贴图效果。也就是说,我们想要看到体纹理数据,在体绘制中需要一个三维模型作为体纹理的载体,体纹理通过纹理坐标(三维)和模型进行对应,然后由视点向模型上的点引射线,该射线穿越模型空间等价于射线穿越了体纹理。通常使用普通的立方体或者圆柱体作为体绘制的空间模型。
※体纹理通过纹理坐标和三维模型进行对应。
图44展示了体纹理坐标在立方体上的分布,这种分布关系是基于OpenGL 的。在宿主程序中确定立方体8 个顶点的体纹理坐标,注意是三元向量,然后传入GPU ,立方体6 个面内部点的体纹理坐标会在GPU 上自动插值得到。根据视点和立方体表面点可以唯一确定一条射线,射线穿越整个立方体等价于穿越体数据,并在穿越过程中对体数据等距采样,对每次得到的采样数据按照光透公式进行反复累加。(图中立方体每个点颜色代表了其坐标,左图是正面,右图是背面)
2. 透明度、图像合成
透明度本质上代表着光穿透物体的能力,光穿透一个物体会导致波长比例的变化,如果穿越多个物体,则这种变化是累加的。所以,透明物体的渲染,本质上是将透明物体的颜色和其后物体的颜色进行混合,这被称为 alpha 混合技术。
(Alpha,Red,Green,Blue):32位色中的24位用来保存颜色信息(R8、G8、B8),另外的8位用来保存ALPHA信息,
ALPHA属性就是透明度。
【Alpha-图像通道】——如果图形卡具有32位总线,附加的8位信号就被用来保存不可见的透明度信号以方便处理用,这就是Alpha通道。白色的alpha像素用以定义不透明的彩色象素,而黑色的alpha象素用以定义透明象素,黑
白之间的灰阶用来定义半透明象素
【Alpha混合】指的是给定两个点P1、P2,其RGB颜色分量分别为(r1,g1,b1)和(r2,g2,b2),假定P1位于P2的后面,
P2的透明度为a(0%<a<100%),计算透过点P2看到P1的颜色值。假定该值为P3(r3,g3,b3),其计算公式如下:
r3=(1-a)*r2+a*r1=r2+a*(r1-r2);(优化了一下,减少了一次乘法)
g3=(1-a)*g2+a*g1=g2+a*(g1-g2);
b3=(1-a)*b2+a*b1=b2+a*(b1-b2);
※如果有多个透明物体,通常需要对物体进行排序。在光线投射算法中,射线穿越体纹理的同时也就是透明度的
排序过程,这里存在一个合成的顺序问题。将射线穿越纹理的过程作为采样合成过程,
•如果从前面到背面进行采样合成,则合成公式为:
其中,ci 和 Ai分别是在体纹理上采样所得到的颜色值和不透明度,也就是体素中蕴含的数据 和 表示累加的颜色值和不透明度。很多体纹理数据其实并没有包含透明度,所以需要定义一个初始透明度,然后进行累加。
•如果从背面到前面进行采样合成,则公式为:
3. 采样过程
假定光线从F点投射到立方体中,并从L点投出,在立方体中穿越的距离为m。当光线从F点投射到立方体中,穿
越距离为n(n<m)时进行采样,则存在公式:
,其中tstart 表示立方体表面被投射点的体纹理坐标,d表示投射方向, delta表示采样间隔,随着n的增加而递增, t为求得的采样纹理坐标。通过求得的采样纹理坐标 就可以在体纹理上查询体素数据。直到n>m或者透明度累加超过1(透明度为1时不透明),一条射线的采样过程结束。
•首先需要一个确定了顶点纹理坐标的三维立方体,光线穿越立方体的过程就是穿越体纹理的过程,在整个穿越过程中,计算采样体纹理坐标,并进行体纹理采样,这个采样过程直到光线投出立方体或者累加的透明度为 1时结束。
•纹理坐标是联系三维模型和体纹理数据之间的桥梁,通过计算光线穿越三维模型,可以计算体纹理在光线穿越方向上的变化。
♥在使用openGL的场景中,有世界坐标,局部坐标,纹理坐标,和屏幕坐标几种。
4.如何判断采样结束?——如何判断光线投射出体纹理,可以转换为判断光线投射出立方体。
•CPU:容易求出光线和几何体的两个交点坐标,计算欧氏距离进行判断。
•GPU 计算光线和几何体的交点是个难题,尤其在几何体不规则的情况下。在GPU 中可以间接反应点和点之间关系的有两个量,一个是纹理坐标,另一个就是深度值。
【计算采样距离的方法如下】
1.剔除深度值较大的片段(正常的渲染状态),渲染场景深度图frontDepth,此时frontDepth 上的每个像素的颜色值都代表【某个方向上离视点最近的点的距离】;
2.剔除深度值较小的片段,渲染场景深度图backDepth ,backDepth 上的每个像素的颜色值都代表【某个方向上离视点最远的点的距离】;
3.将两张深度图上的数据进行相减,得到的值就是光线投射距离 。每一次循环都要计算新的采样纹理坐标和采样距离,然后进行颜色合成和透明度累加,如果采样距离超过了最大穿越距离,或者透明度累加到1 ,则循环结束,将合成得到的颜色值输出即可。
【深度测试】
※从观察者视角出发,越近的物体深度越小;越远的物体深度越大。
深度缓冲区(Detph buffer)和颜色缓冲区(color buffer)是对应的,颜色缓冲区存储的像素的颜色信息,而深度缓冲区存储像素的深度信息。在决定是否绘制一个物体的表面时,首先将表面对应像素的深度值与当前深度缓冲区中的值进行比较,如果大于等于深度缓冲区中值,则丢弃这部分;否则利用这个像素对应的深度值和颜色值,更新深度缓冲区和颜色缓冲区。这一过程称之为深度测试(Depth Testing)。在OpenGL中执行深度测试时,我们可以根据需要指定深度值的比较函数。
【透视和Zbuffer】
解决隐藏面消除的问题(位于背后的物体不可见)
5.重采样
光线与体数据前后两个平面的交点之间可以获取等距的K个采样点,但一般情况下,有些采样点并不处在体数据中已知的网格体素上,如图所示,为了得到这些点的信息,需要对其周围的已知点运用线性插值的方法进行重采样,以得到该点对应的颜色值和不透明度值。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。