[unityshader]制作能量护盾以及简单互动

效果图
在这里插入图片描述
因为csdn有图片大小限定,所以适当减去了点。
图中效果为:能量护盾的收缩,以及与外界collider的碰撞交互效果。

准备模型(BLENDER)

使用Blender制作一个棱角球。

在这里插入图片描述

点开插件面板添加一个tissue插件
在这里插入图片描述
添加后,点击插件面板这个按钮
在这里插入图片描述
就能得到这样的网格了
在这里插入图片描述
重置uv
在这里插入图片描述
网格由五边面和六边面构成,调整uv布局
选中所有的无边面,调整所有的五边面uv布局为左下角,再ctrl+i反选,调整六边面在右上角(uv面板中g移动,s缩放等操作依然适用)
在这里插入图片描述
在这里插入图片描述
然后导出uv布局图
在这里插入图片描述

制作表面贴图(PS)

uv布局图起始效果如下
在这里插入图片描述
在这里插入图片描述
使用色彩范围选中黑色边缘,在新建图层中填充(可以使用快捷键ctrl+delete填充前景色)为白色。
再反选,新建图层作为背景,填充为黑色。得到如下效果
在这里插入图片描述
双击白边所在图层,进入图层样式编辑,选择外发光调整至合适发光边缘
在这里插入图片描述
导出贴图放入Unity

实现效果代码

shader方面就是菲涅尔+顶点动画(使用了_SinTime达到波动效果)+HDR颜色模式(在属性名前面加上[HDR]即可)
关键是如何实现互动。
给棱角球加上一个互动脚本,当碰撞发生时(碰撞发生条件是双方都有collider,其中至少一方含有rigbody组件),传入碰撞点的信息到shader中,在shader中比较当前顶点距离碰撞点的距离,使用smoothstep把距离限制在0-1之间,还能根据参数调整遮罩边缘,再把这个距离值乘上一层护盾颜色。
以下为互动脚本:

using UnityEngine;

public class InteractSphere : MonoBehaviour
{
    public Material material;

    private void OnCollisionEnter(Collision other)
    {
        material.SetVector("_InteractPoint", other.contacts[0].point);
        material.SetFloat("_Toggle", 1);//使用toggle控制是否输入顶点有效


    }
    private void OnCollisionExit(Collision other)
    {
        material.SetFloat("_Toggle", 0);
    }
}

以下为shader代码:

Shader "Unlit/Shield"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        [HDR]_Color("颜色",Color)=(1,1,1,1)
        _Strength("波浪度",Range(0,1))=0
        _Distance("扩散距离",Range(0,0.05))=0.01
        _FresnelPower("菲涅尔power",Range(0,10))=5
        _FresnelScale("菲涅尔比例",Range(0,1))=1

        _MaskRadius("遮罩半径",Range(0,3))=0
        _MaskSmooth("羽化",Range(0,1))=0
        [HDR]_CollisionColor("碰撞颜色",Color)=(1,1,1,1)
        
        
    }
    SubShader
    {
        Tags { "RenderType"="transparent" "queue"="transparent"}
        LOD 100
        
        Pass
        {
            blend srccolor one
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"
            float _Strength;
            float _Distance;
            float _FresnelPower;
            float4 _Color;
            float _FresnelScale;
            float4 _InteractPoint;
            float _MaskSmooth;
            float4 _CollisionColor;
            float _Toggle;
            
            float _MaskRadius;
            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal:NORMAL;
                float2 uv : TEXCOORD0;
                
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 objPos:TEXCOORD1;

                float3 worldNormal:TEXCOORD2;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                
                
                v.vertex+=_Distance*float4((_Strength+_SinTime.w)*v.normal,0);
                o.objPos=v.vertex;
          
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                
                o.worldNormal=normalize(UnityObjectToWorldNormal(v.normal));
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                
                float4 worldPos=mul(unity_ObjectToWorld,i.objPos);
                float dt=smoothstep(_MaskRadius+_MaskSmooth,_MaskRadius-_MaskSmooth,distance(worldPos,_InteractPoint));
                float3 viewDir=normalize(WorldSpaceViewDir(i.objPos));
                float fresnel=_FresnelScale*pow(1-abs(dot(viewDir,i.worldNormal)),_FresnelPower);
                // sample the texture
                fixed4 col =tex2D(_MainTex, i.uv)*(fresnel*_Color+_CollisionColor*dt*_Toggle);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值