Real-Time Rendering——6.6 Alpha Mapping透明度映射

The alpha value can be employed for many effects using alpha blending or alpha testing, such as efficiently rendering foliage, explosions, and distant objects, to name but a few. This section discusses the use of textures with alphas, noting various limitations and solutions along the way.

使用alpha混合或alpha测试,alpha值可以用于许多效果,例如有效地渲染树叶、爆炸和远处的对象,等等。本节讨论了纹理在alphas中的使用,指出了各种限制和解决方案。

One texture-related effect is decaling. As an example, say you wish to put a picture of a flower on a teapot. You do not want the whole picture, but just the parts where the flower is present. By assigning an alpha of 0 to a texel, you make it transparent,so that it has no effect. So, by properly setting the decal texture’s alpha, you can replace or blend the underlying surface with the decal. Typically, a clamp corresponder function is used with a transparent border to apply a single copy of the decal (versus a repeating texture) to the surface. An example of how decaling can be implemented is visualized in Figure 6.26. See Section 20.2 for more information about decals.

一种与纹理相关的效果是贴花。例如,假设您希望在茶壶上放一幅花的图片。你不需要整个画面,只需要花出现的部分。通过给一个纹理元素指定一个0的alpha值,你可以使它透明,这样它就没有效果了。因此,通过正确设置贴花纹理的alpha,可以用贴花替换或混合基础曲面。通常,夹钳对应器功能与透明边框一起使用,将贴花的单个副本(相对于重复纹理)应用到表面。图6.26给出了一个如何实施贴花的例子。有关贴花的更多信息,请参见第20.2节。

Figure 6.26. One way to implement decals. The framebuffer is first rendered with a scene, and then a box is rendered and for all points that are inside the box, the decal texture is projected to the framebuffer contents. The leftmost texel is fully transparent so it does not affect the framebuffer.The yellow texel is not visible since it would be projected onto a hidden part of the surface. 

图6.26。实现贴花的一种方法。首先用场景渲染帧缓冲区,然后渲染一个框,对于框内的所有点,贴图纹理被投影到帧缓冲区内容。最左边的纹理元素是完全透明的,所以它不会影响帧缓冲区。黄色纹理元素不可见,因为它会被投影到表面的隐藏部分。

A similar application of alpha is in making cutouts. Say you make a decal image of a bush and apply it to a rectangle in the scene. The principle is the same as for decals, except that instead of being flush with an underlying surface, the bush will be drawn on top of whatever geometry is behind it. In this way, using a single rectangle you can render an object with a complex silhouette.

alpha的一个类似应用是制作剪纸。假设您制作了一个灌木的贴花图像,并将其应用于场景中的一个矩形。原理与贴花相同,除了不是与基础表面齐平,而是将灌木绘制在它后面的任何几何体的顶部。这样,使用单个矩形,您可以渲染具有复杂轮廓的对象。

In the case of the bush, if you rotate the viewer around it, the illusion fails, since the bush has no thickness. One answer is to copy this bush rectangle and rotate it 90 degrees along the trunk. The two rectangles form an inexpensive three-dimensional bush, sometimes called a “cross tree” [1204], and the illusion is fairly effective when viewed from ground level. See Figure 6.27. Pelzer [1367] discusses a similar configuration using three cutouts to represent grass. In Section 13.6, we discuss a method called billboarding, which is used to reduce such rendering to a single rectangle. If the viewer moves above ground level, the illusion breaks down as the bush is seen from above to be two cutouts. See Figure 6.28. To combat this, more cutouts can be added in different ways—slices, branches, layers—to provide a more convincing model. Section 13.6.5 discusses one approach for generating such models; Figure 19.31 on page 857 shows another. See the images on pages 2 and 1049 for examples of final results.

在灌木的例子中,如果你绕着它旋转观察器,幻觉就失效了,因为灌木没有厚度。一个答案是复制这个灌木矩形,沿着树干旋转90度。这两个矩形形成了一个便宜的三维灌木丛,有时被称为“十字树”[1204],当从地面上看时,这种错觉相当有效。参见图6.27。Pelzer [1367]讨论了一个类似的配置,使用三个剪切块来代表草。在13.6节中,我们将讨论一种叫做布告板的方法,这种方法用于将这种渲染减少到一个矩形。如果观众移动到地面以上,这种错觉就会消失,因为从上面看去,灌木丛是两个剪影。参见图6.28。为了解决这个问题,可以用不同的方式添加更多的剪切块——切片、分支、分层——以提供一个更有说服力的模型。第13.6.5节讨论了生成这种模型的一种方法;图19.31显示了另一种情况。有关最终结果的示例,请参见第2页和第1049页的图像。

