Unity shader中的透明混合
官方文档地址:https://docs.unity3d.com/cn/current/Manual/SL-Blend.html
openGL参考:https://learnopengl-cn.github.io/04 Advanced OpenGL/03 Blending/#_2
混合公式:finalValue = sourceFactor * sourceValue operation destinationFactor * destinationValue
翻译成中文就是 最终颜色(rgba) = 源混合系数 * 源混合颜色(rgba) +(-,*) 目标系数 * 目标颜色(rgba)
sourceFactor 在 Blend 命令中定义。
sourceValue 是片元着色器输出的值。
operation 是混合操作。
destinationFactor 在 Blend 命令中定义。
destinationValue 是目标缓冲区中现有的值。(就是屏幕上已经渲染出的其他物体的颜色)
混合系数就是0.5 1.0这种数值,在 Blend 命令中可以被定义.
常见混合语法
Blend SrcAlpha OneMinusSrcAlpha // 传统透明度
Blend One OneMinusSrcAlpha // 预乘透明度
Blend One One // 加法
Blend OneMinusDstColor One // 软加法
Blend DstColor Zero // 乘法
Blend DstColor SrcColor // 2x 乘法
Blend One One = shader片元输出的颜色 * 1 + 屏幕颜色 * 1
Blend SrcAlpha OneMinusSrcAlpha = shader片元输出的颜色 * 片元输出的color.a +屏幕颜色*(1-屏幕颜色.a)
也有其他写法
demo示例
写半透明效果记得关闭深度写入,改渲染队列
Tags { "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="True" }
先看看Blend SrcAlpha OneMinusSrcAlpha
着色器代码
fixed4 frag (v2f i) : SV_Target
{
//光照和环境光
float3 worldLight = UnityWorldSpaceLightDir(i.worldPos.xyz);
worldLight = normalize(worldLight);
fixed NdotL = saturate(dot(i.worldNromal, worldLight));
fixed4 color = tex2D(_MainTex, i.texcoord);
color.rgb *= _MainColor.rgb * NdotL * _LightColor0;
color.rgb += unity_AmbientSky;
//令片元输出的alpha值 = _AlphaScale
color.a *= _AlphaScale;
return color;
}
接着看看Blend One One
在这个模式下,自定义的蓝色变得很浅,而且我无论怎么调set alpha 它的透明度都不变
alpha测试
openGL里面用discord命令让我们想丢弃的颜色片段不被写入颜色缓冲区中
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D texture1;
void main()
{
vec4 texColor = texture(texture1, TexCoords);
if(texColor.a < 0.1) //将小于阈值=0.1的片段手动丢弃掉
discard;
FragColor = texColor;
}
在unity shader中,用"Queue"="AlphaTest"和"RenderType=Transparent"进行alpha测试,将透明度小于阈值的片段丢弃掉
关了剔除会导致该PASS性能开销增大
示例:
Shader "Custom/alpha-test Transparent"
{
Properties
{
_MainTex ("MainTex", 2D) = "white" {}
_AlphaTest("AlphaTest", Range(0, 1)) = 0
_Color("Main Color",COLOR)=(1,1,1,1)
}
SubShader
{
// 设置queue和RenderType
Tags
{
"Queue" = "AlphaTest"
"RenderType" = "TrannsparentCutout"
"IgnoreProjector" = "True"
}
Pass
{
Tags{"LightMode" = "ForwardBase"}
// 关闭几何体剔除
Cull Off
//为此子着色器启用 alpha-to-coverage 模式
AlphaToMask On
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "UnityLightingCommon.cginc"
struct v2f
{
float4 pos : SV_POSITION;
float4 worldPos : TEXCOORD0;
float2 texcoord : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaTest;
float4 _Color;
v2f vert (appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
float3 worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldNormal = normalize(worldNormal);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float3 worldLight = UnityWorldSpaceLightDir(i.worldPos.xyz);
worldLight = normalize(worldLight);
fixed NdotL = saturate(dot(i.worldNormal, worldLight));
fixed4 color = tex2D(_MainTex, i.texcoord);
color.rgb *= NdotL * _LightColor0*_Color ;
color.rgb += unity_AmbientSky;
//clip(color.a - _AlphaTest);
color.a = color.a<_AlphaTest?0:1;
return color;
}
ENDCG
}
}
}
效果: