欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

unity shader特效之 建筑结构科技透视效果 贴近消失远离显示

程序员文章站 2022-07-12 23:30:57
...

前言

公司需要做个建筑结构演示。看了产品经理的方案感觉实在太low,真的看不下去了。
于是我就极不情愿的修改了方案做了这个玩意。给他看的时候我告诉他:公司难得有我这么牛逼的技术,你们想象应该大胆点。

  • 先贴出最终笑狗图~
    unity shader特效之 建筑结构科技透视效果 贴近消失远离显示

实现思路

其实不少科幻或动作电影中都有类似特效,实现起来并不复杂,只需要将三个小特效结合起来就能实现:

  1. 建筑结构透视
  2. 毛玻璃特效
  3. 贴近显示
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
        }
    }
}

请留下你的赞再走~~~