Figure 6.28. Looking at the “cross-tree” bush from a bit off ground level, then further up, where the illusion breaks down. 

图6.28。从离地面一点的地方看“十字树”灌木丛,然后再往上看,幻觉就在这里消失了。

Combining alpha maps and texture animation can produce convincing special effects,such as flickering torches, plant growth, explosions, and atmospheric effects.

结合alpha贴图和纹理动画可以产生令人信服的特效, 例如闪烁的火把、植物生长、爆炸和大气效果。

There are several options for rendering objects with alpha maps. Alpha blending (Section 5.5) allows for fractional transparency values, which enables antialiasing the object edges, as well as partially transparent objects. However, alpha blending requires rendering the blended triangles after the opaque ones, and in back-to-front order. A simple cross-tree is an example of two cutout textures where no rendering order is correct, since each quadrilateral is in front of a part of the other. Even when it is theoretically possible to sort and get the correct order, it is usually inefficient to do so. For example, a field may have tens of thousands of blades of grass represented by cutouts.Each mesh object may be made of many individual blades. Explicitly sorting each blade is wildly impractical.

使用alpha贴图渲染对象有几个选项。阿尔法混合(第5.5节)允许分数透明度值,这使得对象边缘抗锯齿,以及部分透明的对象。但是,alpha混合需要在不透明三角形之后渲染混合的三角形,并且是从后向前的顺序。一个简单的交叉树是两个剪切纹理的例子,其中没有渲染顺序是正确的,因为每个四边形在另一个的一部分之前。即使理论上可以排序并得到正确的顺序,这样做通常也是低效的。例如,一个领域可能有成千上万的草叶表示的剪切。每个网格对象可以由许多单独的叶片组成。明确地对每个刀片进行分类是非常不切实际的。

This problem can be ameliorated in several different ways when rendering. One is to use alpha testing, which is the process of conditionally discarding fragments with alpha values below a given threshold in the pixel shader. This is done as

在渲染时,这个问题可以通过几种不同的方式得到改善。一种是使用alpha测试,这是在像素着色器中有条件地丢弃alpha值低于给定阈值的片段的过程。这是作为

where texture.a is the alpha value from the texture lookup, and the parameter alphaThreshold is a user-supplied threshold value that determines which fragments will get discarded. This binary visibility test enables triangles to be rendered in any order because transparent fragments are discarded. We normally want to do this for any fragment with an alpha of 0.0. Discarding fully transparent fragments has the additional benefit of saving further shader processing and costs for merging, as well as avoiding incorrectly marking pixels in the z-buffer as visible [394]. For cutouts we often set the threshold value higher than 0.0, say, 0.5 or higher, and take the further step of then ignoring the alpha value altogether, not using it for blending. Doing so avoids out-of-order artifacts. However, the quality is low because only two levels of transparency (fully opaque and fully transparent) are available. Another solution is to perform two passes for each model—one for solid cutouts, which are written to the z-buffer, and the other for semitransparent samples, which are not. 

其中texture.a是来自纹理查找的alpha值,参数alphaThreshold是用户提供的阈值,用于确定哪些片段将被丢弃。这种二进制可见性测试使三角形能够以任何顺序呈现,因为透明片段被丢弃了。我们通常希望对任何alpha值为0.0的片段都这样做。丢弃完全透明的片段具有节省进一步着色器处理和用于合并的成本的额外好处,以及避免错误地将z缓冲器中的像素标记为可见[394]。对于剪切,我们通常将阈值设置为高于0.0,比如0.5或更高,然后进一步忽略alpha值,不使用它进行混合。这样做可以避免无序的伪像。但是,质量很低,因为只有两个级别的透明度(完全不透明和完全透明)可用。另一种解决方案是对每个模型执行两次扫描,一次是对实心剪切块,写入z缓冲区,另一次是对半透明样本,不写入z缓冲区。

There are two other problems with alpha testing, namely too much magnification [1374] and too much minification [234, 557]. When alpha testing is used with mipmapping, the effect can be unconvincing if not handled differently. An example is shown in the top of Figure 6.29, where the leaves of the trees have become more transparent than intended. This can be explained with an example. Assume we have a one-dimensional texture with four alpha values, namely, (0.0, 1.0, 1.0, 0.0). With averaging, the next mipmap level becomes (0.5, 0.5), and then the top level is (0.5).Now, assume we use αt = 0.75. When accessing mipmap level 0, one can show that 1.5 texels out of 4 will survive the discard test. However, when accessing the next two levels, everything will be discarded since 0.5 < 0.75. See Figure 6.30 for another example.

阿尔法测试还有另外两个问题,即放大倍数太大[1374]和缩小倍数太大[234,557]。当alpha测试与mipmapping一起使用时,如果不进行不同的处理,效果可能无法令人信服。图6.29的顶部显示了一个例子,树叶变得比预期的更加透明。这可以用一个例子来说明。假设我们有一个一维纹理,有四个alpha值,即(0.0,1.0,1.0,0.0)。通过平均,下一个mipmap级别变为(0.5,0.5),然后最高级别为(0.5)。现在,假设我们使用αt = 0.75。当访问小中见大贴图级别0时,可以显示4个纹理像素中的1.5个将通过丢弃测试。但是,当访问下两个级别时,从0.5 < 0.75开始,所有内容都将被丢弃。另一个例子见图6.30。

Figure 6.29. Top: alpha testing with mipmapping without any correction. Bottom: alpha testing with alpha values rescaled according to coverage. (Images from “The Witness,” courtesy of Ignacio Casta˜no.) 

图6.29。上图:使用无任何修正的mipmapping进行alpha测试。下图:alpha测试,alpha值根据覆盖率重新调整。(图片来自《目击者》,由Ignacio Casta˜ no提供。)

Figure 6.30. On the top are the different mipmap levels for a leaf pattern with blending, with the higher levels zoomed for visibility. On the bottom the mipmap is displayed as it would be treated with an alpha test of 0.5, showing how the object has fewer pixels as it recedes. (Images courtesy of Ben Golus [557].) 

图6.30。顶部是具有混合的叶图案的不同mipmap级别,较高的级别被缩放以获得可见性。在底部,显示的是使用alpha测试0.5处理的小中见大贴图,显示的是对象后退时像素减少的情况。(图片由本·戈卢斯[557]提供。)

Casta˜no [234] presents a simple solution done during mipmap creation that works well. For mipmap level k, the coverage ck is defined as

casta no[234]提出了一个在创建mipmap期间完成的简单解决方案,效果很好。对于mipmap级别k,覆盖率ck定义为

where nk is the number of texels in mipmap level k, α(k, i) is the alpha value from mipmap level k at pixel i, and αt is the user-supplied alpha threshold in Equation 6.9.Here, we assume that the result of α(k, i) > αt is 1 if it is true, and 0 otherwise.Note that k = 0 indicates the lowest mipmap level, i.e., the original image. For each mipmap level, we then find a new mipmap threshold value αk, instead of using αt,such that ck is equal to c0 (or as close as possible). This can be done using a binary search.Finally, the alpha values of all texels in mipmap level k are scaled by αt/αk.This method was used in the bottom part of Figure 6.29, and there is support for this in NVIDIA’s texture tools. Golus [557] gives a variant where the mipmap is not modified, but instead the alpha is scaled up in the shader as the mipmap level increases. 

其中nk是小中见大贴图层k中纹理像素的数量,α(k,I)是来自像素I处的小中见大贴图层k的α值,而αt是等式6.9中用户提供的α阈值。注意,k = 0表示最低的小中见大贴图级别,即原始图像。对于每个小中见大贴图级别,我们然后找到新的小中见大贴图阈值αk,而不是使用αt,使得ck等于c0(或尽可能接近)。这可以使用二分搜索法来完成。最后,使用αt/αk缩放mipmap级别k中所有纹理元素的α值。这种方法用于图6.29的底部,NVIDIA的纹理工具中也支持这种方法。Golus [557]给出了一个变体,其中不修改小中见大贴图,而是随着小中见大贴图级别的增加,在着色器中放大alpha。

Wyman and McGuire [1933] present a different solution, where the line of code in Equation 6.9 is,in theory, replaced with

Wyman和McGuire [1933]提出了一个不同的解决方案,其中公式6.9中的代码行在理论上被替换为

The random function returns a uniform value in [0, 1], which means that on average this will result in the correct result. For example, if the alpha value of the texture lookup is 0.3, the fragment will be discarded with a 30% chance. This is a form of stochastic transparency with a single sample per pixel [423]. In practice, the random function is replaced with a hash function to avoid temporal and spatial high-frequency noise: 

