前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Unity 科幻投影效果简单实现

Unity 科幻投影效果简单实现

作者头像
HkingAuditore
发布2023-10-26 17:41:09
3560
发布2023-10-26 17:41:09
举报
文章被收录于专栏:HkingAuditoreHkingAuditore

Shader刚入门,记录一下刚玩出来的全息投影效果。

先看原模型:

说到全息投影,最先想到的就是一条条扫描线,在模型上随着投影方向逐层扫描。

原理也比较简单,准备一张扫描采样图,在片元着色器中根据模型的x坐标采样再加上时间变量即可。

代码语言:javascript
复制
// 扫描线流动动画
fixed scroll = _Speed * _Time;
fixed4 col = tex2D(_MainTex,i.uv);
fixed scrollProject =abs(i.objectPos.x+scroll - round(i.objectPos.x+scroll));
fixed4 cybercol = tex2D(_CyberTex, scrollProject);
fixed alpha = 1;
if(cybercol.r + cybercol.g + cybercol.b < 1){
   alpha = 0; 
   col = max(cybercol,col);
} 

实现了非常粗暴的扫描线。

再计算视角与法线的点乘,加上边缘光效果。

代码语言:javascript
复制
//边缘光
fixed edge = pow(i.VdotN, 1) / _Range;
 edge = edge > _OutlineThred ? 1 : edge;   
edge = 1 - edge;       
//小于thred的部分视为边缘
fixed4 edgeCol = pow(edge, 0.1) * fixed4(_EdgeColor.rgb + fixed3(0.3,0.3,0.5) * (sin(_Time.y * 3)+1)*0.5,edge);
//边缘颜色处理
col = col*(1-edgeCol.a)+edgeCol*edgeCol.a;

最后加上两个PASS(其实用一个做法线外扩也可以)做出残影效果,每个pass的算法和前面的基本一致。

完整代码如下:

代码语言:javascript
复制
Shader "Cyber/cyberProjection"
{
    Properties
    {
        _CyberTex ("Cyber Texture", 2D) = "white" {}
        _CyberTexBack ("Cyber Texture Back", 2D) = "white" {}
        _MainTex ("Main Texture", 2D) = "white" {}

        [HDR]_EdgeColor("Edge Color", Color) = (1,1,1,1)
        [HDR]_OutsideColor("Outside Color", Color) = (1,1,1,1)

        _Speed("Speed", Range(-5,5)) = 1
        _OutlineThred("OutlineThred", Range(0,1)) = 0.5
        _Range("Range", Range(0,2)) = 1
        _Size("Size", Range(0,1)) = 0.5
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue" = "Transparent" "IgnoreProjector" = "True" "ForceNoShadowCasting" = "True"}
        LOD 100
        Blend SrcAlpha OneMinusSrcAlpha


        Pass
        {
            // Cull Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"


            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                fixed3 normal : NORMAL;

            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float4 objectPos : TEXCOORD1;
                float4 VdotN : TEXCOORD2;
                UNITY_FOG_COORDS(3)
            };

            sampler2D _CyberTex;
            float4 _CyberTex_ST;
            float4 _CyberTex_TexelSize;

            sampler2D _MainTex;
            float4 _MainTex_ST;

            // fixed4 _MainColor;
            fixed4 _EdgeColor;

            fixed _Speed;
            fixed _Offset;
            float _Range;
            float _OutlineThred;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _CyberTex);
                o.objectPos = v.vertex;
                float3 viewDir = normalize( 
                    mul(unity_WorldToObject, 
                    float4(_WorldSpaceCameraPos.xyz, 1)).xyz - v.vertex);
				o.VdotN = dot(normalize(viewDir),v.normal);


                UNITY_TRANSFER_FOG(o,o.vertex);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // 流动动画
                fixed scroll = _Speed * _Time;
                fixed4 col = tex2D(_MainTex,i.uv);
                fixed scrollProject =abs(i.objectPos.x+scroll - round(i.objectPos.x+scroll));

                fixed4 cybercol = tex2D(_CyberTex, scrollProject);

                fixed alpha = 1;
                alpha -= i.objectPos.x;
                if(cybercol.r + cybercol.g + cybercol.b < 1){
                    alpha = 0; 
                    col = max(cybercol,col);
                } 


                //边缘光
                fixed edge = pow(i.VdotN, 1) / _Range;
	            edge = edge > _OutlineThred ? 1 : edge;   
                edge = 1 - edge;       
                //小于thred的部分视为边缘
	            fixed4 edgeCol = pow(edge, 0.1) * fixed4(_EdgeColor.rgb + fixed3(0.3,0.3,0.5) * (sin(_Time.y * 3)+1)*0.5,edge);
               //边缘颜色处理
                col = col*(1-edgeCol.a)+edgeCol*edgeCol.a;
                   

                UNITY_APPLY_FOG(i.fogCoord, col);

                return fixed4(col.rgb,alpha);
            }
            ENDCG
        }
        Pass
        {
            // Cull Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"


            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float4 objectPos : TEXCOORD1;
                float4 VdotN : TEXCOORD2;
                UNITY_FOG_COORDS(3)
            };

            sampler2D _CyberTexBack;
            float4 _CyberTexBack_ST;
            float4 _CyberTexBack_TexelSize;

            sampler2D _MainTex;
            float4 _MainTex_ST;

            float4 _OutsideColor;

            // fixed4 _MainColor;
            fixed _Speed;
            fixed _Offset;
            fixed _Size;

            v2f vert (appdata v)
            {
                v2f o;
                v.vertex.x -= _Size;
                v.vertex.y -= _Size;
                v.vertex.z -= _Size;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _CyberTexBack);
                o.objectPos = v.vertex;


                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed scroll = _Speed * _Time / 2;
                fixed4 col = tex2D(_MainTex,i.uv);
                fixed scrollProject =abs(i.objectPos.x+scroll - round(i.objectPos.x+scroll));

                fixed4 cybercol = tex2D(_CyberTexBack, scrollProject);

                fixed alpha = 1;
                if(cybercol.r + cybercol.g + cybercol.b < 1){
                    alpha = 0; 
                    col = min(cybercol,col);
                } 

                col *= _OutsideColor;

                   

                UNITY_APPLY_FOG(i.fogCoord, col);

                return fixed4(col.rgb,alpha*0.5);
            }
            ENDCG
        }
        Pass
        {
            // Cull Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"


            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float4 objectPos : TEXCOORD1;
                float4 VdotN : TEXCOORD2;
                UNITY_FOG_COORDS(3)
            };

            sampler2D _CyberTexBack;
            float4 _CyberTexBack_ST;
            float4 _CyberTexBack_TexelSize;
            float4 _OutsideColor;


            sampler2D _MainTex;
            float4 _MainTex_ST;

            // fixed4 _MainColor;
            fixed _Speed;
            fixed _Offset;
            fixed _Size;


            v2f vert (appdata v)
            {
                v2f o;
                v.vertex.x += _Size;
                v.vertex.y += _Size;
                v.vertex.z += _Size;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _CyberTexBack);
                o.objectPos = v.vertex;


                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed scroll = _Speed * _Time * 2;
                fixed4 col = tex2D(_MainTex,i.uv);
                fixed scrollProject =abs(i.objectPos.x+scroll - round(i.objectPos.x+scroll));

                fixed4 cybercol = tex2D(_CyberTexBack, scrollProject);

                fixed alpha = 1;
                if(cybercol.r + cybercol.g + cybercol.b < 1){
                    alpha = 0; 
                    col = min(cybercol,col);
                } 
                col *= _OutsideColor;


                   

                UNITY_APPLY_FOG(i.fogCoord, col);

                return fixed4(col.rgb,alpha*0.5);
            }
            ENDCG
        }
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-07-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档