一般通过unity特效shader
是实习的第一个作业,贼菜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" {}
_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
页:
[1]