赞
踩
很早就想写这么一篇比较全而且详细的博客,介绍一下体渲染的基础算法。这篇博客,能多长我就写多长,能多详细我就写多详细,争取把基础算法都介绍清楚。
那么现在我就开始逐步构建这个博客。
Table of Contents
吸收发射模型(Volume Rendering Equation)
通过模拟光线穿过体空间的过程,我们可以建模得到体渲染的光学方程。
而体渲染是采用“逆向光线”的方式,即射线从眼睛射出,然后进入体空间,在体空间中进行采样,得到最后的成像效果。
我们假设体空间中的每个元素都是在发光的,我们采样会不断的积累光能:
公式:
其中,I 表示积累的光能,在外界一开始的光能
这里的出口处,可以作为外界的初始光亮度。
光在通过物体时会被挡住(吸收),前面的微粒会挡住后面的微粒。
公式:
其中,
转化为积分形式:
也就是说,我们接收到的光源,就是初始光源
现在我们需要将这两个模型整合成一个既有发射又有吸收的模型,但是这个虽然看上去是简单地相加:
但是它的意义却变了:某位置的光能积累的变化率 = 当前位置微元发出的光亮度 减去 当前微元对已经积累的光亮度的阻挡衰减。
这个已经积累的光亮度 I(s) ,就是不断的积累体素发射的光,然后又被前面的粒子阻挡衰减得到的。
变成积分形式:
方程等号后面的左边部分就是初始光亮度不断衰减的过程,右边我们解释一下:
表示的是当前位置 p 微元发射的光能,在经历了前面微粒(p->s)的阻挡衰减以后在 s 位置的值,再对其进行积分,也就是从 s0 位置开始进行采样,采样路线中的所有微粒之间的相互作用(发光增强,阻挡衰减)之后的结果。
衰减的离散化:
吸收发射模型的离散化:
我们在离散公式中只使用三个小段来找规律:
但是这里默认的颜色是已经预乘了当前体素的不透明度的,如果没有预乘,则需要:
其实就是alpha混合。
我们一般就是从前向后积分(混合):
同理,这里的C(i)也需要预乘不透明度。
离散化的不透明度和颜色贡献需要相应地修改,因为它们的值取决于采样距离。
分解成离散和形式后,第 i 段的透明度:
注意这个值是一定小于1的。
第 i 段的颜色值:
我们注意到:
所以
所以
因为颜色的近似公式比较容易:
所以
当然这个 因为并不一定是一个确定量(很多时候都是我们在传输函数里自己设置的),我们可以一开始定一个初始采样距离,然后当采样距离变化时注意修改不透明度项。(因为颜色项与距离的关系是线性的,所以只需要乘不同的采样步长就好了)。很多人都使用的体渲染程序是这样:
- //color表示总的颜色值(x,y,z)和不透明度(w)
- color.x = color.x + stepSize*color_temp.x*color_temp.w*(1-color.w)
- color.y = color.y + stepSize*color_temp.y*color_temp.w*(1-color.w)
- color.z = color.z + stepSize*color_temp.z*color_temp.w*(1-color.w)
- color.w = color.w + stepSize*color_temp.w*(1-color.w)
颜色在这里没有什么问题,主要就是color.w的值,最好要矫正一下,首先设置一个初始步长下的不透明度,然后根据上面所述的方法去求变换步长以后的不透明度。
Visual Computing for Medicine: Theory, Algorithms, and Applications: Second Edition
Real-Time Volume Graphics
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。