转载地址:http://www.omuying.com/article/95.aspx
原文地址https://en.wikibooks.org/wiki/Cg_Programming/Unity/Order-Independent_Transparency
本博客中还有篇详解,可以去看看那篇先做了解。
在《透明度》章节中,我们讨论并解决了在着色器上呈现透明度一些标准的问题,如果你还没有阅读这个章节,那么你应该先去阅读它。
顺序无关的混合
在《透明度》章节中,我们知道,混合的结果取决于三角形的呈现顺序(尤其是 alpha 混合),如果三角形不是按从背面到前面的呈现方式,这样可能会导致渲染问题,术语“order-independent transparency”一词描述各种技术来避免这个问题,其中的一个技术便是“order-independent”混合,即使用一个不依赖于三角形栅格化顺序的混合公式,他们是:加法(additive )blending 和乘法(multiplicative) blending。
我们不可能(至少很难)说是照片以何种顺序拍摄。additive blending 的特点可以依据《透明度》章节的混合公式:
1 |
float4 result = SrcFactor * fragment_output + DstFactor * pixel_color; |
其中 SrcFactor 和 DstFactor 由 Unity 的语法决定:
1 |
Blend {code for SrcFactor} {code for DstFactor} |
对于 additive blending,DstFactor 必须是 One,SrcFactor 的值不能取决于帧缓冲区里面的像素颜色,它可以是 One、SrcColor、SrcAlpha、 OneMinusSrcColor 或者 OneMinusSrcAlpha。
Shader "Cg shader using additive blending" { SubShader { Tags { "Queue" = "Transparent" } // draw after all opaque geometry has been drawn在所有不透明几何物体后绘制 Pass { Cull Off // draw front and back faces ZWrite Off // don't write to depth buffer // in order not to occlude other objects Blend SrcAlpha One // additive blending CGPROGRAM #pragma vertex vert #pragma fragment frag float4 vert(float4 vertexPos : POSITION) : SV_POSITION { return mul(UNITY_MATRIX_MVP, vertexPos); } float4 frag(void) : COLOR { return float4(1.0, 0.0, 0.0, 0.3); } ENDCG } } }
Multiplicative Blending
multiplicative blending 使用的例子是在摄影中使用多个均匀(uniform)的灰色滤波器:摄像机滤波器的顺序对于图像的衰减是无关紧要的,在三角形的栅格化方面,图像对应于在三角形栅格化之前帧缓冲区中的内容,而滤波器对应于三角形。
可以像下面的格式来指定 multiplicative blending:
1 |
Blend {code for SrcFactor} {code for DstFactor} |
对于 SrcFactor 必须是 Zero,并且 DstFactor 必须取决于片段颜色,所以可能的值是 SrcColor、SrcAlpha、OneMinusSrcColor 或者 OneMinusSrcAlpha。典型的例子是 DstFactor 使用 OneMinusSrcAlpha 来表示用片段的 alpha 分量来指定不透明背景的衰减:
最后,我们可以在一个着色器中使用两个 Pass 来合并 multiplicative blending(指定背景的衰减)和 additive blending(给三角形添加颜色),如果忽略三角形网格本身的颜色衰减,这可以被认为是一种近似小不透明体(small opacities)的 alpha 混合,即小的 alpha 值。
Shader "Custom/Blending1"
{
SubShader
{
Tags{ "Queue" = "Transparent" }
// draw after all opaque geometry has been drawn
Pass
{
Cull Off // draw front and back faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend Zero OneMinusSrcAlpha // multiplicative blending
// for attenuation by the fragment's alpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 vert(float4 vertexPos : POSITION) : SV_POSITION
{
return mul(UNITY_MATRIX_MVP, vertexPos);
}
float4 frag(void) : COLOR
{
return float4(0.0, 0.0, 1.0, 0.3);
}
ENDCG
}
Pass
{
Cull Off // draw front and back faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha One // additive blending to add colors
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 vert(float4 vertexPos : POSITION) : SV_POSITION
{
return mul(UNITY_MATRIX_MVP, vertexPos);
}
float4 frag(void) : COLOR
{
return float4(0.0, 0.0, 1.0, 0.5);
}
ENDCG
}
}
}
去掉第二个通道的注释,效果如图所示: