UnityShader入门精要-透明效果

  • Post author:
  • Post category:其他


实现透明效果的方法:1.透明度测试2.透明度混合

深度缓冲Z-buffer决定了哪个物体的那些部分会被渲染在前面,而哪些部分会被遮挡(比较距照相机的距离),渲染一个片元时需要把他的深度值与已经存在在深度缓冲中的值进行比较,判断并将深度值更新到深度缓冲中(如果开启深度写入)。

透明度测试:某个片元的透明度不满足条件(小于某个值),将直接被舍弃;否则就按不透明物体的方式进行处理,进行深度测试深度写入等,即透明度测试不需要关闭深度写入,效果极端全或无。

透明度混合:实现真正的半透明效果,使用当前偏远的透明度作为因子与已经在颜色缓冲中的颜色值混合,得到新的颜色,需要关闭深度写入,但没有关闭深度测试,如果深度值距摄像机更远,则不进行混合操作。


关闭深度写入后,渲染顺序将影响渲染结果。


解决渲染顺序:渲染队列(subshader中的queue标签)


Background:1000 在所有队列之前渲染,用于绘制背景物体


Geometry:2000 默认渲染队列,大多数物体,不透明物体


AlphaTest:2450 需要透明度测试的物体


Transparent:3000  在所有geometry和alphatest渲染后,再从后往前的顺序渲染,使用了透明度混合的物体


Overlay:用于实现叠加效果

SubShader{
    Tags{"Queue"="AlphaTest"}
    Pass{
        ...
    }
}

透明度测试

透明度测试通常使用clip函数:void clip(floatn x);如果给定的参数任何一个分量是负数,就会舍弃当前像素输出颜色。

在下面的片元着色器中,使用clip函数,将小于给定值(cutoff)的texcolor不显示。


			
			fixed4 frag(v2f i) : SV_Target {
				fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
				
				fixed4 texColor = tex2D(_MainTex, i.uv);
				
				// Alpha test
				clip (texColor.a - _Cutoff);
				// Equal to 
//				if ((texColor.a - _Cutoff) < 0.0) {
//					discard;
//				}
				
				fixed3 albedo = texColor.rgb * _Color.rgb;
				
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
				
				fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));
				
				return fixed4(ambient + diffuse, 1.0);
			}
			

透明度混合

使用混合命令Blend,设置混合因子,片元源颜色将乘SrcFactor,目标颜色(已经存在于颜色缓冲中的颜色)将乘以DstFactor,再把两者相加存入颜色缓冲。

DstColor(new)=SrcFactor X SrcColor+DstFactor X DstColor(old)

需要调整的设置

更新后的片元着色器,就是在最后输出的透明度上做了变动

关闭深度写入在处理模型本身有复杂的遮挡关系或者包含了非凸网格是会因为排序错误产生错误的效果。

开启深度写入的半透明效果

一种解决方法是使用两个Pass来渲染模型,一个开启深度写入但不输出颜色,仅仅是为了将模型的深度值存入深度缓存中,剔除模型中被自身遮挡的片元,第二个pass进行正常的透明度混合。

此处ColorMask在ShaderLab中用于设置颜色通道的写掩码, 当其设为0时,表示该Pass不写入任何颜色通道。

ShaderLab的混合命令

片元着色器产生一个颜色时,可以选择与颜色缓存中的颜色进行混合,这样这个操作与两个操作数有关:源颜色(S表示片元着色器产生的颜色),目标颜色(D表示从颜色缓冲中读到的颜色),得到的输出颜色记O,都包含RGBA四个通道。

想要得到O需要两个混合等式,分别计算RGB通道和A通道的混合。如果给出两个因子就用同样的因子计算RGB和A的混合等式,如果给出四个混合因子就用其分别计算RGB和A。

上面使用的是正常的透明度混合,一些其他的混合操作和混合因子的命令可以实现变暗变量,类似彩铅画风等。见书P175.

双面渲染的透明效果

透明物体的内部结构在上面的透明度测试与透明度混合中无法看到,因为默认情况下渲染引擎剔除了物体背面(相对于摄像机的方向)的图元,即只有证明,要得到双面效果,就需要通过

Cull指令来控制需要剔除哪个面。

Cull Back|Front|Off    默认为back 当关闭off时即可双面。

透明度测试的双面渲染

只需在透明度测试的基础上加上cull off即可。

透明度混合的双面渲染

由于透明度测试关闭了深度写入,需要严格控制渲染顺序从后往前,为了保证正面背面正确渲染,将双面渲染氛围两个pass一个只渲染正面,一个只渲染背面,渲染的方式和之前透明度混合的相同。

即在一个pass中声明Cull Front,在另一个中声明Cull Back

效果展示。

上述所有的效果汇总:



版权声明:本文为weixin_58624886原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。