【本系列文章系学习 唐福幸《Unity ShaderLab 新手宝典》的笔记,包含个人理解,如有错误欢迎批评指出
透明效果
一句话总结:双面渲染显示效果更加真实,思路在于先剔除正面渲染,再剔除背面渲染,两个Pass混合即可得到。
7.3.6 半透明物体的双面渲染
前面的渲染效果存在一个问题:当一个完全透明的物体只有单面渲染,就会忽略掉物体背面,如下:
单面渲染:
双面渲染:
之前的Cull可以用来剔除几何体的正面和背面(正面指第一个平行光照射的方向)
- 如果关掉(Cull Off)那么缓存中没有深度信息,会导致正面和背面的绘制顺序有误。
- 如果先剔除背面,再剔除正面,会导致背面图像会叠加在正面上。
- 所以只能先剔除正面,再剔除背面,两个Pass混合之后,渲染出来的效果才是正确的。(两次Pass渲染显然更加耗费性能)
代码模板如下:
Shader "Chapter7/TransImg3"
{
Properties
{
_MainColor("Main Color",Color)=(1,1,1,1)
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"RenderType" = "Transparent"
"IgnoreProjector" = "True"
}
Pass
{
Tags{"Lighting" = "ForwardBase"}
Cull Front
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
//代码。。。。。。。。。。。
ENDCG
}
Pass
{
Tags{"Lighting" = "ForwardBase"}
Cull Back
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
//代码。。。。。。。。。。。
ENDCG
}
}
FallBack "Diffuse"//显示阴影
}
颜色透明代码:
Shader "Chapter7/TransImg3"
{
Properties
{
_MainColor("Main Color",Color)=(1,1,1,1)
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"RenderType" = "Transparent"
"IgnoreProjector" = "True"
}
Pass
{
Tags{"Lighting" = "ForwardBase"}
Cull Front
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "UnityLightingCommon.cginc"
struct v2f
{
float4 pos : SV_POSITION;
fixed4 dif : COLOR0;
};
fixed4 _MainColor;
v2f vert(appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
float3 n = UnityObjectToWorldNormal(v.normal);
fixed3 l = normalize(_WorldSpaceLightPos0.xyz);
fixed ndotl = dot(n,l);
//o.dif = _LightColor0 * _MainColor * saturate(ndotl);
o.dif = _LightColor0 * _MainColor * (0.5 * ndotl + 0.5);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return i.dif;
}
ENDCG
}
Pass
{
Tags{"Lighting" = "ForwardBase"}
Cull Back
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "UnityLightingCommon.cginc"
struct v2f
{
float4 pos : SV_POSITION;
fixed4 dif : COLOR0;
};
fixed4 _MainColor;
v2f vert(appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
float3 n = UnityObjectToWorldNormal(v.normal);
fixed3 l = normalize(_WorldSpaceLightPos0.xyz);
fixed ndotl = dot(n,l);
//o.dif = _LightColor0 * _MainColor * saturate(ndotl);
o.dif = _LightColor0 * _MainColor * (0.5 * ndotl + 0.5);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return i.dif;
}
ENDCG
}
}
FallBack "Diffuse"
}
效果:
贴图透明代码:
Shader "Chapter7/TransImg4"
{
Properties
{
_MainTex ("MainTex", 2D) = "white" {}
_MainColor("Main Color",Color)=(1,1,1,1)
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"RenderType" = "Transparent"
"IgnoreProjector" = "True"
}
Pass
{
Tags{"Lighting" = "ForwardBase"}
Cull Front
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "UnityLightingCommon.cginc"
struct v2f
{
float4 pos : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _MainColor;
v2f vert(appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);//输入uv坐标和纹理名称,得到贴图的纹理坐标
return o;
}
fixed4 frag (v2f i) : COLOR
{
fixed4 color = tex2D(_MainTex, i.texcoord) * _MainColor;
return color;
}
ENDCG
}
Pass
{
Tags{"Lighting" = "ForwardBase"}
Cull Back
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "UnityLightingCommon.cginc"
struct v2f
{
float4 pos : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _MainColor;
v2f vert(appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);//输入uv坐标和纹理名称,得到贴图的纹理坐标
return o;
}
fixed4 frag (v2f i) : COLOR
{
fixed4 color = tex2D(_MainTex, i.texcoord) * _MainColor;
return color;
}
ENDCG
}
}
FallBack "Diffuse"
}
效果: