文章目录
- 环境
- SoftParticleCommon.cg
- Alpha blend
- Additive blend
- UniformSetSoftParticleThreshold.cs
- CustomGraphicsSettings.cs
- 查看 SetGlobalKW
- SoftParticleToggle.cs
- 遇到的坑 _InvFade 默认值修改未 10.0 来避坑
Talk is Cheap, Show me your CODE!
环境
Unity : 2018.2.11f1 Pipeline : BRP
SoftParticleCommon.cg#ifndef __SOFT_PARTICLE_COMMON_H__
#define __SOFT_PARTICLE_COMMON_H__
// jave.lin 2021/02/28
#include "UnityCG.cginc"
#if defined(_SOFT_PARTICLE_ON)
#if defined(_SOFT_PARTICLE_DEPTH_MAP_DEF_ON)
sampler2D _CameraDepthTexture;
#endif
// https://github.com/TwoTailsGames/Unity-Built-in-Shaders/blob/master/DefaultResourcesExtra/Particle%20AddMultiply.shader
half _InvFade; // _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
#define SOFT_PARTICLE_V2F(idx) float4 projPos : TEXCOORD##idx;
#define SOFT_PARTICLE_VERT(o) \
o.projPos = ComputeScreenPos(o.vertex); \
COMPUTE_EYEDEPTH(o.projPos.z);
#define COMPUTE_EYEDEPTH1(o, objVertex) o = -UnityObjectToViewPos( objVertex ).z
#define SOFT_PARTICLE_VERT1(o, vertex) \
o.projPos = ComputeScreenPos(vertex); \
COMPUTE_EYEDEPTH(o.projPos.z);
#define SOFT_PARTICLE_VERT2(o, vertex, objVertex) \
o.projPos = ComputeScreenPos(vertex); \
COMPUTE_EYEDEPTH1(o.projPos.z, objVertex);
#define SOFT_PARTICLE_FRAG_FADE(i, out_v) \
fixed offSP = step(10.0, _InvFade); \
out_v = saturate(_InvFade * (LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos))) - i.projPos.z)); \
out_v = lerp(out_v, 1.0, offSP);
#else
#define SOFT_PARTICLE_V2F(idx)
#define SOFT_PARTICLE_VERT(o)
#define SOFT_PARTICLE_VERT1(o, vertex)
#define SOFT_PARTICLE_FRAG_FADE(i, out_v) out_v = 1.0;
#endif
#endif
意思有两句 fixed offSP = step(10.0, _InvFade);
和 out_v = lerp(out_v, 1.0, offSP);
是为了避免由些特效同学再制作 UI 特效的时候没效果 UI 特效的 BUG
这里我就不使用变体了,计算量不算大,直接 step, lerp 来伪分支即可
Alpha blendsoft particle fade 主要用于 alpha 通道即可
Shader "cgwell/Alpha Blended"
{
Properties
{
_TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
_MainTex ("Particle Texture", 2D) = "white" {}
[HideInInspector]_Center ("Center",Vector) = (0,0,0,1)
[HideInInspector]_Scale ("Scale",Vector) = (1,1,1,1)
[HideInInspector]_Normal ("Normal",Vector) = (0,0,1,0)
_InvFade("Soft Particles Factor", Range(0.01,10.0)) = 10.0 //1.0
}
Category
{
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
Cull Off Lighting Off ZWrite Off Fog { Mode Off}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#pragma multi_compile _ _SOFT_PARTICLE_ON
//#define _SOFT_PARTICLE_ON
#define _SOFT_PARTICLE_DEPTH_MAP_DEF_ON
#include "UnityCG.cginc"
#include "../../../Shaders/Includes/CG/SoftParticleCommon.cginc"
sampler2D _MainTex;
fixed4 _TintColor;
struct appdata_t
{
float4 vertex : POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
SOFT_PARTICLE_V2F(1)
};
float4 _MainTex_ST;
float4 _Center;
float4 _Scale;
float4 _Normal;
uniform float4x4 _Camera2World;
v2f vert (appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.color = v.color;
o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
SOFT_PARTICLE_VERT(o)
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float fade;
SOFT_PARTICLE_FRAG_FADE(i, fade)
fixed4 col = saturate(2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord));
col.a *= fade;
return col;
}
ENDCG
}
}
}
}
Additive blend
主要是减少亮度,也就是 RGB 整体降低
Shader "cgwell/Dissolution_Add" {
Properties {
_TintColor ("Diffuse Color", Color) = (0.6985294,0.6985294,0.6985294,1)
_MainTex ("Diffuse Texture", 2D) = "white" {}
_N_mask ("N_mask", Float ) = 0.3
_MaskTexture ("Mask Texture", 2D) = "white" {}
_C_BYcolor ("C_BYcolor", Color) = (1,0,0,1)
_N_BY_QD ("N_BY_QD", Float ) = 3
_N_BY_KD ("N_BY_KD", Float ) = 0.01
[HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
_InvFade("Soft Particles Factor", Range(0.01,3.0)) = 10.0 //1.0
}
SubShader {
Tags {
"IgnoreProjector"="True"
"Queue"="Transparent"
"RenderType"="Transparent"
}
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
Blend One One
ZWrite Off
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//#define UNITY_PASS_FORWARDBASE
#include "UnityCG.cginc"
#include "../../../Shaders/Includes/CG/SoftParticleCommon.cginc"
#pragma multi_compile _ _SOFT_PARTICLE_ON
//#define _SOFT_PARTICLE_ON
#define _SOFT_PARTICLE_DEPTH_MAP_DEF_ON
#pragma target 3.0
uniform sampler2D _MaskTexture; uniform float4 _MaskTexture_ST;
uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
uniform float4 _TintColor;
uniform float _N_mask;
uniform float _N_BY_KD;
uniform float4 _C_BYcolor;
uniform float _N_BY_QD;
struct VertexInput {
float4 vertex : POSITION;
float2 texcoord0 : TEXCOORD0;
float4 vertexColor : COLOR;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
float4 vertexColor : COLOR;
SOFT_PARTICLE_V2F(1)
};
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.uv0 = v.texcoord0;
o.vertexColor = v.vertexColor;
o.pos = UnityObjectToClipPos(v.vertex );
SOFT_PARTICLE_VERT1(o, o.pos)
return o;
}
float4 frag(VertexOutput i) : COLOR {
float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex));
float vertColMulMask = (i.vertexColor.a * _N_mask);
float maskTexture_r = tex2D(_MaskTexture,TRANSFORM_TEX(i.uv0, _MaskTexture)).r;
float isMaskRGreaterThanVertColMulMask = step(vertColMulMask,maskTexture_r);
float isMaskRNotGreaterThanVertColMulMask = step(maskTexture_r,vertColMulMask);
float vertColMulMaskIsGreaterThan_MaskRPlus_N_BY_KD = step((maskTexture_r+_N_BY_KD),vertColMulMask);
float node_1274 = (isMaskRNotGreaterThanVertColMulMask-vertColMulMaskIsGreaterThan_MaskRPlus_N_BY_KD);
float node_6450 = (isMaskRNotGreaterThanVertColMulMask+node_1274);
float3 node_7666 = ((node_1274*_C_BYcolor.rgb)*_N_BY_QD);
float3 emissive = (_TintColor.a*(((_TintColor.rgb*_MainTex_var.rgb)*node_6450)+node_7666));
float3 finalColor = emissive + (_TintColor.a*node_7666);
float node_6644 = (_TintColor.a*(_MainTex_var.a*node_6450));
fixed4 col = saturate(fixed4(finalColor,node_6644));
float fade;
SOFT_PARTICLE_FRAG_FADE(i, fade)
col *= fade;
return col;
}
ENDCG
}
}
}
因为这些特效之前使用了比较多特效材质的 shader 都是每有这个 _InvFade("Soft Particles Factor", Range(0.01,3.0)) = 0.1 //1.0
属性的,并且优化之前我忘记将默认值线调整到一个看着比较好统一值
然后 _InvFade 都默认是 1.0 了,效果不是很好,如果需要对几千个特效的材质统一处理默认值未 0.1,那么这么多个材质,手动去调整肯定要死人,所以就写个工具批量处理一下即可
UniformSetSoftParticleThreshold.cs// jave.lin : 2022/03/01
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEditor;
using UnityEngine;
public class UniformSetSoftParticleThreshold : EditorWindow
{
private static int _InvFade = Shader.PropertyToID("_InvFade");
[MenuItem("Tools/统一调整所有SoftParticleThreshold...")]
public static void _Show()
{
var win = EditorWindow.GetWindow();
win.Show();
}
private float uniformValue = 0.1f;
private bool adjusting = false;
private int doingIDX = -1;
private int len = -1;
private bool error = false;
private int handlePerFrame = 5;
private List assetPaths;
private Stopwatch sw;
private void OnEnable()
{
if (assetPaths == null)
{
assetPaths = new List();
}
}
private void OnGUI()
{
uniformValue = EditorGUILayout.FloatField("Uniform SoftParticle Threshold", uniformValue);
const int min = 1, max = 20;
handlePerFrame = EditorGUILayout.IntSlider("Hanlde Per Frame", handlePerFrame, min, max);
var srcEnabled = GUI.enabled;
if (adjusting)
{
GUI.enabled = false;
}
if (GUILayout.Button("Adjust"))
{
var filterPaths = new string[]
{
"Assets/LuaFramework/Effect",
"Assets/LuaFramework/EffectNew"
};
if (assetPaths == null) assetPaths = new List();
else assetPaths.Clear();
foreach (var filterPath in filterPaths)
{
var guids = AssetDatabase.FindAssets("t:Material", new string[] { filterPath });
foreach (var guid in guids)
{
var assetPath = AssetDatabase.GUIDToAssetPath(guid);
assetPaths.Add(assetPath);
}
}
doingIDX = 0;
len = assetPaths.Count;
adjusting = true;
sw = new Stopwatch();
sw.Start();
UnityEngine.Debug.Log("Uniform SoftParticle Threshold Start!");
}
GUI.enabled = srcEnabled;
}
private void Update()
{
if (adjusting && assetPaths != null && assetPaths.Count > 0)
{
if (doingIDX == -1 && len == -1)
{
adjusting = false;
return;
}
if (doingIDX >= len)
{
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
adjusting = false;
sw.Stop();
UnityEngine.Debug.Log(
string.Format("Uniform SoftParticle Threshold Complete! handle:{0}, len:{1}, et:{2}",
doingIDX, len, sw.Elapsed
));
return;
}
var cancel = EditorUtility.DisplayCancelableProgressBar(
"Uniform SoftParticle Threshold",
string.Format("{0}/{1}", (doingIDX + 1), len),
(float)(doingIDX + 1) / len);
if (cancel)
{
adjusting = false;
sw.Stop();
UnityEngine.Debug.Log(
string.Format("Uniform SoftParticle Threshold Cancel! handle:{0}, len:{1}, et:{2}",
doingIDX, len, sw.Elapsed
));
return;
}
var n = handlePerFrame;
while (n-- > 0)
{
if (doingIDX >= len)
return;
var assetPath = assetPaths[doingIDX++];
try
{
var mat = AssetDatabase.LoadAssetAtPath(assetPath);
if (mat.HasProperty(_InvFade))
{
mat.SetFloat(_InvFade, uniformValue);
}
}
catch (System.Exception er)
{
error = true;
adjusting = false;
sw.Stop();
UnityEngine.Debug.Log(
string.Format("Uniform SoftParticle Threshold error, idx : {0}, len : {1}\nassetPath : {2}\nerror : \n{3}",
doingIDX, len, assetPath, er
));
}
}
}
}
}
CustomGraphicsSettings.cs
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
// jave.lin : 画质级别
public enum QualityLevel
{
Low = 1,
Middle = 2,
High = 3,
Ultra = 4,
}
public class CustomGraphicsSettings
{
public static void InitGraphicSetting()
{
SceneManager.activeSceneChanged -= Instance.OnActiveSceneChanged;
SceneManager.activeSceneChanged += Instance.OnActiveSceneChanged;
// 场景变更的回调,先调 activeSceneChanged, 再调 sceneLoaded; 比较反直觉。
// SceneManager.sceneLoaded -= Instance.OnSceneLoaded;
// SceneManager.sceneLoaded += Instance.OnSceneLoaded;
SceneManager.sceneUnloaded -= Instance.OnSceneUnloaded;
SceneManager.sceneUnloaded += Instance.OnSceneUnloaded;
Instance.srcShadows = QualitySettings.shadows;
Instance.srcAntiAliasing = QualitySettings.antiAliasing;
var powerSaveMode = PlayerPrefs.GetInt(kPowerSaveModeKey, 0) == 1;
PowerSaveMode = powerSaveMode;
var graphicsQualityLevel = Instance.GetGraphicsQualityLevel();
GraphicsQualityLevel = graphicsQualityLevel;
Instance.DeviceAdapterQualityLevel = GraphicsQualityLevel;
}
public static bool PowerSaveMode
{
get
{
return Application.targetFrameRate = 2500 &&
SystemInfo.processorCount >= 8 &&
SystemInfo.systemMemorySize >= (6 * 1024) &&
SystemInfo.graphicsMemorySize >= (2 * 1024) &&
SystemInfo.graphicsShaderLevel >= 30 &&
SystemInfo.graphicsMultiThreaded &&
SystemInfo.supportsShadows &&
SystemInfo.supportsInstancing &&
SystemInfo.supports32bitsIndexBuffer
)
{
return QualityLevel.Ultra;
}
else if (SystemInfo.processorFrequency >= 2000 &&
SystemInfo.processorCount >= 4 &&
SystemInfo.systemMemorySize >= (4 * 1024) &&
SystemInfo.graphicsMemorySize >= (1 * 1024) &&
SystemInfo.graphicsShaderLevel >= 20
)
{
return QualityLevel.High;
}
else if (SystemInfo.processorFrequency >= 1500 &&
SystemInfo.processorCount >= 2 &&
SystemInfo.systemMemorySize >= (2 * 1024) &&
SystemInfo.graphicsMemorySize >= (512) &&
SystemInfo.graphicsShaderLevel >= 10
)
{
return QualityLevel.Middle;
}
else
{
return QualityLevel.Low;
}
}
private QualityLevel GetGraphicsQualityLevel()
{
var val = PlayerPrefs.GetInt(kGraphicsQualityLevelKey, -1);
if (val == -1)
{
return AnalysicDeviceLevel();
}
else
{
return (QualityLevel)val;
}
}
///
/// 设置图像等级
///
/// [1, 4],等级越高,图形效果越好
private void SetGraphicsQualityLevel(QualityLevel level)
{
SetGraphicsTier(level);
SetResolutionAndShaderLOD(level);
SetAntiAliasing(level);
SetLigthMapUsage(level);
SetShadow(level);
SetGlobalKW(level);
}
private void SetLigthMapUsage(QualityLevel level)
{
if (level >= QualityLevel.High)
{
var datas = CreateCurLightMapsData(SceneManager.GetActiveScene().name);
var len = datas != null ? datas.Length : 0;
var newLightMapDatas = new LightmapData[len];
for (int i = 0; i = QualityLevel.High)
{
QualitySettings.antiAliasing = srcAntiAliasing;
}
else
{
QualitySettings.antiAliasing = 0;
}
}
private void SetGraphicsTier(QualityLevel level)
{
switch(level)
{
case QualityLevel.Low:
case QualityLevel.Middle:
Graphics.activeTier = GraphicsTier.Tier1;
break;
case QualityLevel.High:
Graphics.activeTier = GraphicsTier.Tier2;
break;
case QualityLevel.Ultra:
Graphics.activeTier = GraphicsTier.Tier3;
break;
}
}
private void SetResolutionAndShaderLOD(QualityLevel level)
{
switch (level)
{
case QualityLevel.Low:
QualitySettings.resolutionScalingFixedDPIFactor = 0.75f;
Shader.globalMaximumLOD = 200;
QualitySettings.masterTextureLimit = DeviceAdapterQualityLevel
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?