体积渲染:关于前向混合的困惑

9
例如,在GPU Gems的前向到后向混合方程(用于颜色)中,公式如下:
C'i = (1 - A'i-1)Ci + C'i-1 其中,C'i是输出的累积颜色值;A'i-1是截至前一个体素的累积透明度值;Ci是当前体素的颜色值;C'i-1是截至前一个体素的累积颜色值。
这个公式引发了我两个问题:
  1. 前向到后向的终止发生在累积透明度达到大约1时。那么,当颜色通道(RGB)超过最大值但透明度限制未达到时该怎么办?将值夹在0..255之间(例如500,1000,2000将变为255,255,255),还是考虑通道之间的比率(例如500,1000,2000将变为64,128,255)?

  2. 对于前一个问题的答案可能会影响这个问题。当前体素的颜色输出取决于1减去累积透明度。如果累积透明度为零并且当前体素的透明度也为零怎么办? - 输出是一个完全不透明的体素,因为(1-A'i-1)=1,尽管它本应是一个透明的体素!?

非常感谢任何提示。

公式是递归的,你怎么得到A'_0和C'_0? - Eugeny89
@Eugeny89:好问题!我不知道,也找不到任何参考资料告诉我!我假设两者都是0(即透明黑)。 - Dave
知道颜色是否(或应该)由 Alpha 预乘可能很重要。如果预乘,则它们不应该在不透明度达到最大值之前达到最大值。 - Adrian McCarthy
@Adrian:啊,这很有趣。我发现如果把当前体素的不透明度乘以1减去累积不透明度,事情就开始变得有意义了。但是,我找到的所有文档都没有这样做。 - Dave
1
通常情况下,您会从A(0)=0和C(0)=0开始。我知道另一个参考文献,它将方程式表示为C'(i)=(1-A'(i-1))*C(i)*A(i)+C'(i-1),这将是非预乘alpha版本。我发现非预乘版本更直观;它仅表示材料存在时才会有多少体素颜色渗入光线中。 - timday
3个回答

1
  1. A和C应该在0-1的范围内。(如果您使用无符号字节作为表示,除以255.0,但请注意,对于某些体渲染应用领域,这将使您对小alpha/低不透明度区域的控制不足以令人满意。现在通常更容易从一开始就使用浮点数进行计算)。事实证明,使用您的公式,alpha和颜色值永远不会超出此范围。

  2. 射线alpha A'的序列是A'(i) = (1-A'(i-1)).A(i) + A'(i-1) (其中A(i)是体素alpha),因此如果您的累积射线从A'零开始,并通过一个透明(零A)体素,则射线现在具有A' = (1-0)*0+0,仍然是零,如预期。


谢谢你的回答,大部分问题都解决了。但是关于第二点:从你的回答中看来,似乎是在颜色之前累加alpha,然后在计算当前体素的颜色贡献时使用A'(i)而不是A'(i-1)? - Dave
抱歉...不明白你的意思。对于上面的'2'表达式,我会使用C'(i)=(1-A'(i-1))*C(i)*A(i)+C'(i-1)(请参见您问题中的注释),所以我不知道A'(i)在哪里? "'"-带撇号的量是射线积分,未带撇号的A和C是来自体数据集的体素值。 - timday
啊,我想我误读了你的回答(把A'读成C')。那么,我的理解是,如果假设预乘alpha,则我原来问题中的公式才有效?我很确定GPU Gems中没有提到这一点,这太苛刻了。 - Dave

0

在使用过程中,A和C应该在0和1之间。请使用预乘阿尔法通道来避免溢出问题。


你所说的预乘alpha是什么意思?是指在进行合成之前将所有体素与其相应的alpha值相乘吗?这相当于timday的评论,将方程式表示为:C'(i)=(1-A'(i-1))*C(i)*A(i)+C'(i-1)。 - Dave
2
是的,基本上是这样。从传统的4通道颜色格式(C)转换为预乘alpha(C'):C'_rgb = C_rgb * C_aC'_a = C_a - tkerwin

0
嗯,假设C和A都在0到1之间。可以看到序列 C'(i) = [1 - A'_(i+1)]C(i) + C'(i-1) 随着 i 的增长而增长。我认为C不是颜色(RGB或其他模型的颜色)。也许它是某个体素的“灰度”。即如果体素在其前面有许多体素,则应该比顶部的体素更灰。
所以我的假设是C_i并不直接描述颜色。它告诉我们如何使某些体素的颜色更加灰暗。
对于我的英语拙劣,请原谅,并随时提出问题,如果有什么不清楚的地方。
顺便说一下:如果你相信我,C_0(顶部体素的灰度)应该是1,而A_0应该是0。

我相信您可以将RGB的每个颜色通道分别处理,就像同时处理多个灰度级别一样,然后组合成最终的颜色...? - Dave

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接