[unityshader] energy shield and simple interaction

Design sketch
This is the experience after watching station b av70029953.

Because csdn has a picture size limit, it subtracts points appropriately.
The effect in the figure is the contraction of the energy shield and the collision interaction effect with the outside collider.

Prepare model (BLENDER)

Use Blender to make a corner ball.

Click the plug-in panel to add a tissue plug-in

After adding, click the plug-in panel button

You can get a grid like this

Reset uv

The mesh is composed of five and six sides to adjust the uv layout
Select all the non edge faces, adjust the uv layout of all the five edge faces to the lower left corner, and then reverse the selection with ctrl+i to adjust the upper right corner of the six edge faces (the operation such as g move, s scale in uv panel is still applicable)


Then export the uv layout

The key is coming.

Because when we need the shield to shrink (vertex animation), each face is independent, so we need to separate each face of the model.

Enter edit mode, edit edge
Select all edges to separate them.

Select a face to move to check whether it is independent

Make surface map (PS)

The initial effect of uv layout is as follows


Use the color range to select the black edge and fill in the new layer (you can use the shortcut ctrl+delete to fill in the foreground color) with white.
Then invert the selection. Create a new layer as the background and fill it with black. The results are as follows

Double click the layer where the white edge is located, enter the layer style editing, select the external light to adjust to the appropriate light edge

Export map to Unity

Implementation effect code

In the aspect of shader, it is Fresnel + vertex animation (use ﹣ SinTime to achieve fluctuation effect) + HDR color mode (just add [HDR] before the attribute name)
The key is how to interact.
Add an interactive script to the corner sphere. When the collision occurs (the condition of collision is that both sides have a collider, and at least one of them has a rigbody component), pass in the information of collision point to the shader, compare the distance between the current vertex and the collision point in the shader, use smoothstep to limit the distance between 0-1, and adjust the mask edge according to the parameters, and then set the distance value Put on a layer of shield color.
Here is the interactive script:

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);//Use toggle to control whether the input vertex is valid


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

Here is the shader code:

Shader "Unlit/Shield"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        [HDR]_Color("colour",Color)=(1,1,1,1)
        _Strength("Waviness",Range(0,1))=0
        _Distance("Diffusion distance",Range(0,0.05))=0.01
        _FresnelPower("fresnel power",Range(0,10))=5
        _FresnelScale("Fresnel proportion",Range(0,1))=1

        _MaskRadius("mask radius",Range(0,3))=0
        _MaskSmooth("emergence",Range(0,1))=0
        [HDR]_CollisionColor("Collision color",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
        }
    }
}

Published 16 original articles, won praise 1, visited 541
Private letter follow

Tags: Unity Attribute Fragment

Posted on Sun, 15 Mar 2020 01:09:31 -0400 by unerd.co.uk