Unity 中实现透明效果一般有两种方法
原理:只要片元的透明度不符合要求就直接舍弃
登录后复制
Shader "AlphaTest"{
Properties{
_MainTex ("Main Tex", 2D) = "white" {}
_Color ("Color", Color) = (1, 1, 1, 1)
_Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5 //控制剔除的阈值
}
SubShader
{
Tags { "Queue"="AlphaTest" "IgnoreProjection"="True" "RanderType"="TransparentCutout"}
Pass{
Tags { "LightMode"="ForwardBase" }
Cull Off //用于双面渲染,不剔除背对摄像机的图元
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
struct appdata{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldPos : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _Cutoff;
fixed4 _Color;
v2f vert (appdata v){
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
return o;
}
fixed4 frag (v2f i) : SV_Target{
float3 worldNormal = normalize(i.worldNormal);
float3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
float4 texColor = tex2D(_MainTex, i.uv);
clip(texColor.a - _Cutoff);
//Equal to
//if( (texColor.a - _Cutoff) < 0.0 ){
// discard;
//}
float3 albedo = texColor.rgb * _Color.rgb;
float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
float3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));
return fixed4(ambient + diffuse, 1.0);
}
ENDCG
}
}
FallBack "Transparent/Cutout/VertexLit"
}
透明度测试可以用于消解动画效果的实现
原理:当前片元的透明度作为混合参数与颜色缓冲中的颜色值混合
关闭深度写入,但不关闭深度测试
关闭深度写入将导致渲染顺序变得非常重要
一般做法:
由于排序是对于物体来说的,当物体间循环重叠时就需要用分割物体、分割网格的方法来解决
对于双面渲染的透明度混合,由于关闭了深度写入,在渲染时需要控制渲染顺序
登录后复制
SubShader {
Tags {"Queue"="Transparent" "IgnoreProjection"="True" "RanderType"="Transparent"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha //开启混合模式,设定混合因子
Pass {
...
Cull Front //剔除正面,渲染背面
...
}
Pass {
...
Cull Back //提出背面,渲染正面
...
}
}
半透明物体的阴影没了,暂时不知道原因
使用两个 Pass
由于深度信息是对像素来说的,所以如果单个模型本身存在自我遮挡,那么被遮挡部分就直接舍弃了
ColorMask RGB | A | 0 | ...
表示当前 Pass 写入的颜色通道
由SubShader
的Queue
标签定义:Tags { "Queue"="AlphaTest" }
名称 | 索引号 | 描述 |
Background | 1000 | 最先开始渲染的队列,一般用于绘制于背景上的物体 |
Geometry | 2000 | 默认队列,不透明物体 |
AlphaTest | 2450 | 透明度测试,在不透明物体之后渲染可以更高效 |
Transparent | 3000 | 透明度混合,从后往前的顺序进行渲染 |
Overlay | 4000 | 用于最后渲染的物体,实现一些叠加效果 |
索引号越小越早被渲染
混合不可编程但高度可配置
混合源颜色(当前片元)和目标颜色(颜色缓冲)
Blend SrcFactor DstFactor
: 只混合rgb通道Blend SrcFactor DstFactor,SrcFactorA DstFactorA
: 上面的基础上,再混合 a 通道例子:
Blend SrcAlpha OneMinusSrcAlpha
:开启混合,并且混合结果是 \(Src.a * Src.rgb + (1-Src.a)*Des.rgb\)
还可以配置混合操作
BlendOp BlendOperation
即改变源颜色和目标颜色最后的混合方式,默认为 Add
操作 | 描述 |
Add | 加法 |
Sub | 减法 |
RevSub | 交换减法 |
Min | 取各分量的最小值 |
Max | 取各分量的最大值 |
同时使用上面两种方法可设定混合类型
类型 | 描述 |
正常 | Blend SrcAlpha OneMinusSrcAlpha |
柔和相加 | Blend OneMinusDstAlpha One |
正片叠底 | Blend DstColor Zero |
两倍相乘 | Blend DstColor SrcColor |
变暗 | BlendOp Min Blend One One |
变亮 | BlendOp Max Blend One One |
滤色 | Blend OneMinusDstColor One |
线性减淡 | Blend One One |
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删