random函数在[0,1]中返回一个统一的值,这意味着平均起来这将产生正确的结果。例如,如果纹理查找的alpha值为0.3,则该片段将有30%的几率被丢弃。这是一种随机透明的形式,每个像素一个样本[423]。在实践中,随机函数被替换为散列函数,以避免时间和空间高频噪声:

A three-dimensional hash is formed by nested calls to the above function, i.e., float hash3D(x,y,z) { return hash2D(hash2D(x,y),z); }, which returns a number in [0, 1). The input to the hash is object-space coordinates divided by the maximum screen-space derivatives (x and y) of the object-space coordinates, followed by clamping.Further care is needed to obtain stability for movements in the z-direction, and the method is best combined with temporal antialiasing techniques. This technique is faded in with distance, so that close up we do not get any stochastic effect at all. The advantage of this method is that every fragment is correct on average, while Casta˜no’s method [234] creates a single αk for each mipmap level. However, this value likely varies over each mipmap level, which may reduce quality and require artist intervention. 

通过对上述函数的嵌套调用形成一个三维hash,即float hash3D(x,y,z) { return hash2D(hash2D(x,y),z);},它返回[0,1]中的一个数字。散列的输入是对象空间坐标除以对象空间坐标的最大屏幕空间导数(x和y ),然后是箝位。需要进一步小心以获得z方向运动的稳定性,并且该方法最好与时间抗锯齿技术相结合。这种技术随着距离的增加而淡入,所以近看的话,我们根本看不到任何随机效果。这种方法的优点是每个片段平均都是正确的,而Casta˜ no的方法[234]为每个mipmap级别创建了一个单独的αk。然而,该值可能在每个mipmap级别上有所不同,这可能会降低质量并需要艺术家的干预。

Alpha testing displays ripple artifacts under magnification, which can be avoided by precomputing the alpha map as a distance field [580] (see also the discussion on page 677).

阿尔法测试显示放大倍数下的波纹伪影,这可以通过预先计算阿尔法图作为距离场来避免[580](参见677页的讨论)。

Alpha to coverage, and the similar feature transparency adaptive antialiasing, take the transparency value of the fragment and convert this into how many samples inside a pixel are covered [1250]. This idea is like screen-door transparency, described in Section 5.5, but at a subpixel level. Imagine that each pixel has four sample locations,and that a fragment covers a pixel, but is 25% transparent (75% opaque), due to the cutout texture. The alpha to coverage mode makes the fragment become fully opaque but has it cover only three of the four samples. This mode is useful for cutout textures for overlapping grassy fronds, for example [887, 1876]. Since each sample drawn is fully opaque, the closest frond will hide objects behind it in a consistent way along its edges. No sorting is needed to correctly blend semitransparent edge pixels,since alpha blending is turned off.

Alpha to coverage,以及类似的特征透明度自适应抗锯齿,获取片段的透明度值,并将其转换为一个像素内有多少样本被覆盖[1250]。这个想法就像5.5节中描述的纱门透明,但是是在子像素级别。假设每个像素有四个采样位置,并且一个片段覆盖了一个像素,但是由于剪切纹理,它是25%透明的(75%不透明的)。alpha to coverage模式使片段变得完全不透明,但只覆盖了四个样本中的三个。这种模式对于剪切重叠的草叶子的纹理很有用,例如[887,1876]。由于绘制的每个样本都是完全不透明的,最近的叶子会沿着边缘以一致的方式隐藏后面的对象。不需要排序来正确混合半透明的边缘像素,因为alpha混合已关闭。

Alpha to coverage is good for antialiasing alpha testing, but can show artifacts when alpha blending. For example, two alpha-blended fragments with the same alpha coverage percentage will use the same subpixel pattern, meaning that one fragment will entirely cover the other instead of blending with it. Golus [557] discusses using the fwidth() shader instruction to give content a crisper edge. See Figure 6.31.

Alpha to coverage适用于抗锯齿Alpha测试,但在alpha混合时可能会显示伪像。例如,具有相同alpha覆盖百分比的两个alpha混合片段将使用相同的子像素图案,这意味着一个片段将完全覆盖另一个片段,而不是与之混合。Golus [557]讨论了使用fwidth()着色器指令来赋予内容更清晰的边缘。参见图6.31。

Figure 6.31. Different rendering techniques of leaf textures with partial alpha coverage for the edges.From left to right: alpha test, alpha blend, alpha to coverage, and alpha to coverage with sharpened edges. (Images courtesy of Ben Golus [557].) 

图6.31。边缘部分alpha覆盖的树叶纹理的不同渲染技术。从左到右:alpha测试、alpha混合、alpha到覆盖和alpha到带有锐化边缘的覆盖。(图片由本·戈卢斯[557]提供。)

For any use of alpha mapping, it is important to understand how bilinear interpolation affects the color values. Imagine two texels neighboring each other:rgbα = (255, 0, 0, 255) is a solid red, and its neighbor, rgbα = (0, 0, 0, 2), is black and almost entirely transparent. What is the rgbα for a location exactly midway between the two texels? Simple interpolation gives (127, 0, 0, 128), with the resulting rgb value alone a “dimmer” red. However, this result is not actually dimmer, it is a full red that has been premultiplied by its alpha. If you interpolate alpha values, for correct interpolation you need to ensure that the colors being interpolated are already premultiplied by alpha before interpolation. As an example, imagine the almost-transparent neighbor is instead set to rgbα = (0, 255, 0, 2), giving a minuscule tinge of green. This color is not premultiplied by alpha and would give the result (127, 127, 0, 128) when interpolated—the tiny tinge of green suddenly shifts the result to be a (premultiplied) yellow sample. The premultiplied version of this neighbor texel is (0, 2, 0, 2), which gives the proper premultiplied result of (127, 1, 0, 128). This result makes more sense,with the resulting premultiplied color being mostly red with an imperceptible tinge of green.

对于任何alpha贴图的使用,理解双线性插值如何影响颜色值是很重要的。想象两个彼此相邻的纹理元素:rgbα = (255,0,0,255)是纯红色,它的邻居rgbα = (0,0,0,2)是黑色的,几乎完全透明。两个纹理元素中间位置的rgbα是多少?简单的插值得到(127,0,0,128),结果rgb值单独为“较暗”的红色。然而,这个结果实际上并不暗,它是一个完全的红色,已经被它的alpha预乘。如果您内插alpha值,为了正确内插,您需要确保内插的颜色在内插之前已经预先乘以alpha。作为一个例子,假设几乎透明的邻居被设置为rgbα = (0,255,0,2),给出一点点绿色。这种颜色不是alpha的预乘,插值时会得到(127,127,0,128)的结果——微小的绿色突然将结果转变为(预乘的)黄色样本。这个邻居纹理元素的预乘版本是(0,2,0,2),这给出了(127,1,0,128)的正确预乘结果。这个结果更有意义,产生的预乘颜色主要是红色,带有一点难以察觉的绿色。

Ignoring that the result of bilinear interpolation gives a premultiplied result can lead to black edges around decals and cutout objects. The “dimmer” red result gets treated as an unmultiplied color by the rest of the pipeline and the fringes go to black.This effect can also be visible even if using alpha testing. The best strategy is to premultiply before bilinear interpolation is done [490, 648, 1166, 1813]. The WebGL API supports this, since compositing is important for webpages. However, bilinear interpolation is normally performed by the GPU, and operations on texel values cannot be done by the shader before this operation is performed. Images are not premultiplied in file formats such as PNG, as doing so would lose color precision. These two factors combine to cause black fringing by default when using alpha mapping. One common workaround is to preprocess cutout images, painting the transparent, “black” texels with a color derived from nearby opaque texels [490, 685]. All transparent areas often need to be repainted in this way, by hand or automatically, so that the mipmap levels also avoid fringing problems [295]. It is also worth noting that premultiplied values should be used when forming mipmaps with alpha values [1933].

忽略双线性插值给出预乘结果可能会导致贴花和剪切对象周围出现黑边。“较暗”的红色结果被管道的其余部分视为未相乘的颜色,条纹变为黑色。即使使用alpha测试,这种影响也是可见的。最佳策略是在双线性插值完成之前进行预乘[490,648,1166,1813]。WebGL API支持这一点,因为合成对网页很重要。但是,双线性插值通常由GPU执行,在执行此操作之前,着色器无法对纹理像素值进行操作。在PNG等文件格式中,图像不会预乘,因为这样做会损失颜色精度。默认情况下,使用alpha贴图时,这两个因素结合在一起会导致黑色边缘。一种常见的解决方法是预处理剪切图像,用从附近不透明纹理元素中获得的颜色绘制透明的“黑色”纹理元素。所有透明区域经常需要以这种方式重新绘制,手动或自动,以便mipmap级别也避免边缘问题[295]。同样值得注意的是,当使用alpha值形成mipmaps时,应使用预乘值[1933]。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

椰子糖莫莫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值