Unity shader 护盾shield的简单实现

扰动
直接对uv进行变换就可以了,记得首先把六边形格子地图的Tilling调高点 先预先调成合适大小的六边形,然后repeat铺满整个护盾

1
2
3
4
5
6
// Tiles and offsets the value of input UV by the inputs Tiling and Offset respectively.
// This is commonly used for detail maps and scrolling textures over Time.
void Unity_TilingAndOffset_float(float2 UV, float2 Tiling, float2 Offset, out float2 Out)
{
Out = UV * Tiling + Offset;
}
直接在vertex着色器中对appdata传进来的uv进行变动,两者 offset的变动频率不同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
half2 uv = TRANSFORM_TEX(v.uv, _MainTex);
Unity_TilingAndOffset_float(uv, half2(1, 1), half2(0, -_Time.y), o.uv);
Unity_TilingAndOffset_float(uv, half2(1, 1), half2(0, -_Time.y * 2), o.uvGlow);

            float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; 
	
            o.worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
		    o.worldNormal = UnityObjectToWorldNormal(v.normal);
            return o;
        }

护盾边缘光
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};

        struct v2f
        {
            float2 uv : TEXCOORD0;
            float2 uvGlow : TEXCOORD1;
            float4 vertex : SV_POSITION;
		    half3 worldNormal : TEXCOORD2;
            half3 worldViewDir : TEXCOORD3;
        };

vertex着色器
1
2
3
4
5
6
7
8
9
10
11
12
13
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);

float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

            o.worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
		    o.worldNormal = UnityObjectToWorldNormal(v.normal);
            ...
                
            return o;
        }

fragment着色器
先获取世界坐标系下的法线向量和世界坐标系下摄像机到顶点的向量,1-点乘得到的值然后结合到最后的颜色输出计算中,法线向量与摄像机到顶点的向量的所成夹角可视为从中心点向边缘扩散,角度越来越大,到边缘区角度呈局部最大值

1
2
3
4
5
6
7
8
9
10
11
half4 frag (v2f i) : SV_Target
{

half rim = pow(1 - abs(dot(normalize(i.worldNormal), normalize(i.worldViewDir))), _RimNum);

            // 边缘高光
            col = lerp(col, _LightColor, rim);
            ...

            return col;
        }

全部代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
Shader “Unlit/ShieldForceField”
{
Properties
{
_MainTex (“Texture”, 2D) = “white” {}
[NoScaleOffset] _LightTex (“LightTex”, 2D) = “white” {}
_Hologram (“Hologram”, 2D) = “white” {}
[HDR] _LightColor (“LightColor”, Color) = (1, 1, 1, 1)
// 边缘光幅度
_RimNum(“Rim” , Range(0 , 5)) = 1
}
SubShader
{
Tags
{
“RenderType” = “Transparent”
“Queue” = “Transparent”
“IgnoreProjector” = “True”
“ForceNoShadowCasting” = “True”
}

    Blend SrcAlpha OneMinusSrcAlpha

    Pass
    {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag

        #include "UnityCG.cginc"
        #include "../../../../../Assets/ShaderGraphic.cginc"
		
		sampler2D _MainTex, _LightTex, _Hologram;
        float4 _MainTex_ST;
        half4 _LightColor;
        
        float _RimNum;

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

        struct v2f
        {
            float2 uv : TEXCOORD0;
            float2 uvGlow : TEXCOORD1;
            float4 vertex : SV_POSITION;
		    half3 worldNormal : TEXCOORD2;
            half3 worldViewDir : TEXCOORD3;
        };

        v2f vert (appdata v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            half2 uv = TRANSFORM_TEX(v.uv, _MainTex);
            Unity_TilingAndOffset_float(uv, half2(1, 1), half2(0, -_Time.y), o.uv);
            Unity_TilingAndOffset_float(uv, half2(1, 1), half2(0, -_Time.y * 2), o.uvGlow);
            
            float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; 
	
            o.worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
		    o.worldNormal = UnityObjectToWorldNormal(v.normal);
            return o;
        }

        half4 frag (v2f i) : SV_Target
        {
            half4 col = tex2D(_MainTex, i.uv);
            half4 light = tex2D(_LightTex, i.uv);

            // light.rgb = light.r * _LightColor.rgb;
            light.rgb = _LightColor.rgb;
            col.rgb += light.rgb * _LightColor.a;

            half4 holoColor = tex2D(_Hologram, i.uvGlow);
            col += holoColor * 0.3;

            col.a = 0.5;

            half rim = pow(1 - abs(dot(normalize(i.worldNormal), normalize(i.worldViewDir))), _RimNum);

            // 边缘高光
            col = lerp(col, _LightColor, rim);

            return col;
        }
        ENDCG
    }
}

}

最后大功告成了,后续可能会继续改进一下(加上相交时会留下边缘光)
USB Microphone https://www.soft-voice.com/
Wooden Speakers https://www.zeshuiplatform.com/
亚马逊测评 www.yisuping.cn
深圳网站建设www.sz886.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值