Cg Programming/Unity/Order-Independent Transparency

本文介绍了在计算机图形学中,顺序独立混合技术的概念及其应用。主要包括加法混合与乘法混合两种基本类型,以及如何在Unity ShaderLab中实现这两种混合方式。最后还探讨了将两种混合方式结合起来以达到近似的顺序独立alpha混合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里写图片描述本教程介绍顺序独立的混合
下面我们继续在章节“透明度”中的讨论以及解决一些在标准透明度中的问题。你应该先读一下那个教程如果你没读过的话。

顺序独立的混合

正如在“透明度”这章提到的,混合的结果(特别是对于标准alpha混合)经常取决于三角形渲染的顺序,并且如果三角形没有按照从后向前(经常是这样的)的排序会导致渲染假象。“顺序独立的透明度”这个词就描述了避免此问题的各种技术。其中的一种技术就是顺序独立的混合,也就是说混合等式的使用并不取决于三角形光栅化的顺序。有两种基本的可能性:加性混合与乘法混合。

加法混合

双重曝光的例子双重曝光的例子
加法混合的标准示例就是如本章图像所示的双重曝光:被添加的颜色不可能(或者说很难)说出照片是以何种顺序拍摄的。加性混合可以根据“透明度”一节中引入的混合等式来描述:
float4 result = SrcFactor * fragment_output + DstFactor * pixel_color;
fragment_output就是片元着色器的输出,pixel_color就是已经在帧缓冲中的颜色,同时SrcFactor和DstFactor由Unity的ShaderLab语法来定义:
Blend {code for SrcFactor} {code for DstFactor}
对于加法混合,DstFactor的代码必须是One并且SrcFactor代码不能取决于帧缓冲中的颜色;也就是说,代码可以是One, SrcColor, SrcAlpha, OneMinusSrcColor, 或者OneMinusSrcAlpha。
请看示例:

Shader "Cg shader using additive blending" {
   SubShader {
      Tags { "Queue" = "Transparent" } 
         // 在所有不透明几何体绘制之后绘制
      Pass { 
         Cull Off // 绘制正面和背面
         ZWrite Off // 不写入深度缓存 
            // 为了不排除其它物体
         Blend SrcAlpha One // 加法混合

         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.2); 
         } 
         ENDCG  
      }
   }
}

乘法混合

乘法混合在摄影中的例子就是多种均匀灰度滤镜的使用:在一个摄像机上的滤镜顺序并不影响图像的衰减。就三角形光栅化而言,图像对应于三角形光栅化之前的帧缓存中的内容,同时滤镜对应于三角形。
在Unity中是以这行语句来指定乘法混合的
Blend {code for SrcFactor} {code for DstFactor}
DstFactor的代码必须是Zero并且SrcFactor代码必须取决于片元颜色;也就是说,代码可以是SrcColor, SrcAlpha, OneMinusSrcColor, OneMinusSrcAlpha。用片元的 alpha 分量所指定的不透明度衰减背景的典型示例就是使用了OneMinusSrcAlpha作为DstFactor的代码:

Shader "Cg shader using multiplicative blending" {
   SubShader {
      Tags { "Queue" = "Transparent" } 
         // 在所有不透明几何体绘制之后绘制
      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(1.0, 0.0, 0.0, 0.2); 
         }

         ENDCG  
      }
   }
}

完整的着色器代码

最终,通过结合上面提到的两个通道使得背景衰减的乘法混合和在一个着色器中添加三角形的颜色的加法混合组合起来是很有意义的。这个可以被认为小阴影的alpha混合的近似,也就是说alpha值是小的如果忽视了三角形网格的颜色衰减。

Shader "Cg shader using order-independent blending" {
   SubShader {
      Tags { "Queue" = "Transparent" } 
         // draw after all opaque geometry has been drawn
      Pass { 
         Cull Off // 绘制正面和背面
         ZWrite Off // 不写入深度缓存 
            // 为了不排除其它物体
         Blend Zero OneMinusSrcAlpha // 乘法混合 
            // 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(1.0, 0.0, 0.0, 0.2); 
         }

         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(1.0, 0.0, 0.0, 0.2); 
         }

         ENDCG  
      }
   }
}

注意两个通道的顺序是最重要的:首先是背景衰减然后是颜色被叠加。

总结

恭喜你,顺利读完了这章。我们学到了:

  • 什么是顺序独立的透明度以及顺序独立的混合。
  • 什么是最重要的两种顺序独立的混合(加法和乘法)。
  • 如何实现加法和乘法混合。
  • 如何结合加法和乘法混合的两个实现近似顺序独立的alpha混合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值