前言
公司需要做个建筑结构演示。看了产品经理的方案感觉实在太low,真的看不下去了。于是我就极不情愿的修改了方案做了这个玩意。
效果:
透视显示建筑结构
离镜头越近的地方越透明,防止阻挡视线
- 先贴出最终笑狗图~
实现思路
其实不少科幻或动作电影中都有类似特效,实现起来并不复杂,只需要将三个小特效结合起来就能实现:
- 建筑结构透视
- 毛玻璃特效
- 贴近显示
1 结构透视的shader
其实就是半透明嘛,根据需求调整cull的面。这个过于初级我就不贴了。
2 毛玻璃
毛玻璃是根据法线做颜色变化
之前我有写过相关的文章,请无情的点击这里https://blog.csdn.net/lengyoumo/article/details/105343400
3 贴近显示
像素远近是根据像素和摄像机的距离来做适当变化。
废话不多说直接上shader,各处都有详细注释
Shader "Custom/FadeDistance" {
Properties{
_Inverse("Inverse", int) = 0 /// 如果不等于0 就使用相反的效果
_MainTex("Texture", 2D) = "white" { } // 贴图
_MainColor("MainColor", Color) = (1,1,1,1) //主颜色
_FadeNear("fade near distance", float) = 10 //贴近显示的最近距离
_FadeFar("fade far", float) = 20 // 贴近显示的最远距离
_FadeRate("Fade Rate", Range(0.001, 2)) = 0.1 // 整体受影响比例
}
SubShader
{
// 设置显示类型和队列,由于需要使用像素透明度的fade 所以需要在transparent队列
Tags { "Queue" = "Transparent" "RenderType" = "Transparent"}
// 设置剔除面。至少在我这个例子中,cull back的效果好一点,cull off 显得有点杂。
Cull back
// 透明混合方式。 最普通的处理方式,不用多说
Blend SrcAlpha OneMinusSrcAlpha
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float fade : TEXCOORD1;
};
int _Inverse;
float4 _MainColor;
float _FadeRate;
float _FadeNear;
float _FadeFar;
// 顶点着色器
v2f vert(appdata_base v)
{
v2f o;
// 将顶点从模型空间转换到裁剪空间
o.pos = UnityObjectToClipPos(v.vertex);
// 获取正确的uv坐标
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
// 将坐标转换到观察空间
float4 posView = mul(UNITY_MATRIX_MV,v.vertex);
// 物体与镜头距离
float distance = length(posView);
// 是否翻转fade方向
if(_Inverse==0){
// 靠近消失
o.fade = saturate((distance - _FadeNear) / (_FadeFar - _FadeNear)) * _FadeRate;
}else{
// 远离消失
o.fade = 1 - saturate((distance + _FadeNear) / (_FadeFar + _FadeNear));
}
return o;
}
// 片元着色器
float4 frag(v2f i) : COLOR
{
// 合并贴图、主颜色、uv取得像素的颜色信息
float4 col = tex2D(_MainTex,i.uv) * _MainColor;
// 计算镜头fade 获取最终像素颜色透明度
return float4(col.rgb, col.a * i.fade);
}
ENDCG
}
}
结合1,2,3得到最终的shader代码
Shader "Custom/FadeInOut" {
Properties{
_Inverse("Inverse", int) = 0
_MainTex("Texture", 2D) = "white" { }
_MainColor("MainColor", Color) = (1,1,1,1)
_FadeNear("fade near distance", float) = 10
_FadeFar("fade far", float) = 20
_FadeRate("Fade Rate", Range(0.001, 2)) = 0.1
_AlphaValue("_AlphaValue",Range(0.01,1)) = 1
}
SubShader
{
Tags { "Queue" = "Transparent" "RenderType" = "Transparent"}
Cull back
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float fade : TEXCOORD1;
float3 viewDir:TEXCOORD2;
float3 worldNormal:NORMAL;
};
float _AlphaValue;
int _Inverse;
float4 _MainColor;
float _FadeRate;
float _FadeNear;
float _FadeFar;
v2f vert(appdata_base v)
{
v2f o;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
o.viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
float4 posView = mul(UNITY_MATRIX_MV,v.vertex);
float distance = length(posView);
if(_Inverse==0){
o.fade = saturate((distance - _FadeNear) / (_FadeFar - _FadeNear)) * _FadeRate;
}else{
o.fade = 1 - saturate((distance + _FadeNear) / (_FadeFar + _FadeNear));
}
return o;
}
float4 frag(v2f i) : COLOR
{
float4 col = tex2D(_MainTex,i.uv)* _MainColor;
half normalAngle = 1 - abs(dot(i.worldNormal, i.viewDir));
return float4(col.rgb, col.a * i.fade) * normalAngle;
}
ENDCG
}
}
}
请留下你的赞再走~~~