找回密码
 立即注册
查看: 315|回复: 0

一般通过unity特效shader

[复制链接]
发表于 2022-9-19 07:34 | 显示全部楼层 |阅读模式
是实习的第一个作业,贼菜2333
一个有基本功能的特效shader+制作一个爆炸效果
特效shader

当时还没怎么写过c#,也不懂序列化和生命周期,纠结了半天我刚刚填进去的东西怎么一运行就没了啊,然后发现材质会存.mat文件,就直接存材质里了(逃。
当时还没写过editor,随便网上找了个改吧改吧。
总之是按要求实现了,原理就不写了!网上满天飞。

mask
https://www.zhihu.com/video/1554840288279109632


warp
https://www.zhihu.com/video/1554840471729582080

pannar
https://www.zhihu.com/video/1554840540960665600
Shader "Effect/qwqCustomEffect"
{
    Properties
    {
        _MainTex ("Main Texture", 2D) = "white" {}
        [HDR]_MainColor("Main Color", Color) = (1,1,1,1)
        _UseMainTexPanner("Use MainTex Panner", float) = 0
        _MainTex_PannerU("Main Texture panner u", float) = 0
        _MainTex_PannerV("Main Texture panner v", float) = 0

        _MaskTex("Mask Texture", 2D) = "white" {}
        _UseMaskTexPanner("Use MaskTex Panner", float) = 0
        _MaskTex_PannerU("Mask Texture panner u", float) = 0
        _MaskTex_PannerV("Mask Texture panner v", float) = 0        

        _DissolveTex("Dissolve Texture", 2D) = "wihte"{}
        _DissolveFactor("Dissolve Factor", Range(0,1)) = 0
        _DissolveWidth("Dissolve Width", Range(0,1)) = 0
        _UseCustomData("", float) = 0
        
        _WarpTex("Warping Texture", 2D) = "bump"{}
        _WarpFactor("Warping Factor", Range(0,1)) = 0
        _WarpDeltaTime("Warping Delta Time", range(0.05, 0.5)) =0

    }
    SubShader
    {
        Tags
        {
            "Queue" = "Transparent"
            "RenderPipeline" = "UniversalPipeline"
            "IgnoreProjector" = "True"
        }
        LOD 100

        Pass
        {
            Cull Off
                        Lighting Off
                        ZWrite On
            ZTest On
            Blend SrcAlpha OneMinusSrcAlpha

            HLSLPROGRAM
            #pragma vertex EffectVert
            #pragma fragment EffectFrag

            #pragma multi_compile_instancing
            
            #pragma shader_feature_local __ _USE_MASK
            #pragma shader_feature_local __ _USE_PANNER
            #pragma shader_feature_local __ _USE_DISSOLVE
            #pragma shader_feature_local __ _USE_WARPING
            #pragma shader_feature_local __ _BILLBOARD_ON

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            //#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Particles.hlsl"

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);
            #ifdef _USE_MASK
            TEXTURE2D(_MaskTex);
            SAMPLER(sampler_MaskTex);
            #endif
            #ifdef _USE_DISSOLVE
            TEXTURE2D(_DissolveTex);
            SAMPLER(sampler_DissolveTex);            
            #endif
            #ifdef _USE_WARPING
            TEXTURE2D(_WarpTex);
            SAMPLER(sampler_WarpTex);            
            #endif

            CBUFFER_START(UnityPerMaterial)
            half4 _MainTex_ST;
            half4 _MainColor;
            half _MainTex_PannerU;
            half _MainTex_PannerV;
            half _MaskTex_PannerU;
            half _MaskTex_PannerV;      
            half4 _MaskTex_ST;
            half4 _DissolveTex_ST;
            half _DissolveFactor;
            half _DissolveWidth;
            half _WarpFactor;
            half _WarpDeltaTime;
            half _UseCustomData;
            CBUFFER_END

            struct appdata
            {
                float4 vertex : POSITION;
                float4 color : COLOR;
                float4 uv : TEXCOORD0;
                float4 customData1 : TEXCOORD1; //if need Particle System CustomData
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float4 vertexCol : COLOR;
                float4 uv1 : TEXCOORD0; //MainTex uv
                float4 customData1 : TEXCOORD1;
                #ifdef _USE_MASK
                float2 uv2 : TEXCOORD2; //Mask uv
                #endif
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            #define _BILLBOARD_ON
            v2f EffectVert (appdata v)
            {
                v2f o;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_TRANSFER_INSTANCE_ID(v, o);
            
                o.vertex = TransformObjectToHClip(v.vertex.xyz);
                o.vertexCol = v.color;
                //half2 uv;
                //GetParticleTexcoords(uv, v.uv.xy);
                o.uv1.xy = TRANSFORM_TEX(v.uv.xy, _MainTex);
                o.customData1 = v.customData1;
                #ifdef _USE_MASK
                o.uv2.xy = TRANSFORM_TEX(v.uv.xy, _MaskTex);
                #endif
                #ifdef _USE_PANNER
                o.uv1.xy += _Time.y * float2(_MainTex_PannerU, _MainTex_PannerV);
                    #ifdef _USE_MASK
                    o.uv2 += _Time.y * float2(_MaskTex_PannerU, _MaskTex_PannerV);
                    #endif
                #endif

                return o;
            }

            half4 EffectFrag (v2f i) : SV_Target
            {
                UNITY_SETUP_INSTANCE_ID(i);
                #ifdef _USE_WARPING
                half4 noise = SAMPLE_TEXTURE2D(_WarpTex, sampler_WarpTex, i.uv1.xy + _Time.xy * _WarpDeltaTime);
                i.uv1.xy += noise.xy * _WarpFactor;
                #endif
                // sample the texture
                half4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv1.xy) * _MainColor;
                col *= saturate(i.vertexCol);
               
                #ifdef _USE_MASK
                //col.rgb = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex,i.uv2);
                col.a = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex,i.uv2).r;
                #endif
               
                #ifdef _USE_DISSOLVE
                half dissolveTex =  SAMPLE_TEXTURE2D(_DissolveTex, sampler_DissolveTex,i.uv1.xy);
                //_DissolveFactor = i.uv1.x;
                half dissolveL = _DissolveFactor;
                dissolveL = lerp(_DissolveFactor, i.customData1.x, _UseCustomData);
                dissolveL *= 1 + _DissolveWidth;
                half2 dissolveRange = half2(saturate((dissolveL - _DissolveWidth) ),
                                            saturate(dissolveL ));
                col.a *= smoothstep(dissolveRange.x, dissolveRange.y, dissolveTex);
                #endif
                //clip(col.a-0.01);
                return col;
            }
            ENDHLSL
        }
    }
    CustomEditor "EffectShaderGUI"
}
editor:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class EffectShaderGUI : ShaderGUI
{
    Material Mat;
    MaterialProperty _MainTex, _MainColor;
    bool usePanner;
    bool useMainTexPanner;
    MaterialProperty _UseMainTexPanner, _MainTex_PannerU,_MainTex_PannerV;

    bool useMask, useMaskPanner;
    MaterialProperty _MaskTex, _UseMaskTexPanner, _MaskTex_PannerU, _MaskTex_PannerV;

    bool useDissolve;
    MaterialProperty _DissolveTex, _DissolveFactor, _DissolveWidth;

    bool useWarping;
    MaterialProperty _WarpTex, _WarpFactor, _WarpDeltaTime;

    bool useCustomData;
    MaterialProperty _UseCustomData;

    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
    {
        this.Mat = materialEditor.target as Material;

        GUILayout.Button("Common Effect Shader");
        //usePanner = useMainTexPanner || useMaskPanner;
        usePanner = Mat.IsKeywordEnabled("_USE_PANNER");

        //Main Texture
        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
        MaterialProperty _MainTex = FindProperty("_MainTex", props);
        materialEditor.ShaderProperty(_MainTex, "Main Texture");
        MaterialProperty _MainColor = FindProperty("_MainColor", props);
        materialEditor.ShaderProperty(_MainColor, "Main Color");

        useMainTexPanner = Mat.GetInt("_UseMainTexPanner") > 0.5 ? true : false;
        useMainTexPanner = EditorGUILayout.Toggle("MainTex UV Panner", useMainTexPanner);
        if(useMainTexPanner)
        {
            usePanner = true;
            Mat.SetInt("_UseMainTexPanner", 1);
            
            _MainTex_PannerU = FindProperty("_MainTex_PannerU", props);
            _MainTex_PannerV = FindProperty("_MainTex_PannerV", props);
            materialEditor.ShaderProperty(_MainTex_PannerU, "Pannar u");
            materialEditor.ShaderProperty(_MainTex_PannerV, "Pannar v");
        }
        else
        {
            Mat.SetInt("_UseMainTexPanner", 0);
            Mat.SetFloat("_MainTex_PannerU", 0.0f);
            Mat.SetFloat("_MainTex_PannerV", 0.0f);
        }
        EditorGUILayout.EndVertical();

        //Mask
        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
        useMask = Mat.IsKeywordEnabled("_USE_MASK");
        useMask = EditorGUILayout.Toggle("Mask", useMask);
        if(useMask)
        {
            Mat.EnableKeyword("_USE_MASK");
            _MaskTex = FindProperty("_MaskTex", props);
            materialEditor.ShaderProperty(_MaskTex, "Mask Texture");

            useMaskPanner = Mat.GetInt("_UseMaskTexPanner") > 0.5 ? true : false;
            useMaskPanner = EditorGUILayout.Toggle("MaskTex UV Panner", useMaskPanner);
            if(useMaskPanner)
            {
                usePanner = true;
                Mat.SetInt("_UseMaskTexPanner", 1);
               
                _MaskTex_PannerU = FindProperty("_MaskTex_PannerU", props);
                _MaskTex_PannerV = FindProperty("_MaskTex_PannerV", props);
                materialEditor.ShaderProperty(_MaskTex_PannerU, "Pannar u");
                materialEditor.ShaderProperty(_MaskTex_PannerV, "Pannar v");
            }
            else
            {
                Mat.SetInt("_UseMaskTexPanner", 0);
                Mat.SetFloat("_MaskTex_PannerU", 0.0f);
                Mat.SetFloat("_MaskTex_PannerV", 0.0f);
            }
        }
        else
        {
            Mat.DisableKeyword("_USE_MASK");
        }
        EditorGUILayout.EndVertical();

        //Dissolve
        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
        useDissolve = Mat.IsKeywordEnabled("_USE_DISSOLVE");
        useDissolve = EditorGUILayout.Toggle("Dissolve", useDissolve);
        if(useDissolve)
        {
            Mat.EnableKeyword("_USE_DISSOLVE");
            _DissolveTex = FindProperty("_DissolveTex", props);
            materialEditor.ShaderProperty(_DissolveTex, "Dissolve Texture");

            //if need ParticleSystem Custom data
            useCustomData = Mat.GetInt("_UseCustomData") > 0.5 ? true : false;
            useCustomData = EditorGUILayout.Toggle("PS CustomData", useCustomData);  
            if(useCustomData)
            {
                Mat.SetInt("_UseCustomData", 1);
            }
            else
            {
                Mat.SetInt("_UseCustomData", 0);
                _DissolveFactor = FindProperty("_DissolveFactor", props);
                materialEditor.ShaderProperty(_DissolveFactor, "Dissolve Range");
            }
            _DissolveWidth = FindProperty("_DissolveWidth", props);
            materialEditor.ShaderProperty(_DissolveWidth, "Dissolve Soft Edge");
           
        }
        else
        {
            Mat.DisableKeyword("_USE_DISSOLVE");
        }
        EditorGUILayout.EndVertical();
        
        //Warping
        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
        useWarping = Mat.IsKeywordEnabled("_USE_WARPING");
        useWarping = EditorGUILayout.Toggle("Warping", useWarping);
        if(useWarping)
        {
            Mat.EnableKeyword("_USE_WARPING");
            _WarpTex = FindProperty("_WarpTex", props);
            materialEditor.ShaderProperty(_WarpTex, "Warping Texture");
            _WarpFactor = FindProperty("_WarpFactor", props);
            materialEditor.ShaderProperty(_WarpFactor, "Warping Factor");
            _WarpDeltaTime = FindProperty("_WarpDeltaTime", props);
            materialEditor.ShaderProperty(_WarpDeltaTime, "Speed");            
        }
        else
        {
            Mat.DisableKeyword("_USE_WARPING");
        }
        EditorGUILayout.EndVertical();

        if(usePanner)
        {
            Mat.EnableKeyword("_USE_PANNER");
        }
        else
        {
            Mat.DisableKeyword("_USE_PANNER");
        }

        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
        materialEditor.RenderQueueField();
        EditorGUILayout.EndVertical();

    }
}
有个问题是不知道是我叠加不对还是什么bug,当时用unity的particle system时间轴控制颜色透明度,总觉得最后透明度乘的结果很奇怪,仿佛乘的不是1是255,但是后来又复现不出来这个问题了。。。算了润了。

爆炸效果

年轻的我以为随便做个效果应该很简单吧,拖到ddl前一天晚上才开做。
惨不忍睹的第一版,美术向的mentor看了给我塞了几个视频,好好康康别人咋做的。
左挑右改折腾到晚上三点终于做完了
我爹的评价:感觉不如...页游
美术也太难了!可恶


https://www.zhihu.com/video/1554838298438328320

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 11:40 , Processed in 0.092103 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表