SFX added

This commit is contained in:
2023-08-06 16:46:05 +05:30
parent a0ebd1d3f3
commit 50a2bec854
61 changed files with 35177 additions and 34198 deletions

View File

@@ -1,275 +1,275 @@
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
using System.Collections.Generic;
using System.IO;
// Parse conditional expressions from CFXR_MaterialInspector to show/hide some parts of the UI easily
namespace CartoonFX
{
public static class ExpressionParser
{
public delegate bool EvaluateFunction(string content);
//--------------------------------------------------------------------------------------------------------------------------------
// Main Function to use
static public bool EvaluateExpression(string expression, EvaluateFunction evalFunction)
{
//Remove white spaces and double && ||
string cleanExpr = "";
for(int i = 0; i < expression.Length; i++)
{
switch(expression[i])
{
case ' ': break;
case '&': cleanExpr += expression[i]; i++; break;
case '|': cleanExpr += expression[i]; i++; break;
default: cleanExpr += expression[i]; break;
}
}
List<Token> tokens = new List<Token>();
StringReader reader = new StringReader(cleanExpr);
Token t = null;
do
{
t = new Token(reader);
tokens.Add(t);
} while(t.type != Token.TokenType.EXPR_END);
List<Token> polishNotation = Token.TransformToPolishNotation(tokens);
var enumerator = polishNotation.GetEnumerator();
enumerator.MoveNext();
Expression root = MakeExpression(ref enumerator, evalFunction);
return root.Evaluate();
}
//--------------------------------------------------------------------------------------------------------------------------------
// Expression Token
public class Token
{
static Dictionary<char, KeyValuePair<TokenType, string>> typesDict = new Dictionary<char, KeyValuePair<TokenType, string>>()
{
{'(', new KeyValuePair<TokenType, string>(TokenType.OPEN_PAREN, "(")},
{')', new KeyValuePair<TokenType, string>(TokenType.CLOSE_PAREN, ")")},
{'!', new KeyValuePair<TokenType, string>(TokenType.UNARY_OP, "NOT")},
{'&', new KeyValuePair<TokenType, string>(TokenType.BINARY_OP, "AND")},
{'|', new KeyValuePair<TokenType, string>(TokenType.BINARY_OP, "OR")}
};
public enum TokenType
{
OPEN_PAREN,
CLOSE_PAREN,
UNARY_OP,
BINARY_OP,
LITERAL,
EXPR_END
}
public TokenType type;
public string value;
public Token(StringReader s)
{
int c = s.Read();
if(c == -1)
{
type = TokenType.EXPR_END;
value = "";
return;
}
char ch = (char)c;
//Special case: solve bug where !COND_FALSE_1 && COND_FALSE_2 would return True
bool embeddedNot = (ch == '!' && s.Peek() != '(');
if(typesDict.ContainsKey(ch) && !embeddedNot)
{
type = typesDict[ch].Key;
value = typesDict[ch].Value;
}
else
{
string str = "";
str += ch;
while(s.Peek() != -1 && !typesDict.ContainsKey((char)s.Peek()))
{
str += (char)s.Read();
}
type = TokenType.LITERAL;
value = str;
}
}
static public List<Token> TransformToPolishNotation(List<Token> infixTokenList)
{
Queue<Token> outputQueue = new Queue<Token>();
Stack<Token> stack = new Stack<Token>();
int index = 0;
while(infixTokenList.Count > index)
{
Token t = infixTokenList[index];
switch(t.type)
{
case Token.TokenType.LITERAL:
outputQueue.Enqueue(t);
break;
case Token.TokenType.BINARY_OP:
case Token.TokenType.UNARY_OP:
case Token.TokenType.OPEN_PAREN:
stack.Push(t);
break;
case Token.TokenType.CLOSE_PAREN:
while(stack.Peek().type != Token.TokenType.OPEN_PAREN)
{
outputQueue.Enqueue(stack.Pop());
}
stack.Pop();
if(stack.Count > 0 && stack.Peek().type == Token.TokenType.UNARY_OP)
{
outputQueue.Enqueue(stack.Pop());
}
break;
default:
break;
}
index++;
}
while(stack.Count > 0)
{
outputQueue.Enqueue(stack.Pop());
}
var list = new List<Token>(outputQueue);
list.Reverse();
return list;
}
}
//--------------------------------------------------------------------------------------------------------------------------------
// Boolean Expression Classes
public abstract class Expression
{
public abstract bool Evaluate();
}
public class ExpressionLeaf : Expression
{
private string content;
private EvaluateFunction evalFunction;
public ExpressionLeaf(EvaluateFunction _evalFunction, string _content)
{
this.evalFunction = _evalFunction;
this.content = _content;
}
override public bool Evaluate()
{
//embedded not, see special case in Token declaration
if(content.StartsWith("!"))
{
return !this.evalFunction(content.Substring(1));
}
return this.evalFunction(content);
}
}
public class ExpressionAnd : Expression
{
private Expression left;
private Expression right;
public ExpressionAnd(Expression _left, Expression _right)
{
this.left = _left;
this.right = _right;
}
override public bool Evaluate()
{
return left.Evaluate() && right.Evaluate();
}
}
public class ExpressionOr : Expression
{
private Expression left;
private Expression right;
public ExpressionOr(Expression _left, Expression _right)
{
this.left = _left;
this.right = _right;
}
override public bool Evaluate()
{
return left.Evaluate() || right.Evaluate();
}
}
public class ExpressionNot : Expression
{
private Expression expr;
public ExpressionNot(Expression _expr)
{
this.expr = _expr;
}
override public bool Evaluate()
{
return !expr.Evaluate();
}
}
static public Expression MakeExpression(ref List<Token>.Enumerator polishNotationTokensEnumerator, EvaluateFunction _evalFunction)
{
if(polishNotationTokensEnumerator.Current.type == Token.TokenType.LITERAL)
{
Expression lit = new ExpressionLeaf(_evalFunction, polishNotationTokensEnumerator.Current.value);
polishNotationTokensEnumerator.MoveNext();
return lit;
}
else
{
if(polishNotationTokensEnumerator.Current.value == "NOT")
{
polishNotationTokensEnumerator.MoveNext();
Expression operand = MakeExpression(ref polishNotationTokensEnumerator, _evalFunction);
return new ExpressionNot(operand);
}
else if(polishNotationTokensEnumerator.Current.value == "AND")
{
polishNotationTokensEnumerator.MoveNext();
Expression left = MakeExpression(ref polishNotationTokensEnumerator, _evalFunction);
Expression right = MakeExpression(ref polishNotationTokensEnumerator, _evalFunction);
return new ExpressionAnd(left, right);
}
else if(polishNotationTokensEnumerator.Current.value == "OR")
{
polishNotationTokensEnumerator.MoveNext();
Expression left = MakeExpression(ref polishNotationTokensEnumerator, _evalFunction);
Expression right = MakeExpression(ref polishNotationTokensEnumerator, _evalFunction);
return new ExpressionOr(left, right);
}
}
return null;
}
}
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
using System.Collections.Generic;
using System.IO;
// Parse conditional expressions from CFXR_MaterialInspector to show/hide some parts of the UI easily
namespace CartoonFX
{
public static class ExpressionParser
{
public delegate bool EvaluateFunction(string content);
//--------------------------------------------------------------------------------------------------------------------------------
// Main Function to use
static public bool EvaluateExpression(string expression, EvaluateFunction evalFunction)
{
//Remove white spaces and double && ||
string cleanExpr = "";
for(int i = 0; i < expression.Length; i++)
{
switch(expression[i])
{
case ' ': break;
case '&': cleanExpr += expression[i]; i++; break;
case '|': cleanExpr += expression[i]; i++; break;
default: cleanExpr += expression[i]; break;
}
}
List<Token> tokens = new List<Token>();
StringReader reader = new StringReader(cleanExpr);
Token t = null;
do
{
t = new Token(reader);
tokens.Add(t);
} while(t.type != Token.TokenType.EXPR_END);
List<Token> polishNotation = Token.TransformToPolishNotation(tokens);
var enumerator = polishNotation.GetEnumerator();
enumerator.MoveNext();
Expression root = MakeExpression(ref enumerator, evalFunction);
return root.Evaluate();
}
//--------------------------------------------------------------------------------------------------------------------------------
// Expression Token
public class Token
{
static Dictionary<char, KeyValuePair<TokenType, string>> typesDict = new Dictionary<char, KeyValuePair<TokenType, string>>()
{
{'(', new KeyValuePair<TokenType, string>(TokenType.OPEN_PAREN, "(")},
{')', new KeyValuePair<TokenType, string>(TokenType.CLOSE_PAREN, ")")},
{'!', new KeyValuePair<TokenType, string>(TokenType.UNARY_OP, "NOT")},
{'&', new KeyValuePair<TokenType, string>(TokenType.BINARY_OP, "AND")},
{'|', new KeyValuePair<TokenType, string>(TokenType.BINARY_OP, "OR")}
};
public enum TokenType
{
OPEN_PAREN,
CLOSE_PAREN,
UNARY_OP,
BINARY_OP,
LITERAL,
EXPR_END
}
public TokenType type;
public string value;
public Token(StringReader s)
{
int c = s.Read();
if(c == -1)
{
type = TokenType.EXPR_END;
value = "";
return;
}
char ch = (char)c;
//Special case: solve bug where !COND_FALSE_1 && COND_FALSE_2 would return True
bool embeddedNot = (ch == '!' && s.Peek() != '(');
if(typesDict.ContainsKey(ch) && !embeddedNot)
{
type = typesDict[ch].Key;
value = typesDict[ch].Value;
}
else
{
string str = "";
str += ch;
while(s.Peek() != -1 && !typesDict.ContainsKey((char)s.Peek()))
{
str += (char)s.Read();
}
type = TokenType.LITERAL;
value = str;
}
}
static public List<Token> TransformToPolishNotation(List<Token> infixTokenList)
{
Queue<Token> outputQueue = new Queue<Token>();
Stack<Token> stack = new Stack<Token>();
int index = 0;
while(infixTokenList.Count > index)
{
Token t = infixTokenList[index];
switch(t.type)
{
case Token.TokenType.LITERAL:
outputQueue.Enqueue(t);
break;
case Token.TokenType.BINARY_OP:
case Token.TokenType.UNARY_OP:
case Token.TokenType.OPEN_PAREN:
stack.Push(t);
break;
case Token.TokenType.CLOSE_PAREN:
while(stack.Peek().type != Token.TokenType.OPEN_PAREN)
{
outputQueue.Enqueue(stack.Pop());
}
stack.Pop();
if(stack.Count > 0 && stack.Peek().type == Token.TokenType.UNARY_OP)
{
outputQueue.Enqueue(stack.Pop());
}
break;
default:
break;
}
index++;
}
while(stack.Count > 0)
{
outputQueue.Enqueue(stack.Pop());
}
var list = new List<Token>(outputQueue);
list.Reverse();
return list;
}
}
//--------------------------------------------------------------------------------------------------------------------------------
// Boolean Expression Classes
public abstract class Expression
{
public abstract bool Evaluate();
}
public class ExpressionLeaf : Expression
{
private string content;
private EvaluateFunction evalFunction;
public ExpressionLeaf(EvaluateFunction _evalFunction, string _content)
{
this.evalFunction = _evalFunction;
this.content = _content;
}
override public bool Evaluate()
{
//embedded not, see special case in Token declaration
if(content.StartsWith("!"))
{
return !this.evalFunction(content.Substring(1));
}
return this.evalFunction(content);
}
}
public class ExpressionAnd : Expression
{
private Expression left;
private Expression right;
public ExpressionAnd(Expression _left, Expression _right)
{
this.left = _left;
this.right = _right;
}
override public bool Evaluate()
{
return left.Evaluate() && right.Evaluate();
}
}
public class ExpressionOr : Expression
{
private Expression left;
private Expression right;
public ExpressionOr(Expression _left, Expression _right)
{
this.left = _left;
this.right = _right;
}
override public bool Evaluate()
{
return left.Evaluate() || right.Evaluate();
}
}
public class ExpressionNot : Expression
{
private Expression expr;
public ExpressionNot(Expression _expr)
{
this.expr = _expr;
}
override public bool Evaluate()
{
return !expr.Evaluate();
}
}
static public Expression MakeExpression(ref List<Token>.Enumerator polishNotationTokensEnumerator, EvaluateFunction _evalFunction)
{
if(polishNotationTokensEnumerator.Current.type == Token.TokenType.LITERAL)
{
Expression lit = new ExpressionLeaf(_evalFunction, polishNotationTokensEnumerator.Current.value);
polishNotationTokensEnumerator.MoveNext();
return lit;
}
else
{
if(polishNotationTokensEnumerator.Current.value == "NOT")
{
polishNotationTokensEnumerator.MoveNext();
Expression operand = MakeExpression(ref polishNotationTokensEnumerator, _evalFunction);
return new ExpressionNot(operand);
}
else if(polishNotationTokensEnumerator.Current.value == "AND")
{
polishNotationTokensEnumerator.MoveNext();
Expression left = MakeExpression(ref polishNotationTokensEnumerator, _evalFunction);
Expression right = MakeExpression(ref polishNotationTokensEnumerator, _evalFunction);
return new ExpressionAnd(left, right);
}
else if(polishNotationTokensEnumerator.Current.value == "OR")
{
polishNotationTokensEnumerator.MoveNext();
Expression left = MakeExpression(ref polishNotationTokensEnumerator, _evalFunction);
Expression right = MakeExpression(ref polishNotationTokensEnumerator, _evalFunction);
return new ExpressionOr(left, right);
}
}
return null;
}
}
}

View File

@@ -1,362 +1,362 @@
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
using UnityEngine;
using UnityEditor;
// GUI Styles and UI methods
namespace CartoonFX
{
public static class Styles
{
//================================================================================================================================
// GUI Styles
//================================================================================================================================
//================================================================================================================================
// (x) close button
static GUIStyle _closeCrossButton;
public static GUIStyle CloseCrossButton
{
get
{
if(_closeCrossButton == null)
{
//Try to load GUISkin according to its GUID
//Assumes that its .meta file should always stick with it!
string guiSkinPath = AssetDatabase.GUIDToAssetPath("02d396fa782e5d7438e231ea9f8be23c");
var gs = AssetDatabase.LoadAssetAtPath<GUISkin>(guiSkinPath);
if(gs != null)
{
_closeCrossButton = System.Array.Find<GUIStyle>(gs.customStyles, x => x.name == "CloseCrossButton");
}
//Else fall back to minibutton
if(_closeCrossButton == null)
_closeCrossButton = EditorStyles.miniButton;
}
return _closeCrossButton;
}
}
//================================================================================================================================
// Shuriken Toggle with label alignment fix
static GUIStyle _shurikenToggle;
public static GUIStyle ShurikenToggle
{
get
{
if(_shurikenToggle == null)
{
_shurikenToggle = new GUIStyle("ShurikenToggle");
_shurikenToggle.fontSize = 9;
_shurikenToggle.contentOffset = new Vector2(16, -1);
if(EditorGUIUtility.isProSkin)
{
var textColor = new Color(.8f, .8f, .8f);
_shurikenToggle.normal.textColor = textColor;
_shurikenToggle.active.textColor = textColor;
_shurikenToggle.focused.textColor = textColor;
_shurikenToggle.hover.textColor = textColor;
_shurikenToggle.onNormal.textColor = textColor;
_shurikenToggle.onActive.textColor = textColor;
_shurikenToggle.onFocused.textColor = textColor;
_shurikenToggle.onHover.textColor = textColor;
}
}
return _shurikenToggle;
}
}
//================================================================================================================================
// Bold mini-label (the one from EditorStyles isn't actually "mini")
static GUIStyle _miniBoldLabel;
public static GUIStyle MiniBoldLabel
{
get
{
if(_miniBoldLabel == null)
{
_miniBoldLabel = new GUIStyle(EditorStyles.boldLabel);
_miniBoldLabel.fontSize = 10;
_miniBoldLabel.margin = new RectOffset(0, 0, 0, 0);
}
return _miniBoldLabel;
}
}
//================================================================================================================================
// Bold mini-foldout
static GUIStyle _miniBoldFoldout;
public static GUIStyle MiniBoldFoldout
{
get
{
if(_miniBoldFoldout == null)
{
_miniBoldFoldout = new GUIStyle(EditorStyles.foldout);
_miniBoldFoldout.fontSize = 10;
_miniBoldFoldout.fontStyle = FontStyle.Bold;
_miniBoldFoldout.margin = new RectOffset(0, 0, 0, 0);
}
return _miniBoldFoldout;
}
}
//================================================================================================================================
// Gray right-aligned label for Orderable List (Material Animator)
static GUIStyle _PropertyTypeLabel;
public static GUIStyle PropertyTypeLabel
{
get
{
if(_PropertyTypeLabel == null)
{
_PropertyTypeLabel = new GUIStyle(EditorStyles.label);
_PropertyTypeLabel.alignment = TextAnchor.MiddleRight;
_PropertyTypeLabel.normal.textColor = Color.gray;
_PropertyTypeLabel.fontSize = 9;
}
return _PropertyTypeLabel;
}
}
// Dark Gray right-aligned label for Orderable List (Material Animator)
static GUIStyle _PropertyTypeLabelFocused;
public static GUIStyle PropertyTypeLabelFocused
{
get
{
if(_PropertyTypeLabelFocused == null)
{
_PropertyTypeLabelFocused = new GUIStyle(EditorStyles.label);
_PropertyTypeLabelFocused.alignment = TextAnchor.MiddleRight;
_PropertyTypeLabelFocused.normal.textColor = new Color(.2f, .2f, .2f);
_PropertyTypeLabelFocused.fontSize = 9;
}
return _PropertyTypeLabelFocused;
}
}
//================================================================================================================================
// Rounded Box
static GUIStyle _roundedBox;
public static GUIStyle RoundedBox
{
get
{
if(_roundedBox == null)
{
_roundedBox = new GUIStyle(EditorStyles.helpBox);
}
return _roundedBox;
}
}
//================================================================================================================================
// Center White Label ("Editing Spline" label in Scene View)
static GUIStyle _CenteredWhiteLabel;
public static GUIStyle CenteredWhiteLabel
{
get
{
if(_CenteredWhiteLabel == null)
{
_CenteredWhiteLabel = new GUIStyle(EditorStyles.centeredGreyMiniLabel);
_CenteredWhiteLabel.fontSize = 20;
_CenteredWhiteLabel.normal.textColor = Color.white;
}
return _CenteredWhiteLabel;
}
}
//================================================================================================================================
// Used to draw lines for separators
static public GUIStyle _LineStyle;
static public GUIStyle LineStyle
{
get
{
if(_LineStyle == null)
{
_LineStyle = new GUIStyle();
_LineStyle.normal.background = EditorGUIUtility.whiteTexture;
_LineStyle.stretchWidth = true;
}
return _LineStyle;
}
}
//================================================================================================================================
// HelpBox with rich text formatting support
static GUIStyle _HelpBoxRichTextStyle;
static public GUIStyle HelpBoxRichTextStyle
{
get
{
if(_HelpBoxRichTextStyle == null)
{
_HelpBoxRichTextStyle = new GUIStyle("HelpBox");
_HelpBoxRichTextStyle.richText = true;
}
return _HelpBoxRichTextStyle;
}
}
//================================================================================================================================
// Material Blue Header
static public GUIStyle _MaterialHeaderStyle;
static public GUIStyle MaterialHeaderStyle
{
get
{
if(_MaterialHeaderStyle == null)
{
_MaterialHeaderStyle = new GUIStyle(EditorStyles.label);
_MaterialHeaderStyle.fontStyle = FontStyle.Bold;
_MaterialHeaderStyle.fontSize = 11;
_MaterialHeaderStyle.padding.top = 0;
_MaterialHeaderStyle.padding.bottom = 0;
_MaterialHeaderStyle.normal.textColor = EditorGUIUtility.isProSkin ? new Color32(75, 128, 255, 255) : new Color32(0, 50, 230, 255);
_MaterialHeaderStyle.stretchWidth = true;
}
return _MaterialHeaderStyle;
}
}
//================================================================================================================================
// Material Header emboss effect
static public GUIStyle _MaterialHeaderStyleHighlight;
static public GUIStyle MaterialHeaderStyleHighlight
{
get
{
if(_MaterialHeaderStyleHighlight == null)
{
_MaterialHeaderStyleHighlight = new GUIStyle(MaterialHeaderStyle);
_MaterialHeaderStyleHighlight.contentOffset = new Vector2(1, 1);
_MaterialHeaderStyleHighlight.normal.textColor = EditorGUIUtility.isProSkin ? new Color32(255, 255, 255, 16) : new Color32(255, 255, 255, 32);
}
return _MaterialHeaderStyleHighlight;
}
}
//================================================================================================================================
// Filled rectangle
static private GUIStyle _WhiteRectangleStyle;
static public void DrawRectangle(Rect position, Color color)
{
var col = GUI.color;
GUI.color *= color;
DrawRectangle(position);
GUI.color = col;
}
static public void DrawRectangle(Rect position)
{
if(_WhiteRectangleStyle == null)
{
_WhiteRectangleStyle = new GUIStyle();
_WhiteRectangleStyle.normal.background = EditorGUIUtility.whiteTexture;
}
if(Event.current != null && Event.current.type == EventType.Repaint)
{
_WhiteRectangleStyle.Draw(position, false, false, false, false);
}
}
//================================================================================================================================
// Methods
//================================================================================================================================
static public void DrawLine(float height = 2f)
{
DrawLine(Color.black, height);
}
static public void DrawLine(Color color, float height = 1f)
{
Rect position = GUILayoutUtility.GetRect(0f, float.MaxValue, height, height, LineStyle);
DrawLine(position, color);
}
static public void DrawLine(Rect position, Color color)
{
if(Event.current.type == EventType.Repaint)
{
Color orgColor = GUI.color;
GUI.color = orgColor * color;
LineStyle.Draw(position, false, false, false, false);
GUI.color = orgColor;
}
}
static public void MaterialDrawHeader(GUIContent guiContent)
{
var rect = GUILayoutUtility.GetRect(guiContent, MaterialHeaderStyle);
GUI.Label(rect, guiContent, MaterialHeaderStyleHighlight);
GUI.Label(rect, guiContent, MaterialHeaderStyle);
}
static public void MaterialDrawSeparator()
{
GUILayout.Space(4);
if(EditorGUIUtility.isProSkin)
DrawLine(new Color(.3f, .3f, .3f, 1f), 1);
else
DrawLine(new Color(.6f, .6f, .6f, 1f), 1);
GUILayout.Space(4);
}
static public void MaterialDrawSeparatorDouble()
{
GUILayout.Space(6);
if(EditorGUIUtility.isProSkin)
{
DrawLine(new Color(.1f, .1f, .1f, 1f), 1);
DrawLine(new Color(.4f, .4f, .4f, 1f), 1);
}
else
{
DrawLine(new Color(.3f, .3f, .3f, 1f), 1);
DrawLine(new Color(.9f, .9f, .9f, 1f), 1);
}
GUILayout.Space(6);
}
//built-in console icons, also used in help box
static Texture2D warnIcon;
static Texture2D infoIcon;
static Texture2D errorIcon;
static public void HelpBoxRichText(Rect position, string message, MessageType msgType)
{
Texture2D icon = null;
switch(msgType)
{
case MessageType.Warning: icon = warnIcon ?? (warnIcon = EditorGUIUtility.Load("console.warnicon") as Texture2D); break;
case MessageType.Info: icon = infoIcon ?? (infoIcon = EditorGUIUtility.Load("console.infoicon") as Texture2D); break;
case MessageType.Error: icon = errorIcon ?? (errorIcon = EditorGUIUtility.Load("console.erroricon") as Texture2D); break;
}
EditorGUI.LabelField(position, GUIContent.none, new GUIContent(message, icon), HelpBoxRichTextStyle);
}
static public void HelpBoxRichText(string message, MessageType msgType)
{
Texture2D icon = null;
switch(msgType)
{
case MessageType.Warning: icon = warnIcon ?? (warnIcon = EditorGUIUtility.Load("console.warnicon") as Texture2D); break;
case MessageType.Info: icon = infoIcon ?? (infoIcon = EditorGUIUtility.Load("console.infoicon") as Texture2D); break;
case MessageType.Error: icon = errorIcon ?? (errorIcon = EditorGUIUtility.Load("console.erroricon") as Texture2D); break;
}
EditorGUILayout.LabelField(GUIContent.none, new GUIContent(message, icon), HelpBoxRichTextStyle);
}
}
}
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
using UnityEngine;
using UnityEditor;
// GUI Styles and UI methods
namespace CartoonFX
{
public static class Styles
{
//================================================================================================================================
// GUI Styles
//================================================================================================================================
//================================================================================================================================
// (x) close button
static GUIStyle _closeCrossButton;
public static GUIStyle CloseCrossButton
{
get
{
if(_closeCrossButton == null)
{
//Try to load GUISkin according to its GUID
//Assumes that its .meta file should always stick with it!
string guiSkinPath = AssetDatabase.GUIDToAssetPath("02d396fa782e5d7438e231ea9f8be23c");
var gs = AssetDatabase.LoadAssetAtPath<GUISkin>(guiSkinPath);
if(gs != null)
{
_closeCrossButton = System.Array.Find<GUIStyle>(gs.customStyles, x => x.name == "CloseCrossButton");
}
//Else fall back to minibutton
if(_closeCrossButton == null)
_closeCrossButton = EditorStyles.miniButton;
}
return _closeCrossButton;
}
}
//================================================================================================================================
// Shuriken Toggle with label alignment fix
static GUIStyle _shurikenToggle;
public static GUIStyle ShurikenToggle
{
get
{
if(_shurikenToggle == null)
{
_shurikenToggle = new GUIStyle("ShurikenToggle");
_shurikenToggle.fontSize = 9;
_shurikenToggle.contentOffset = new Vector2(16, -1);
if(EditorGUIUtility.isProSkin)
{
var textColor = new Color(.8f, .8f, .8f);
_shurikenToggle.normal.textColor = textColor;
_shurikenToggle.active.textColor = textColor;
_shurikenToggle.focused.textColor = textColor;
_shurikenToggle.hover.textColor = textColor;
_shurikenToggle.onNormal.textColor = textColor;
_shurikenToggle.onActive.textColor = textColor;
_shurikenToggle.onFocused.textColor = textColor;
_shurikenToggle.onHover.textColor = textColor;
}
}
return _shurikenToggle;
}
}
//================================================================================================================================
// Bold mini-label (the one from EditorStyles isn't actually "mini")
static GUIStyle _miniBoldLabel;
public static GUIStyle MiniBoldLabel
{
get
{
if(_miniBoldLabel == null)
{
_miniBoldLabel = new GUIStyle(EditorStyles.boldLabel);
_miniBoldLabel.fontSize = 10;
_miniBoldLabel.margin = new RectOffset(0, 0, 0, 0);
}
return _miniBoldLabel;
}
}
//================================================================================================================================
// Bold mini-foldout
static GUIStyle _miniBoldFoldout;
public static GUIStyle MiniBoldFoldout
{
get
{
if(_miniBoldFoldout == null)
{
_miniBoldFoldout = new GUIStyle(EditorStyles.foldout);
_miniBoldFoldout.fontSize = 10;
_miniBoldFoldout.fontStyle = FontStyle.Bold;
_miniBoldFoldout.margin = new RectOffset(0, 0, 0, 0);
}
return _miniBoldFoldout;
}
}
//================================================================================================================================
// Gray right-aligned label for Orderable List (Material Animator)
static GUIStyle _PropertyTypeLabel;
public static GUIStyle PropertyTypeLabel
{
get
{
if(_PropertyTypeLabel == null)
{
_PropertyTypeLabel = new GUIStyle(EditorStyles.label);
_PropertyTypeLabel.alignment = TextAnchor.MiddleRight;
_PropertyTypeLabel.normal.textColor = Color.gray;
_PropertyTypeLabel.fontSize = 9;
}
return _PropertyTypeLabel;
}
}
// Dark Gray right-aligned label for Orderable List (Material Animator)
static GUIStyle _PropertyTypeLabelFocused;
public static GUIStyle PropertyTypeLabelFocused
{
get
{
if(_PropertyTypeLabelFocused == null)
{
_PropertyTypeLabelFocused = new GUIStyle(EditorStyles.label);
_PropertyTypeLabelFocused.alignment = TextAnchor.MiddleRight;
_PropertyTypeLabelFocused.normal.textColor = new Color(.2f, .2f, .2f);
_PropertyTypeLabelFocused.fontSize = 9;
}
return _PropertyTypeLabelFocused;
}
}
//================================================================================================================================
// Rounded Box
static GUIStyle _roundedBox;
public static GUIStyle RoundedBox
{
get
{
if(_roundedBox == null)
{
_roundedBox = new GUIStyle(EditorStyles.helpBox);
}
return _roundedBox;
}
}
//================================================================================================================================
// Center White Label ("Editing Spline" label in Scene View)
static GUIStyle _CenteredWhiteLabel;
public static GUIStyle CenteredWhiteLabel
{
get
{
if(_CenteredWhiteLabel == null)
{
_CenteredWhiteLabel = new GUIStyle(EditorStyles.centeredGreyMiniLabel);
_CenteredWhiteLabel.fontSize = 20;
_CenteredWhiteLabel.normal.textColor = Color.white;
}
return _CenteredWhiteLabel;
}
}
//================================================================================================================================
// Used to draw lines for separators
static public GUIStyle _LineStyle;
static public GUIStyle LineStyle
{
get
{
if(_LineStyle == null)
{
_LineStyle = new GUIStyle();
_LineStyle.normal.background = EditorGUIUtility.whiteTexture;
_LineStyle.stretchWidth = true;
}
return _LineStyle;
}
}
//================================================================================================================================
// HelpBox with rich text formatting support
static GUIStyle _HelpBoxRichTextStyle;
static public GUIStyle HelpBoxRichTextStyle
{
get
{
if(_HelpBoxRichTextStyle == null)
{
_HelpBoxRichTextStyle = new GUIStyle("HelpBox");
_HelpBoxRichTextStyle.richText = true;
}
return _HelpBoxRichTextStyle;
}
}
//================================================================================================================================
// Material Blue Header
static public GUIStyle _MaterialHeaderStyle;
static public GUIStyle MaterialHeaderStyle
{
get
{
if(_MaterialHeaderStyle == null)
{
_MaterialHeaderStyle = new GUIStyle(EditorStyles.label);
_MaterialHeaderStyle.fontStyle = FontStyle.Bold;
_MaterialHeaderStyle.fontSize = 11;
_MaterialHeaderStyle.padding.top = 0;
_MaterialHeaderStyle.padding.bottom = 0;
_MaterialHeaderStyle.normal.textColor = EditorGUIUtility.isProSkin ? new Color32(75, 128, 255, 255) : new Color32(0, 50, 230, 255);
_MaterialHeaderStyle.stretchWidth = true;
}
return _MaterialHeaderStyle;
}
}
//================================================================================================================================
// Material Header emboss effect
static public GUIStyle _MaterialHeaderStyleHighlight;
static public GUIStyle MaterialHeaderStyleHighlight
{
get
{
if(_MaterialHeaderStyleHighlight == null)
{
_MaterialHeaderStyleHighlight = new GUIStyle(MaterialHeaderStyle);
_MaterialHeaderStyleHighlight.contentOffset = new Vector2(1, 1);
_MaterialHeaderStyleHighlight.normal.textColor = EditorGUIUtility.isProSkin ? new Color32(255, 255, 255, 16) : new Color32(255, 255, 255, 32);
}
return _MaterialHeaderStyleHighlight;
}
}
//================================================================================================================================
// Filled rectangle
static private GUIStyle _WhiteRectangleStyle;
static public void DrawRectangle(Rect position, Color color)
{
var col = GUI.color;
GUI.color *= color;
DrawRectangle(position);
GUI.color = col;
}
static public void DrawRectangle(Rect position)
{
if(_WhiteRectangleStyle == null)
{
_WhiteRectangleStyle = new GUIStyle();
_WhiteRectangleStyle.normal.background = EditorGUIUtility.whiteTexture;
}
if(Event.current != null && Event.current.type == EventType.Repaint)
{
_WhiteRectangleStyle.Draw(position, false, false, false, false);
}
}
//================================================================================================================================
// Methods
//================================================================================================================================
static public void DrawLine(float height = 2f)
{
DrawLine(Color.black, height);
}
static public void DrawLine(Color color, float height = 1f)
{
Rect position = GUILayoutUtility.GetRect(0f, float.MaxValue, height, height, LineStyle);
DrawLine(position, color);
}
static public void DrawLine(Rect position, Color color)
{
if(Event.current.type == EventType.Repaint)
{
Color orgColor = GUI.color;
GUI.color = orgColor * color;
LineStyle.Draw(position, false, false, false, false);
GUI.color = orgColor;
}
}
static public void MaterialDrawHeader(GUIContent guiContent)
{
var rect = GUILayoutUtility.GetRect(guiContent, MaterialHeaderStyle);
GUI.Label(rect, guiContent, MaterialHeaderStyleHighlight);
GUI.Label(rect, guiContent, MaterialHeaderStyle);
}
static public void MaterialDrawSeparator()
{
GUILayout.Space(4);
if(EditorGUIUtility.isProSkin)
DrawLine(new Color(.3f, .3f, .3f, 1f), 1);
else
DrawLine(new Color(.6f, .6f, .6f, 1f), 1);
GUILayout.Space(4);
}
static public void MaterialDrawSeparatorDouble()
{
GUILayout.Space(6);
if(EditorGUIUtility.isProSkin)
{
DrawLine(new Color(.1f, .1f, .1f, 1f), 1);
DrawLine(new Color(.4f, .4f, .4f, 1f), 1);
}
else
{
DrawLine(new Color(.3f, .3f, .3f, 1f), 1);
DrawLine(new Color(.9f, .9f, .9f, 1f), 1);
}
GUILayout.Space(6);
}
//built-in console icons, also used in help box
static Texture2D warnIcon;
static Texture2D infoIcon;
static Texture2D errorIcon;
static public void HelpBoxRichText(Rect position, string message, MessageType msgType)
{
Texture2D icon = null;
switch(msgType)
{
case MessageType.Warning: icon = warnIcon ?? (warnIcon = EditorGUIUtility.Load("console.warnicon") as Texture2D); break;
case MessageType.Info: icon = infoIcon ?? (infoIcon = EditorGUIUtility.Load("console.infoicon") as Texture2D); break;
case MessageType.Error: icon = errorIcon ?? (errorIcon = EditorGUIUtility.Load("console.erroricon") as Texture2D); break;
}
EditorGUI.LabelField(position, GUIContent.none, new GUIContent(message, icon), HelpBoxRichTextStyle);
}
static public void HelpBoxRichText(string message, MessageType msgType)
{
Texture2D icon = null;
switch(msgType)
{
case MessageType.Warning: icon = warnIcon ?? (warnIcon = EditorGUIUtility.Load("console.warnicon") as Texture2D); break;
case MessageType.Info: icon = infoIcon ?? (infoIcon = EditorGUIUtility.Load("console.infoicon") as Texture2D); break;
case MessageType.Error: icon = errorIcon ?? (errorIcon = EditorGUIUtility.Load("console.erroricon") as Texture2D); break;
}
EditorGUILayout.LabelField(GUIContent.none, new GUIContent(message, icon), HelpBoxRichTextStyle);
}
}
}

View File

@@ -1,287 +1,287 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace CartoonFX
{
public partial class CFXR_Effect : MonoBehaviour
{
[System.Serializable]
public class CameraShake
{
public enum ShakeSpace
{
Screen,
World
}
static public bool editorPreview = true;
//--------------------------------------------------------------------------------------------------------------------------------
public bool enabled = false;
[Space]
public bool useMainCamera = true;
public List<Camera> cameras = new List<Camera>();
[Space]
public float delay = 0.0f;
public float duration = 1.0f;
public ShakeSpace shakeSpace = ShakeSpace.Screen;
public Vector3 shakeStrength = new Vector3(0.1f, 0.1f, 0.1f);
public AnimationCurve shakeCurve = AnimationCurve.Linear(0, 1, 1, 0);
[Space]
[Range(0, 0.1f)] public float shakesDelay = 0;
[System.NonSerialized] public bool isShaking;
Dictionary<Camera, Vector3> camerasPreRenderPosition = new Dictionary<Camera, Vector3>();
Vector3 shakeVector;
float delaysTimer;
//--------------------------------------------------------------------------------------------------------------------------------
// STATIC
// Use static methods to dispatch the Camera callbacks, to ensure that ScreenShake components are called in an order in PreRender,
// and in the _reverse_ order for PostRender, so that the final Camera position is the same as it is originally (allowing concurrent
// screen shake to be active)
static bool s_CallbackRegistered;
static List<CameraShake> s_CameraShakes = new List<CameraShake>();
#if UNITY_2019_1_OR_NEWER
static void OnPreRenderCamera_Static_URP(ScriptableRenderContext context, Camera cam)
{
OnPreRenderCamera_Static(cam);
}
static void OnPostRenderCamera_Static_URP(ScriptableRenderContext context, Camera cam)
{
OnPostRenderCamera_Static(cam);
}
#endif
static void OnPreRenderCamera_Static(Camera cam)
{
int count = s_CameraShakes.Count;
for (int i = 0; i < count; i++)
{
var ss = s_CameraShakes[i];
ss.onPreRenderCamera(cam);
}
}
static void OnPostRenderCamera_Static(Camera cam)
{
int count = s_CameraShakes.Count;
for (int i = count-1; i >= 0; i--)
{
var ss = s_CameraShakes[i];
ss.onPostRenderCamera(cam);
}
}
static void RegisterStaticCallback(CameraShake cameraShake)
{
s_CameraShakes.Add(cameraShake);
if (!s_CallbackRegistered)
{
#if UNITY_2019_1_OR_NEWER
#if UNITY_2019_3_OR_NEWER
if (GraphicsSettings.currentRenderPipeline == null)
#else
if (GraphicsSettings.renderPipelineAsset == null)
#endif
{
// Built-in Render Pipeline
Camera.onPreRender += OnPreRenderCamera_Static;
Camera.onPostRender += OnPostRenderCamera_Static;
}
else
{
// URP
RenderPipelineManager.beginCameraRendering += OnPreRenderCamera_Static_URP;
RenderPipelineManager.endCameraRendering += OnPostRenderCamera_Static_URP;
}
#else
Camera.onPreRender += OnPreRenderCamera_Static;
Camera.onPostRender += OnPostRenderCamera_Static;
#endif
s_CallbackRegistered = true;
}
}
static void UnregisterStaticCallback(CameraShake cameraShake)
{
s_CameraShakes.Remove(cameraShake);
if (s_CallbackRegistered && s_CameraShakes.Count == 0)
{
#if UNITY_2019_1_OR_NEWER
#if UNITY_2019_3_OR_NEWER
if (GraphicsSettings.currentRenderPipeline == null)
#else
if (GraphicsSettings.renderPipelineAsset == null)
#endif
{
// Built-in Render Pipeline
Camera.onPreRender -= OnPreRenderCamera_Static;
Camera.onPostRender -= OnPostRenderCamera_Static;
}
else
{
// URP
RenderPipelineManager.beginCameraRendering -= OnPreRenderCamera_Static_URP;
RenderPipelineManager.endCameraRendering -= OnPostRenderCamera_Static_URP;
}
#else
Camera.onPreRender -= OnPreRenderCamera_Static;
Camera.onPostRender -= OnPostRenderCamera_Static;
#endif
s_CallbackRegistered = false;
}
}
//--------------------------------------------------------------------------------------------------------------------------------
void onPreRenderCamera(Camera cam)
{
#if UNITY_EDITOR
//add scene view camera if necessary
if (SceneView.currentDrawingSceneView != null && SceneView.currentDrawingSceneView.camera == cam && !camerasPreRenderPosition.ContainsKey(cam))
{
camerasPreRenderPosition.Add(cam, cam.transform.localPosition);
}
#endif
if (isShaking && camerasPreRenderPosition.ContainsKey(cam))
{
camerasPreRenderPosition[cam] = cam.transform.localPosition;
if (Time.timeScale <= 0) return;
switch (shakeSpace)
{
case ShakeSpace.Screen: cam.transform.localPosition += cam.transform.rotation * shakeVector; break;
case ShakeSpace.World: cam.transform.localPosition += shakeVector; break;
}
}
}
void onPostRenderCamera(Camera cam)
{
if (camerasPreRenderPosition.ContainsKey(cam))
{
cam.transform.localPosition = camerasPreRenderPosition[cam];
}
}
public void fetchCameras()
{
#if UNITY_EDITOR
if (!EditorApplication.isPlayingOrWillChangePlaymode)
{
return;
}
#endif
foreach (var cam in cameras)
{
if (cam == null) continue;
camerasPreRenderPosition.Remove(cam);
}
cameras.Clear();
if (useMainCamera && Camera.main != null)
{
cameras.Add(Camera.main);
}
foreach (var cam in cameras)
{
if (cam == null) continue;
if (!camerasPreRenderPosition.ContainsKey(cam))
{
camerasPreRenderPosition.Add(cam, Vector3.zero);
}
}
}
public void StartShake()
{
if (isShaking)
{
StopShake();
}
isShaking = true;
RegisterStaticCallback(this);
}
public void StopShake()
{
isShaking = false;
shakeVector = Vector3.zero;
UnregisterStaticCallback(this);
}
public void animate(float time)
{
#if UNITY_EDITOR
if (!editorPreview && !EditorApplication.isPlaying)
{
shakeVector = Vector3.zero;
return;
}
#endif
float totalDuration = duration + delay;
if (time < totalDuration)
{
if (time < delay)
{
return;
}
if (!isShaking)
{
this.StartShake();
}
// duration of the camera shake
float delta = Mathf.Clamp01(time/totalDuration);
// delay between each camera move
if (shakesDelay > 0)
{
delaysTimer += Time.deltaTime;
if (delaysTimer < shakesDelay)
{
return;
}
else
{
while (delaysTimer >= shakesDelay)
{
delaysTimer -= shakesDelay;
}
}
}
var randomVec = new Vector3(Random.value, Random.value, Random.value);
var shakeVec = Vector3.Scale(randomVec, shakeStrength) * (Random.value > 0.5f ? -1 : 1);
shakeVector = shakeVec * shakeCurve.Evaluate(delta) * GLOBAL_CAMERA_SHAKE_MULTIPLIER;
}
else if (isShaking)
{
StopShake();
}
}
}
}
}
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace CartoonFX
{
public partial class CFXR_Effect : MonoBehaviour
{
[System.Serializable]
public class CameraShake
{
public enum ShakeSpace
{
Screen,
World
}
static public bool editorPreview = true;
//--------------------------------------------------------------------------------------------------------------------------------
public bool enabled = false;
[Space]
public bool useMainCamera = true;
public List<Camera> cameras = new List<Camera>();
[Space]
public float delay = 0.0f;
public float duration = 1.0f;
public ShakeSpace shakeSpace = ShakeSpace.Screen;
public Vector3 shakeStrength = new Vector3(0.1f, 0.1f, 0.1f);
public AnimationCurve shakeCurve = AnimationCurve.Linear(0, 1, 1, 0);
[Space]
[Range(0, 0.1f)] public float shakesDelay = 0;
[System.NonSerialized] public bool isShaking;
Dictionary<Camera, Vector3> camerasPreRenderPosition = new Dictionary<Camera, Vector3>();
Vector3 shakeVector;
float delaysTimer;
//--------------------------------------------------------------------------------------------------------------------------------
// STATIC
// Use static methods to dispatch the Camera callbacks, to ensure that ScreenShake components are called in an order in PreRender,
// and in the _reverse_ order for PostRender, so that the final Camera position is the same as it is originally (allowing concurrent
// screen shake to be active)
static bool s_CallbackRegistered;
static List<CameraShake> s_CameraShakes = new List<CameraShake>();
#if UNITY_2019_1_OR_NEWER
static void OnPreRenderCamera_Static_URP(ScriptableRenderContext context, Camera cam)
{
OnPreRenderCamera_Static(cam);
}
static void OnPostRenderCamera_Static_URP(ScriptableRenderContext context, Camera cam)
{
OnPostRenderCamera_Static(cam);
}
#endif
static void OnPreRenderCamera_Static(Camera cam)
{
int count = s_CameraShakes.Count;
for (int i = 0; i < count; i++)
{
var ss = s_CameraShakes[i];
ss.onPreRenderCamera(cam);
}
}
static void OnPostRenderCamera_Static(Camera cam)
{
int count = s_CameraShakes.Count;
for (int i = count-1; i >= 0; i--)
{
var ss = s_CameraShakes[i];
ss.onPostRenderCamera(cam);
}
}
static void RegisterStaticCallback(CameraShake cameraShake)
{
s_CameraShakes.Add(cameraShake);
if (!s_CallbackRegistered)
{
#if UNITY_2019_1_OR_NEWER
#if UNITY_2019_3_OR_NEWER
if (GraphicsSettings.currentRenderPipeline == null)
#else
if (GraphicsSettings.renderPipelineAsset == null)
#endif
{
// Built-in Render Pipeline
Camera.onPreRender += OnPreRenderCamera_Static;
Camera.onPostRender += OnPostRenderCamera_Static;
}
else
{
// URP
RenderPipelineManager.beginCameraRendering += OnPreRenderCamera_Static_URP;
RenderPipelineManager.endCameraRendering += OnPostRenderCamera_Static_URP;
}
#else
Camera.onPreRender += OnPreRenderCamera_Static;
Camera.onPostRender += OnPostRenderCamera_Static;
#endif
s_CallbackRegistered = true;
}
}
static void UnregisterStaticCallback(CameraShake cameraShake)
{
s_CameraShakes.Remove(cameraShake);
if (s_CallbackRegistered && s_CameraShakes.Count == 0)
{
#if UNITY_2019_1_OR_NEWER
#if UNITY_2019_3_OR_NEWER
if (GraphicsSettings.currentRenderPipeline == null)
#else
if (GraphicsSettings.renderPipelineAsset == null)
#endif
{
// Built-in Render Pipeline
Camera.onPreRender -= OnPreRenderCamera_Static;
Camera.onPostRender -= OnPostRenderCamera_Static;
}
else
{
// URP
RenderPipelineManager.beginCameraRendering -= OnPreRenderCamera_Static_URP;
RenderPipelineManager.endCameraRendering -= OnPostRenderCamera_Static_URP;
}
#else
Camera.onPreRender -= OnPreRenderCamera_Static;
Camera.onPostRender -= OnPostRenderCamera_Static;
#endif
s_CallbackRegistered = false;
}
}
//--------------------------------------------------------------------------------------------------------------------------------
void onPreRenderCamera(Camera cam)
{
#if UNITY_EDITOR
//add scene view camera if necessary
if (SceneView.currentDrawingSceneView != null && SceneView.currentDrawingSceneView.camera == cam && !camerasPreRenderPosition.ContainsKey(cam))
{
camerasPreRenderPosition.Add(cam, cam.transform.localPosition);
}
#endif
if (isShaking && camerasPreRenderPosition.ContainsKey(cam))
{
camerasPreRenderPosition[cam] = cam.transform.localPosition;
if (Time.timeScale <= 0) return;
switch (shakeSpace)
{
case ShakeSpace.Screen: cam.transform.localPosition += cam.transform.rotation * shakeVector; break;
case ShakeSpace.World: cam.transform.localPosition += shakeVector; break;
}
}
}
void onPostRenderCamera(Camera cam)
{
if (camerasPreRenderPosition.ContainsKey(cam))
{
cam.transform.localPosition = camerasPreRenderPosition[cam];
}
}
public void fetchCameras()
{
#if UNITY_EDITOR
if (!EditorApplication.isPlayingOrWillChangePlaymode)
{
return;
}
#endif
foreach (var cam in cameras)
{
if (cam == null) continue;
camerasPreRenderPosition.Remove(cam);
}
cameras.Clear();
if (useMainCamera && Camera.main != null)
{
cameras.Add(Camera.main);
}
foreach (var cam in cameras)
{
if (cam == null) continue;
if (!camerasPreRenderPosition.ContainsKey(cam))
{
camerasPreRenderPosition.Add(cam, Vector3.zero);
}
}
}
public void StartShake()
{
if (isShaking)
{
StopShake();
}
isShaking = true;
RegisterStaticCallback(this);
}
public void StopShake()
{
isShaking = false;
shakeVector = Vector3.zero;
UnregisterStaticCallback(this);
}
public void animate(float time)
{
#if UNITY_EDITOR
if (!editorPreview && !EditorApplication.isPlaying)
{
shakeVector = Vector3.zero;
return;
}
#endif
float totalDuration = duration + delay;
if (time < totalDuration)
{
if (time < delay)
{
return;
}
if (!isShaking)
{
this.StartShake();
}
// duration of the camera shake
float delta = Mathf.Clamp01(time/totalDuration);
// delay between each camera move
if (shakesDelay > 0)
{
delaysTimer += Time.deltaTime;
if (delaysTimer < shakesDelay)
{
return;
}
else
{
while (delaysTimer >= shakesDelay)
{
delaysTimer -= shakesDelay;
}
}
}
var randomVec = new Vector3(Random.value, Random.value, Random.value);
var shakeVec = Vector3.Scale(randomVec, shakeStrength) * (Random.value > 0.5f ? -1 : 1);
shakeVector = shakeVec * shakeCurve.Evaluate(delta) * GLOBAL_CAMERA_SHAKE_MULTIPLIER;
}
else if (isShaking)
{
StopShake();
}
}
}
}
}

View File

@@ -1,419 +1,419 @@
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2022 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace CartoonFX
{
[RequireComponent(typeof(ParticleSystem))]
public class CFXR_ParticleText : MonoBehaviour
{
[Header("Dynamic")]
[Tooltip("Allow changing the text at runtime with the 'UpdateText' method. If disabled, this script will be excluded from the build.")]
public bool isDynamic;
[Header("Text")]
[SerializeField] string text;
[SerializeField] float size = 1f;
[SerializeField] float letterSpacing = 0.44f;
[Header("Colors")]
[SerializeField] Color backgroundColor = new Color(0, 0, 0, 1);
[SerializeField] Color color1 = new Color(1, 1, 1, 1);
[SerializeField] Color color2 = new Color(0, 0, 1, 1);
[Header("Delay")]
[SerializeField] float delay = 0.05f;
[SerializeField] bool cumulativeDelay = false;
[Range(0f, 2f)] [SerializeField] float compensateLifetime = 0;
[Header("Misc")]
[SerializeField] float lifetimeMultiplier = 1f;
[Range(-90f, 90f)] [SerializeField] float rotation = -5f;
[SerializeField] float sortingFudgeOffset = 0.1f;
#pragma warning disable 0649
[SerializeField] CFXR_ParticleTextFontAsset font;
#pragma warning restore 0649
#if UNITY_EDITOR
[HideInInspector] [SerializeField] bool autoUpdateEditor = true;
void OnValidate()
{
if (text == null || font == null)
{
return;
}
// parse text to only allow valid characters
List<char> allowed = new List<char>(font.CharSequence.ToCharArray());
allowed.Add(' ');
char[] chars;
switch (font.letterCase)
{
case CFXR_ParticleTextFontAsset.LetterCase.Lower: chars = text.ToLowerInvariant().ToCharArray(); break;
case CFXR_ParticleTextFontAsset.LetterCase.Upper: chars = text.ToUpperInvariant().ToCharArray(); break;
default:
case CFXR_ParticleTextFontAsset.LetterCase.Both: chars = text.ToCharArray(); break;
}
string newText = "";
foreach (var c in chars)
{
if (allowed.Contains(c))
{
newText += c;
}
}
text = newText;
// prevent negative or 0 size
size = Mathf.Max(0.001f, size);
// delay so that we are allowed to destroy GameObjects
if (autoUpdateEditor && !EditorApplication.isPlayingOrWillChangePlaymode)
{
EditorApplication.delayCall += () => { UpdateText(null); };
}
}
#endif
void Awake()
{
if (!isDynamic)
{
Destroy(this);
return;
}
InitializeFirstParticle();
}
float baseLifetime;
float baseScaleX;
float baseScaleY;
float baseScaleZ;
Vector3 basePivot;
void InitializeFirstParticle()
{
if (isDynamic && this.transform.childCount == 0)
{
throw new System.Exception("[CFXR_ParticleText] A disabled GameObject with a ParticleSystem component is required as the first child when 'isDyanmic' is enabled, so that its settings can be used as a base for the generated characters.");
}
var ps = isDynamic ? this.transform.GetChild(0).GetComponent<ParticleSystem>() : this.GetComponent<ParticleSystem>();
var main = ps.main;
baseLifetime = main.startLifetime.constant;
baseScaleX = main.startSizeXMultiplier;
baseScaleY = main.startSizeYMultiplier;
baseScaleZ = main.startSizeZMultiplier;
basePivot = ps.GetComponent<ParticleSystemRenderer>().pivot;
if (isDynamic)
{
basePivot.x = 0; // make sure to not offset the text horizontally
ps.gameObject.SetActive(false); // ensure first child is inactive
ps.gameObject.name = "MODEL";
}
}
public void UpdateText(
string newText = null,
float? newSize = null,
Color? newColor1 = null, Color? newColor2 = null, Color? newBackgroundColor = null,
float? newLifetimeMultiplier = null
)
{
#if UNITY_EDITOR
// Only allow updating text for GameObjects that aren't prefabs, since we are possibly destroying/adding GameObjects
if (this == null)
{
return;
}
var prefabInstanceStatus = PrefabUtility.GetPrefabInstanceStatus(this);
var prefabAssetType = PrefabUtility.GetPrefabAssetType(this);
if (!(prefabInstanceStatus == PrefabInstanceStatus.NotAPrefab && prefabAssetType == PrefabAssetType.NotAPrefab))
{
return;
}
if (!Application.isPlaying)
{
InitializeFirstParticle();
}
#endif
if (Application.isPlaying && !isDynamic)
{
throw new System.Exception("[CFXR_ParticleText] You cannot update the text at runtime if it's not marked as dynamic.");
}
if (newText != null)
{
switch (font.letterCase)
{
case CFXR_ParticleTextFontAsset.LetterCase.Lower:
newText = newText.ToLowerInvariant();
break;
case CFXR_ParticleTextFontAsset.LetterCase.Upper:
newText = newText.ToUpperInvariant();
break;
}
// Verify that new text doesn't contain invalid characters
foreach (char c in newText)
{
if (char.IsWhiteSpace(c)) continue;
if (font.CharSequence.IndexOf(c) < 0)
{
throw new System.Exception("[CFXR_ParticleText] Invalid character supplied for the dynamic text: '" + c + "'\nThe allowed characters from the selected font are: " + font.CharSequence);
}
}
this.text = newText;
}
if (newSize != null) this.size = newSize.Value;
if (newColor1 != null) this.color1 = newColor1.Value;
if (newColor2 != null) this.color2 = newColor2.Value;
if (newBackgroundColor != null) this.backgroundColor = newBackgroundColor.Value;
if (newLifetimeMultiplier != null) this.lifetimeMultiplier = newLifetimeMultiplier.Value;
if (text == null || font == null || !font.IsValid())
{
return;
}
if (this.transform.childCount == 0)
{
throw new System.Exception("[CFXR_ParticleText] A disabled GameObject with a ParticleSystem component is required as the first child when 'isDyanmic' is enabled, so that its settings can be used as a base for the generated characters.");
}
// process text and calculate total width offset
float totalWidth = 0f;
int charCount = 0;
for (int i = 0; i < text.Length; i++)
{
if (char.IsWhiteSpace(text[i]))
{
if (i > 0)
{
totalWidth += letterSpacing * size;
}
}
else
{
charCount++;
if (i > 0)
{
int index = font.CharSequence.IndexOf(text[i]);
var sprite = font.CharSprites[index];
float charWidth = sprite.rect.width + font.CharKerningOffsets[index].post + font.CharKerningOffsets[index].pre;
totalWidth += (charWidth * 0.01f + letterSpacing) * size;
}
}
}
#if UNITY_EDITOR
// delete all children in editor, to make sure we refresh the particle systems based on the first one
if (!Application.isPlaying)
{
int length = this.transform.childCount;
int overflow = 0;
while (this.transform.childCount > 1)
{
Object.DestroyImmediate(this.transform.GetChild(this.transform.childCount - 1).gameObject);
overflow++;
if (overflow > 1000)
{
// just in case...
Debug.LogError("Overflow!");
break;
}
}
}
#endif
if (charCount > 0)
{
// calculate needed instances
int childCount = this.transform.childCount - (isDynamic ? 1 : 0); // first one is the particle source and always deactivated
if (childCount < charCount)
{
// instantiate new letter GameObjects if needed
GameObject model = isDynamic ? this.transform.GetChild(0).gameObject : null;
for (int i = childCount; i < charCount; i++)
{
var newLetter = isDynamic ? Instantiate(model, this.transform) : new GameObject();
if (!isDynamic)
{
newLetter.transform.SetParent(this.transform);
newLetter.AddComponent<ParticleSystem>();
}
newLetter.transform.localPosition = Vector3.zero;
newLetter.transform.localRotation = Quaternion.identity;
}
}
// update each letter
float offset = totalWidth / 2f;
totalWidth = 0f;
int currentChild = isDynamic ? 0 : -1;
// when not dynamic, we use CopySerialized to propagate the settings to the instances
var sourceParticle = isDynamic ? null : this.GetComponent<ParticleSystem>();
var sourceParticleRenderer = this.GetComponent<ParticleSystemRenderer>();
for (int i = 0; i < text.Length; i++)
{
var letter = text[i];
if (char.IsWhiteSpace(letter))
{
totalWidth += letterSpacing * size;
}
else
{
currentChild++;
int index = font.CharSequence.IndexOf(text[i]);
var sprite = font.CharSprites[index];
// calculate char particle size ratio
var ratio = size * sprite.rect.width / 50f;
// calculate char position
totalWidth += font.CharKerningOffsets[index].pre * 0.01f * size;
var position = (totalWidth - offset) / ratio;
float charWidth = sprite.rect.width + font.CharKerningOffsets[index].post;
totalWidth += (charWidth * 0.01f + letterSpacing) * size;
// update particle system for this letter
var letterObj = this.transform.GetChild(currentChild).gameObject;
letterObj.name = letter.ToString();
var ps = letterObj.GetComponent<ParticleSystem>();
#if UNITY_EDITOR
if (!isDynamic)
{
EditorUtility.CopySerialized(sourceParticle, ps);
ps.gameObject.SetActive(true);
}
#endif
var mainModule = ps.main;
mainModule.startSizeXMultiplier = baseScaleX * ratio;
mainModule.startSizeYMultiplier = baseScaleY * ratio;
mainModule.startSizeZMultiplier = baseScaleZ * ratio;
ps.textureSheetAnimation.SetSprite(0, sprite);
mainModule.startRotation = Mathf.Deg2Rad * rotation;
mainModule.startColor = backgroundColor;
var customData = ps.customData;
customData.enabled = true;
customData.SetColor(ParticleSystemCustomData.Custom1, color1);
customData.SetColor(ParticleSystemCustomData.Custom2, color2);
if (cumulativeDelay)
{
mainModule.startDelay = delay * i;
mainModule.startLifetime = Mathf.LerpUnclamped(baseLifetime, baseLifetime + (delay * (text.Length - i)), compensateLifetime / lifetimeMultiplier);
}
else
{
mainModule.startDelay = delay;
}
mainModule.startLifetime = mainModule.startLifetime.constant * lifetimeMultiplier;
// particle system renderer parameters
var particleRenderer = ps.GetComponent<ParticleSystemRenderer>();
#if UNITY_EDITOR
if (!isDynamic)
{
EditorUtility.CopySerialized(sourceParticleRenderer, particleRenderer);
}
#endif
particleRenderer.enabled = true;
particleRenderer.pivot = new Vector3(basePivot.x + position, basePivot.y, basePivot.z);
particleRenderer.sortingFudge += i * sortingFudgeOffset;
}
}
}
// set active state for needed letters only
for (int i = 1, l = this.transform.childCount; i < l; i++)
{
this.transform.GetChild(i).gameObject.SetActive(i <= charCount);
}
#if UNITY_EDITOR
// automatically play the effect in Editor
if (!Application.isPlaying)
{
this.GetComponent<ParticleSystem>().Clear(true);
this.GetComponent<ParticleSystem>().Play(true);
}
#endif
}
}
#if UNITY_EDITOR
[CustomEditor(typeof(CFXR_ParticleText))]
public class ParticleTextEditor : Editor
{
CFXR_ParticleText CastTarget
{
get { return (CFXR_ParticleText) this.target; }
}
GUIContent GUIContent_AutoUpdateToggle = new GUIContent("Auto-update", "Automatically regenerate the text when a property is changed.");
GUIContent GUIContent_UpdateTextButton = new GUIContent(" Update Text ", "Regenerate the text and create new letter GameObjects if needed.");
public override void OnInspectorGUI()
{
var prefab = PrefabUtility.GetPrefabInstanceStatus(target);
if (prefab != PrefabInstanceStatus.NotAPrefab)
{
EditorGUILayout.HelpBox("Cartoon FX Particle Text doesn't work on Prefab Instances, as it needs to destroy/create children GameObjects.\nYou can right-click on the object, and select \"Unpack Prefab\" to make it an independent Game Object.",
MessageType.Warning);
return;
}
base.OnInspectorGUI();
serializedObject.Update();
SerializedProperty autoUpdateBool = serializedObject.FindProperty("autoUpdateEditor");
GUILayout.Space(8);
GUILayout.BeginHorizontal();
{
GUILayout.FlexibleSpace();
autoUpdateBool.boolValue = GUILayout.Toggle(autoUpdateBool.boolValue, GUIContent_AutoUpdateToggle, GUILayout.Height(30));
if (GUILayout.Button(GUIContent_UpdateTextButton, GUILayout.Height(30)))
{
CastTarget.UpdateText(null);
}
}
GUILayout.EndHorizontal();
if (GUI.changed)
{
serializedObject.ApplyModifiedProperties();
}
}
}
#endif
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2022 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace CartoonFX
{
[RequireComponent(typeof(ParticleSystem))]
public class CFXR_ParticleText : MonoBehaviour
{
[Header("Dynamic")]
[Tooltip("Allow changing the text at runtime with the 'UpdateText' method. If disabled, this script will be excluded from the build.")]
public bool isDynamic;
[Header("Text")]
[SerializeField] string text;
[SerializeField] float size = 1f;
[SerializeField] float letterSpacing = 0.44f;
[Header("Colors")]
[SerializeField] Color backgroundColor = new Color(0, 0, 0, 1);
[SerializeField] Color color1 = new Color(1, 1, 1, 1);
[SerializeField] Color color2 = new Color(0, 0, 1, 1);
[Header("Delay")]
[SerializeField] float delay = 0.05f;
[SerializeField] bool cumulativeDelay = false;
[Range(0f, 2f)] [SerializeField] float compensateLifetime = 0;
[Header("Misc")]
[SerializeField] float lifetimeMultiplier = 1f;
[Range(-90f, 90f)] [SerializeField] float rotation = -5f;
[SerializeField] float sortingFudgeOffset = 0.1f;
#pragma warning disable 0649
[SerializeField] CFXR_ParticleTextFontAsset font;
#pragma warning restore 0649
#if UNITY_EDITOR
[HideInInspector] [SerializeField] bool autoUpdateEditor = true;
void OnValidate()
{
if (text == null || font == null)
{
return;
}
// parse text to only allow valid characters
List<char> allowed = new List<char>(font.CharSequence.ToCharArray());
allowed.Add(' ');
char[] chars;
switch (font.letterCase)
{
case CFXR_ParticleTextFontAsset.LetterCase.Lower: chars = text.ToLowerInvariant().ToCharArray(); break;
case CFXR_ParticleTextFontAsset.LetterCase.Upper: chars = text.ToUpperInvariant().ToCharArray(); break;
default:
case CFXR_ParticleTextFontAsset.LetterCase.Both: chars = text.ToCharArray(); break;
}
string newText = "";
foreach (var c in chars)
{
if (allowed.Contains(c))
{
newText += c;
}
}
text = newText;
// prevent negative or 0 size
size = Mathf.Max(0.001f, size);
// delay so that we are allowed to destroy GameObjects
if (autoUpdateEditor && !EditorApplication.isPlayingOrWillChangePlaymode)
{
EditorApplication.delayCall += () => { UpdateText(null); };
}
}
#endif
void Awake()
{
if (!isDynamic)
{
Destroy(this);
return;
}
InitializeFirstParticle();
}
float baseLifetime;
float baseScaleX;
float baseScaleY;
float baseScaleZ;
Vector3 basePivot;
void InitializeFirstParticle()
{
if (isDynamic && this.transform.childCount == 0)
{
throw new System.Exception("[CFXR_ParticleText] A disabled GameObject with a ParticleSystem component is required as the first child when 'isDyanmic' is enabled, so that its settings can be used as a base for the generated characters.");
}
var ps = isDynamic ? this.transform.GetChild(0).GetComponent<ParticleSystem>() : this.GetComponent<ParticleSystem>();
var main = ps.main;
baseLifetime = main.startLifetime.constant;
baseScaleX = main.startSizeXMultiplier;
baseScaleY = main.startSizeYMultiplier;
baseScaleZ = main.startSizeZMultiplier;
basePivot = ps.GetComponent<ParticleSystemRenderer>().pivot;
if (isDynamic)
{
basePivot.x = 0; // make sure to not offset the text horizontally
ps.gameObject.SetActive(false); // ensure first child is inactive
ps.gameObject.name = "MODEL";
}
}
public void UpdateText(
string newText = null,
float? newSize = null,
Color? newColor1 = null, Color? newColor2 = null, Color? newBackgroundColor = null,
float? newLifetimeMultiplier = null
)
{
#if UNITY_EDITOR
// Only allow updating text for GameObjects that aren't prefabs, since we are possibly destroying/adding GameObjects
if (this == null)
{
return;
}
var prefabInstanceStatus = PrefabUtility.GetPrefabInstanceStatus(this);
var prefabAssetType = PrefabUtility.GetPrefabAssetType(this);
if (!(prefabInstanceStatus == PrefabInstanceStatus.NotAPrefab && prefabAssetType == PrefabAssetType.NotAPrefab))
{
return;
}
if (!Application.isPlaying)
{
InitializeFirstParticle();
}
#endif
if (Application.isPlaying && !isDynamic)
{
throw new System.Exception("[CFXR_ParticleText] You cannot update the text at runtime if it's not marked as dynamic.");
}
if (newText != null)
{
switch (font.letterCase)
{
case CFXR_ParticleTextFontAsset.LetterCase.Lower:
newText = newText.ToLowerInvariant();
break;
case CFXR_ParticleTextFontAsset.LetterCase.Upper:
newText = newText.ToUpperInvariant();
break;
}
// Verify that new text doesn't contain invalid characters
foreach (char c in newText)
{
if (char.IsWhiteSpace(c)) continue;
if (font.CharSequence.IndexOf(c) < 0)
{
throw new System.Exception("[CFXR_ParticleText] Invalid character supplied for the dynamic text: '" + c + "'\nThe allowed characters from the selected font are: " + font.CharSequence);
}
}
this.text = newText;
}
if (newSize != null) this.size = newSize.Value;
if (newColor1 != null) this.color1 = newColor1.Value;
if (newColor2 != null) this.color2 = newColor2.Value;
if (newBackgroundColor != null) this.backgroundColor = newBackgroundColor.Value;
if (newLifetimeMultiplier != null) this.lifetimeMultiplier = newLifetimeMultiplier.Value;
if (text == null || font == null || !font.IsValid())
{
return;
}
if (this.transform.childCount == 0)
{
throw new System.Exception("[CFXR_ParticleText] A disabled GameObject with a ParticleSystem component is required as the first child when 'isDyanmic' is enabled, so that its settings can be used as a base for the generated characters.");
}
// process text and calculate total width offset
float totalWidth = 0f;
int charCount = 0;
for (int i = 0; i < text.Length; i++)
{
if (char.IsWhiteSpace(text[i]))
{
if (i > 0)
{
totalWidth += letterSpacing * size;
}
}
else
{
charCount++;
if (i > 0)
{
int index = font.CharSequence.IndexOf(text[i]);
var sprite = font.CharSprites[index];
float charWidth = sprite.rect.width + font.CharKerningOffsets[index].post + font.CharKerningOffsets[index].pre;
totalWidth += (charWidth * 0.01f + letterSpacing) * size;
}
}
}
#if UNITY_EDITOR
// delete all children in editor, to make sure we refresh the particle systems based on the first one
if (!Application.isPlaying)
{
int length = this.transform.childCount;
int overflow = 0;
while (this.transform.childCount > 1)
{
Object.DestroyImmediate(this.transform.GetChild(this.transform.childCount - 1).gameObject);
overflow++;
if (overflow > 1000)
{
// just in case...
Debug.LogError("Overflow!");
break;
}
}
}
#endif
if (charCount > 0)
{
// calculate needed instances
int childCount = this.transform.childCount - (isDynamic ? 1 : 0); // first one is the particle source and always deactivated
if (childCount < charCount)
{
// instantiate new letter GameObjects if needed
GameObject model = isDynamic ? this.transform.GetChild(0).gameObject : null;
for (int i = childCount; i < charCount; i++)
{
var newLetter = isDynamic ? Instantiate(model, this.transform) : new GameObject();
if (!isDynamic)
{
newLetter.transform.SetParent(this.transform);
newLetter.AddComponent<ParticleSystem>();
}
newLetter.transform.localPosition = Vector3.zero;
newLetter.transform.localRotation = Quaternion.identity;
}
}
// update each letter
float offset = totalWidth / 2f;
totalWidth = 0f;
int currentChild = isDynamic ? 0 : -1;
// when not dynamic, we use CopySerialized to propagate the settings to the instances
var sourceParticle = isDynamic ? null : this.GetComponent<ParticleSystem>();
var sourceParticleRenderer = this.GetComponent<ParticleSystemRenderer>();
for (int i = 0; i < text.Length; i++)
{
var letter = text[i];
if (char.IsWhiteSpace(letter))
{
totalWidth += letterSpacing * size;
}
else
{
currentChild++;
int index = font.CharSequence.IndexOf(text[i]);
var sprite = font.CharSprites[index];
// calculate char particle size ratio
var ratio = size * sprite.rect.width / 50f;
// calculate char position
totalWidth += font.CharKerningOffsets[index].pre * 0.01f * size;
var position = (totalWidth - offset) / ratio;
float charWidth = sprite.rect.width + font.CharKerningOffsets[index].post;
totalWidth += (charWidth * 0.01f + letterSpacing) * size;
// update particle system for this letter
var letterObj = this.transform.GetChild(currentChild).gameObject;
letterObj.name = letter.ToString();
var ps = letterObj.GetComponent<ParticleSystem>();
#if UNITY_EDITOR
if (!isDynamic)
{
EditorUtility.CopySerialized(sourceParticle, ps);
ps.gameObject.SetActive(true);
}
#endif
var mainModule = ps.main;
mainModule.startSizeXMultiplier = baseScaleX * ratio;
mainModule.startSizeYMultiplier = baseScaleY * ratio;
mainModule.startSizeZMultiplier = baseScaleZ * ratio;
ps.textureSheetAnimation.SetSprite(0, sprite);
mainModule.startRotation = Mathf.Deg2Rad * rotation;
mainModule.startColor = backgroundColor;
var customData = ps.customData;
customData.enabled = true;
customData.SetColor(ParticleSystemCustomData.Custom1, color1);
customData.SetColor(ParticleSystemCustomData.Custom2, color2);
if (cumulativeDelay)
{
mainModule.startDelay = delay * i;
mainModule.startLifetime = Mathf.LerpUnclamped(baseLifetime, baseLifetime + (delay * (text.Length - i)), compensateLifetime / lifetimeMultiplier);
}
else
{
mainModule.startDelay = delay;
}
mainModule.startLifetime = mainModule.startLifetime.constant * lifetimeMultiplier;
// particle system renderer parameters
var particleRenderer = ps.GetComponent<ParticleSystemRenderer>();
#if UNITY_EDITOR
if (!isDynamic)
{
EditorUtility.CopySerialized(sourceParticleRenderer, particleRenderer);
}
#endif
particleRenderer.enabled = true;
particleRenderer.pivot = new Vector3(basePivot.x + position, basePivot.y, basePivot.z);
particleRenderer.sortingFudge += i * sortingFudgeOffset;
}
}
}
// set active state for needed letters only
for (int i = 1, l = this.transform.childCount; i < l; i++)
{
this.transform.GetChild(i).gameObject.SetActive(i <= charCount);
}
#if UNITY_EDITOR
// automatically play the effect in Editor
if (!Application.isPlaying)
{
this.GetComponent<ParticleSystem>().Clear(true);
this.GetComponent<ParticleSystem>().Play(true);
}
#endif
}
}
#if UNITY_EDITOR
[CustomEditor(typeof(CFXR_ParticleText))]
public class ParticleTextEditor : Editor
{
CFXR_ParticleText CastTarget
{
get { return (CFXR_ParticleText) this.target; }
}
GUIContent GUIContent_AutoUpdateToggle = new GUIContent("Auto-update", "Automatically regenerate the text when a property is changed.");
GUIContent GUIContent_UpdateTextButton = new GUIContent(" Update Text ", "Regenerate the text and create new letter GameObjects if needed.");
public override void OnInspectorGUI()
{
var prefab = PrefabUtility.GetPrefabInstanceStatus(target);
if (prefab != PrefabInstanceStatus.NotAPrefab)
{
EditorGUILayout.HelpBox("Cartoon FX Particle Text doesn't work on Prefab Instances, as it needs to destroy/create children GameObjects.\nYou can right-click on the object, and select \"Unpack Prefab\" to make it an independent Game Object.",
MessageType.Warning);
return;
}
base.OnInspectorGUI();
serializedObject.Update();
SerializedProperty autoUpdateBool = serializedObject.FindProperty("autoUpdateEditor");
GUILayout.Space(8);
GUILayout.BeginHorizontal();
{
GUILayout.FlexibleSpace();
autoUpdateBool.boolValue = GUILayout.Toggle(autoUpdateBool.boolValue, GUIContent_AutoUpdateToggle, GUILayout.Height(30));
if (GUILayout.Button(GUIContent_UpdateTextButton, GUILayout.Height(30)))
{
CastTarget.UpdateText(null);
}
}
GUILayout.EndHorizontal();
if (GUI.changed)
{
serializedObject.ApplyModifiedProperties();
}
}
}
#endif
}

View File

@@ -1,128 +1,128 @@
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace CartoonFX
{
public class CFXR_ParticleTextFontAsset : ScriptableObject
{
public enum LetterCase
{
Both,
Upper,
Lower
}
public string CharSequence = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!?-.#@$ ";
public LetterCase letterCase = LetterCase.Upper;
public Sprite[] CharSprites;
public Kerning[] CharKerningOffsets;
[System.Serializable]
public class Kerning
{
public string name = "A";
public float pre = 0f;
public float post = 0f;
}
void OnValidate()
{
this.hideFlags = HideFlags.None;
if (CharKerningOffsets == null || CharKerningOffsets.Length != CharSequence.Length)
{
CharKerningOffsets = new Kerning[CharSequence.Length];
for (int i = 0; i < CharKerningOffsets.Length; i++)
{
CharKerningOffsets[i] = new Kerning() { name = CharSequence[i].ToString() };
}
}
}
public bool IsValid()
{
bool valid = !string.IsNullOrEmpty(CharSequence) && CharSprites != null && CharSprites.Length == CharSequence.Length && CharKerningOffsets != null && CharKerningOffsets.Length == CharSprites.Length;
if (!valid)
{
Debug.LogError(string.Format("Invalid ParticleTextFontAsset: '{0}'\n", this.name), this);
}
return valid;
}
#if UNITY_EDITOR
// [MenuItem("Tools/Create font asset")]
static void CreateFontAsset()
{
var instance = CreateInstance<CFXR_ParticleTextFontAsset>();
AssetDatabase.CreateAsset(instance, "Assets/Font.asset");
}
#endif
}
#if UNITY_EDITOR
[CustomEditor(typeof(CFXR_ParticleTextFontAsset))]
public class ParticleTextFontAssetEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Export Kerning"))
{
var ptfa = this.target as CFXR_ParticleTextFontAsset;
var path = EditorUtility.SaveFilePanel("Export Kerning Settings", Application.dataPath, ptfa.name + " kerning", ".txt");
if (!string.IsNullOrEmpty(path))
{
string output = "";
foreach (var k in ptfa.CharKerningOffsets)
{
output += k.name + "\t" + k.pre + "\t" + k.post + "\n";
}
System.IO.File.WriteAllText(path, output);
}
}
if (GUILayout.Button("Import Kerning"))
{
var path = EditorUtility.OpenFilePanel("Import Kerning Settings", Application.dataPath, "txt");
if (!string.IsNullOrEmpty(path))
{
var text = System.IO.File.ReadAllText(path);
var split = text.Split(new string[] { "\n" }, System.StringSplitOptions.RemoveEmptyEntries);
var ptfa = this.target as CFXR_ParticleTextFontAsset;
Undo.RecordObject(ptfa, "Import Kerning Settings");
List<CFXR_ParticleTextFontAsset.Kerning> kerningList = new List<CFXR_ParticleTextFontAsset.Kerning>(ptfa.CharKerningOffsets);
for (int i = 0; i < split.Length; i++)
{
var data = split[i].Split('\t');
foreach (var cko in kerningList)
{
if (cko.name == data[0])
{
cko.pre = float.Parse(data[1]);
cko.post = float.Parse(data[2]);
break;
}
}
}
ptfa.CharKerningOffsets = kerningList.ToArray();
}
}
GUILayout.EndHorizontal();
}
}
#endif
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace CartoonFX
{
public class CFXR_ParticleTextFontAsset : ScriptableObject
{
public enum LetterCase
{
Both,
Upper,
Lower
}
public string CharSequence = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!?-.#@$ ";
public LetterCase letterCase = LetterCase.Upper;
public Sprite[] CharSprites;
public Kerning[] CharKerningOffsets;
[System.Serializable]
public class Kerning
{
public string name = "A";
public float pre = 0f;
public float post = 0f;
}
void OnValidate()
{
this.hideFlags = HideFlags.None;
if (CharKerningOffsets == null || CharKerningOffsets.Length != CharSequence.Length)
{
CharKerningOffsets = new Kerning[CharSequence.Length];
for (int i = 0; i < CharKerningOffsets.Length; i++)
{
CharKerningOffsets[i] = new Kerning() { name = CharSequence[i].ToString() };
}
}
}
public bool IsValid()
{
bool valid = !string.IsNullOrEmpty(CharSequence) && CharSprites != null && CharSprites.Length == CharSequence.Length && CharKerningOffsets != null && CharKerningOffsets.Length == CharSprites.Length;
if (!valid)
{
Debug.LogError(string.Format("Invalid ParticleTextFontAsset: '{0}'\n", this.name), this);
}
return valid;
}
#if UNITY_EDITOR
// [MenuItem("Tools/Create font asset")]
static void CreateFontAsset()
{
var instance = CreateInstance<CFXR_ParticleTextFontAsset>();
AssetDatabase.CreateAsset(instance, "Assets/Font.asset");
}
#endif
}
#if UNITY_EDITOR
[CustomEditor(typeof(CFXR_ParticleTextFontAsset))]
public class ParticleTextFontAssetEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Export Kerning"))
{
var ptfa = this.target as CFXR_ParticleTextFontAsset;
var path = EditorUtility.SaveFilePanel("Export Kerning Settings", Application.dataPath, ptfa.name + " kerning", ".txt");
if (!string.IsNullOrEmpty(path))
{
string output = "";
foreach (var k in ptfa.CharKerningOffsets)
{
output += k.name + "\t" + k.pre + "\t" + k.post + "\n";
}
System.IO.File.WriteAllText(path, output);
}
}
if (GUILayout.Button("Import Kerning"))
{
var path = EditorUtility.OpenFilePanel("Import Kerning Settings", Application.dataPath, "txt");
if (!string.IsNullOrEmpty(path))
{
var text = System.IO.File.ReadAllText(path);
var split = text.Split(new string[] { "\n" }, System.StringSplitOptions.RemoveEmptyEntries);
var ptfa = this.target as CFXR_ParticleTextFontAsset;
Undo.RecordObject(ptfa, "Import Kerning Settings");
List<CFXR_ParticleTextFontAsset.Kerning> kerningList = new List<CFXR_ParticleTextFontAsset.Kerning>(ptfa.CharKerningOffsets);
for (int i = 0; i < split.Length; i++)
{
var data = split[i].Split('\t');
foreach (var cko in kerningList)
{
if (cko.name == data[0])
{
cko.pre = float.Parse(data[1]);
cko.post = float.Parse(data[2]);
break;
}
}
}
ptfa.CharKerningOffsets = kerningList.ToArray();
}
}
GUILayout.EndHorizontal();
}
}
#endif
}

View File

@@ -1,176 +1,176 @@
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
Shader "Cartoon FX/Remaster/Particle Screen Distortion"
{
Properties
{
[Toggle(_ALPHATEST_ON)] _UseAlphaClip ("Alpha Clipping (Cutout)", Float) = 0
//# IF_KEYWORD _ALPHATEST_ON
_Cutoff ("Cutoff Threshold", Range(0.001,1)) = 0.1
//# END_IF
//# --------------------------------------------------------
[Toggle(_FADING_ON)] _UseSP ("Soft Particles", Float) = 0
//# IF_KEYWORD _FADING_ON
_SoftParticlesFadeDistanceNear ("Near Fade", Float) = 0
_SoftParticlesFadeDistanceFar ("Far Fade", Float) = 1
//# END_IF
//#
[Toggle(_CFXR_EDGE_FADING)] _UseEF ("Edge Fade", Float) = 0
//# IF_KEYWORD _CFXR_EDGE_FADING
_EdgeFadePow ("Edge Fade Power", Float) = 1
//# END_IF
//# ========================================================
//# Texture
//#
[NoScaleOffset] _ScreenDistortionTex ("Distortion Texture", 2D) = "bump" {}
_ScreenDistortionScale ("Distortion Scale", Range(-0.5, 0.5)) = 0.1
//# ========================================================
//# Debug
//#
[Toggle(_DEBUG_VISUALIZE_DISTORTION)] _DebugVisualize ("Visualize Distortion Particles", Float) = 0
}
Category
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
}
Blend SrcAlpha OneMinusSrcAlpha, One One
ZWrite Off
Cull Off
//====================================================================================================================================
// Universal Rendering Pipeline
Subshader
{
Pass
{
Name "BASE_URP"
Tags { "LightMode"="UniversalForward" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:ParticleInstancingSetup
#pragma multi_compile_fog
//#pragma multi_compile_fwdbase
//#pragma multi_compile SHADOWS_SCREEN
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _DEBUG_VISUALIZE_DISTORTION
#define CFXR_URP
#define CFXR_SCREEN_DISTORTION_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
// Same as above with 'Universal2D' instead and DISABLE_SOFT_PARTICLES keyword
Pass
{
Name "BASE_URP"
Tags { "LightMode"="Universal2D" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:ParticleInstancingSetup
#pragma multi_compile_fog
//#pragma multi_compile_fwdbase
//#pragma multi_compile SHADOWS_SCREEN
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _DEBUG_VISUALIZE_DISTORTION
#define CFXR_URP
#define DISABLE_SOFT_PARTICLES
#define CFXR_SCREEN_DISTORTION_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
//====================================================================================================================================
// Built-in Rendering Pipeline
SubShader
{
GrabPass
{
Tags { "LightMode" = "Always" }
"_GrabTexture"
}
Pass
{
Name "BASE"
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
//vertInstancingSetup writes to global, not allowed with DXC
// #pragma never_use_dxc
// #pragma target 2.5
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:vertInstancingSetup
#pragma multi_compile_particles
#pragma multi_compile_fog
//#pragma multi_compile_fwdbase
//#pragma multi_compile SHADOWS_SCREEN
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _DEBUG_VISUALIZE_DISTORTION
#include "UnityStandardParticleInstancing.cginc"
#define CFXR_SCREEN_DISTORTION_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
}
CustomEditor "CartoonFX.MaterialInspector"
}
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
Shader "Cartoon FX/Remaster/Particle Screen Distortion"
{
Properties
{
[Toggle(_ALPHATEST_ON)] _UseAlphaClip ("Alpha Clipping (Cutout)", Float) = 0
//# IF_KEYWORD _ALPHATEST_ON
_Cutoff ("Cutoff Threshold", Range(0.001,1)) = 0.1
//# END_IF
//# --------------------------------------------------------
[Toggle(_FADING_ON)] _UseSP ("Soft Particles", Float) = 0
//# IF_KEYWORD _FADING_ON
_SoftParticlesFadeDistanceNear ("Near Fade", Float) = 0
_SoftParticlesFadeDistanceFar ("Far Fade", Float) = 1
//# END_IF
//#
[Toggle(_CFXR_EDGE_FADING)] _UseEF ("Edge Fade", Float) = 0
//# IF_KEYWORD _CFXR_EDGE_FADING
_EdgeFadePow ("Edge Fade Power", Float) = 1
//# END_IF
//# ========================================================
//# Texture
//#
[NoScaleOffset] _ScreenDistortionTex ("Distortion Texture", 2D) = "bump" {}
_ScreenDistortionScale ("Distortion Scale", Range(-0.5, 0.5)) = 0.1
//# ========================================================
//# Debug
//#
[Toggle(_DEBUG_VISUALIZE_DISTORTION)] _DebugVisualize ("Visualize Distortion Particles", Float) = 0
}
Category
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
}
Blend SrcAlpha OneMinusSrcAlpha, One One
ZWrite Off
Cull Off
//====================================================================================================================================
// Universal Rendering Pipeline
Subshader
{
Pass
{
Name "BASE_URP"
Tags { "LightMode"="UniversalForward" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:ParticleInstancingSetup
#pragma multi_compile_fog
//#pragma multi_compile_fwdbase
//#pragma multi_compile SHADOWS_SCREEN
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _DEBUG_VISUALIZE_DISTORTION
#define CFXR_URP
#define CFXR_SCREEN_DISTORTION_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
// Same as above with 'Universal2D' instead and DISABLE_SOFT_PARTICLES keyword
Pass
{
Name "BASE_URP"
Tags { "LightMode"="Universal2D" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:ParticleInstancingSetup
#pragma multi_compile_fog
//#pragma multi_compile_fwdbase
//#pragma multi_compile SHADOWS_SCREEN
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _DEBUG_VISUALIZE_DISTORTION
#define CFXR_URP
#define DISABLE_SOFT_PARTICLES
#define CFXR_SCREEN_DISTORTION_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
//====================================================================================================================================
// Built-in Rendering Pipeline
SubShader
{
GrabPass
{
Tags { "LightMode" = "Always" }
"_GrabTexture"
}
Pass
{
Name "BASE"
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
//vertInstancingSetup writes to global, not allowed with DXC
// #pragma never_use_dxc
// #pragma target 2.5
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:vertInstancingSetup
#pragma multi_compile_particles
#pragma multi_compile_fog
//#pragma multi_compile_fwdbase
//#pragma multi_compile SHADOWS_SCREEN
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _DEBUG_VISUALIZE_DISTORTION
#include "UnityStandardParticleInstancing.cginc"
#define CFXR_SCREEN_DISTORTION_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
}
CustomEditor "CartoonFX.MaterialInspector"
}

View File

@@ -1,274 +1,274 @@
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
Shader "Cartoon FX/Remaster/Particle Procedural Glow"
{
Properties
{
//# Blending
//#
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Blend Source", Float) = 5
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Blend Destination", Float) = 10
//# --------------------------------------------------------
[Toggle(_CFXR_DISSOLVE)] _UseDissolve ("Enable Dissolve", Float) = 0
//# IF_KEYWORD _CFXR_DISSOLVE
[NoScaleOffset] _DissolveTex ("Dissolve Texture", 2D) = "gray" {}
_DissolveSmooth ("Dissolve Smoothing", Range(0.0001,0.5)) = 0.1
[ToggleNoKeyword] _InvertDissolveTex ("Invert Dissolve Texture", Float) = 0
//# END_IF
//# --------------------------------------------------------
//# Procedural Circle
//#
[KeywordEnum(P0, P2, P4, P8)] _CFXR_GLOW_POW ("Apply Power of", Float) = 0
_GlowMin ("Circle Min", Float) = 0
_GlowMax ("Circle Max", Float) = 1
//#
_MaxValue ("Max Value", Float) = 10
//# --------------------------------------------------------
[Toggle(_CFXR_HDR_BOOST)] _HdrBoost ("Enable HDR Multiplier", Float) = 0
//# IF_KEYWORD _CFXR_HDR_BOOST
_HdrMultiply ("HDR Multiplier", Float) = 2
//# END_IF
//# --------------------------------------------------------
[Toggle(_FADING_ON)] _UseSP ("Soft Particles", Float) = 0
//# IF_KEYWORD _FADING_ON
_SoftParticlesFadeDistanceNear ("Near Fade", Float) = 0
_SoftParticlesFadeDistanceFar ("Far Fade", Float) = 1
//# END_IF
//# ========================================================
//# Shadows
//#
[KeywordEnum(Off,On,CustomTexture)] _CFXR_DITHERED_SHADOWS ("Dithered Shadows", Float) = 0
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
_ShadowStrength ("Shadows Strength Max", Range(0,1)) = 1.0
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
_DitherCustom ("Dithering 3D Texture", 3D) = "black" {}
//# END_IF
//# END_IF
}
Category
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
}
Blend [_SrcBlend] [_DstBlend], One One
Cull Off
ZWrite Off
//====================================================================================================================================
// Universal Rendering Pipeline
SubShader
{
Pass
{
Name "BASE"
Tags { "LightMode"="UniversalForward" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:ParticleInstancingSetup
#pragma multi_compile_fog
#pragma shader_feature_local _ _CFXR_GLOW_POW_P2 _CFXR_GLOW_POW_P4 _CFXR_GLOW_POW_P8
#pragma shader_feature_local _ _CFXR_HDR_BOOST
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_URP
#define CFXR_GLOW_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
// Same as above with 'Universal2D' instead and DISABLE_SOFT_PARTICLES keyword
Pass
{
Name "BASE"
Tags { "LightMode"="Universal2D" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:ParticleInstancingSetup
#pragma multi_compile_fog
#pragma shader_feature_local _ _CFXR_GLOW_POW_P2 _CFXR_GLOW_POW_P4 _CFXR_GLOW_POW_P8
#pragma shader_feature_local _ _CFXR_HDR_BOOST
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_URP
#define DISABLE_SOFT_PARTICLES
#define CFXR_GLOW_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
//--------------------------------------------------------------------------------------------------------------------------------
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma shader_feature_local _ _CFXR_GLOW_POW_P2 _CFXR_GLOW_POW_P4 _CFXR_GLOW_POW_P8
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON
#pragma multi_compile_shadowcaster
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
#pragma target 3.0 //needed for VPOS
#endif
#define CFXR_URP
#define PASS_SHADOW_CASTER
#define CFXR_GLOW_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
//====================================================================================================================================
// Built-in Rendering Pipeline
SubShader
{
Pass
{
Name "BASE"
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
//vertInstancingSetup writes to global, not allowed with DXC
// #pragma never_use_dxc
// #pragma target 2.5
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:vertInstancingSetup
#pragma multi_compile_particles
#pragma multi_compile_fog
#pragma shader_feature_local _ _CFXR_GLOW_POW_P2 _CFXR_GLOW_POW_P4 _CFXR_GLOW_POW_P8
#pragma shader_feature_local _ _CFXR_HDR_BOOST
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#include "UnityStandardParticleInstancing.cginc"
#define CFXR_GLOW_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
//--------------------------------------------------------------------------------------------------------------------------------
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
//vertInstancingSetup writes to global, not allowed with DXC
// #pragma never_use_dxc
// #pragma target 2.5
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:vertInstancingSetup
#pragma shader_feature_local _ _CFXR_GLOW_POW_P2 _CFXR_GLOW_POW_P4 _CFXR_GLOW_POW_P8
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON
#pragma multi_compile_shadowcaster
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
#pragma target 3.0 //needed for VPOS
#endif
#include "UnityStandardParticleInstancing.cginc"
#define PASS_SHADOW_CASTER
#define CFXR_GLOW_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
}
CustomEditor "CartoonFX.MaterialInspector"
}
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
Shader "Cartoon FX/Remaster/Particle Procedural Glow"
{
Properties
{
//# Blending
//#
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Blend Source", Float) = 5
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Blend Destination", Float) = 10
//# --------------------------------------------------------
[Toggle(_CFXR_DISSOLVE)] _UseDissolve ("Enable Dissolve", Float) = 0
//# IF_KEYWORD _CFXR_DISSOLVE
[NoScaleOffset] _DissolveTex ("Dissolve Texture", 2D) = "gray" {}
_DissolveSmooth ("Dissolve Smoothing", Range(0.0001,0.5)) = 0.1
[ToggleNoKeyword] _InvertDissolveTex ("Invert Dissolve Texture", Float) = 0
//# END_IF
//# --------------------------------------------------------
//# Procedural Circle
//#
[KeywordEnum(P0, P2, P4, P8)] _CFXR_GLOW_POW ("Apply Power of", Float) = 0
_GlowMin ("Circle Min", Float) = 0
_GlowMax ("Circle Max", Float) = 1
//#
_MaxValue ("Max Value", Float) = 10
//# --------------------------------------------------------
[Toggle(_CFXR_HDR_BOOST)] _HdrBoost ("Enable HDR Multiplier", Float) = 0
//# IF_KEYWORD _CFXR_HDR_BOOST
_HdrMultiply ("HDR Multiplier", Float) = 2
//# END_IF
//# --------------------------------------------------------
[Toggle(_FADING_ON)] _UseSP ("Soft Particles", Float) = 0
//# IF_KEYWORD _FADING_ON
_SoftParticlesFadeDistanceNear ("Near Fade", Float) = 0
_SoftParticlesFadeDistanceFar ("Far Fade", Float) = 1
//# END_IF
//# ========================================================
//# Shadows
//#
[KeywordEnum(Off,On,CustomTexture)] _CFXR_DITHERED_SHADOWS ("Dithered Shadows", Float) = 0
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
_ShadowStrength ("Shadows Strength Max", Range(0,1)) = 1.0
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
_DitherCustom ("Dithering 3D Texture", 3D) = "black" {}
//# END_IF
//# END_IF
}
Category
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
}
Blend [_SrcBlend] [_DstBlend], One One
Cull Off
ZWrite Off
//====================================================================================================================================
// Universal Rendering Pipeline
SubShader
{
Pass
{
Name "BASE"
Tags { "LightMode"="UniversalForward" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:ParticleInstancingSetup
#pragma multi_compile_fog
#pragma shader_feature_local _ _CFXR_GLOW_POW_P2 _CFXR_GLOW_POW_P4 _CFXR_GLOW_POW_P8
#pragma shader_feature_local _ _CFXR_HDR_BOOST
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_URP
#define CFXR_GLOW_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
// Same as above with 'Universal2D' instead and DISABLE_SOFT_PARTICLES keyword
Pass
{
Name "BASE"
Tags { "LightMode"="Universal2D" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:ParticleInstancingSetup
#pragma multi_compile_fog
#pragma shader_feature_local _ _CFXR_GLOW_POW_P2 _CFXR_GLOW_POW_P4 _CFXR_GLOW_POW_P8
#pragma shader_feature_local _ _CFXR_HDR_BOOST
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_URP
#define DISABLE_SOFT_PARTICLES
#define CFXR_GLOW_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
//--------------------------------------------------------------------------------------------------------------------------------
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma shader_feature_local _ _CFXR_GLOW_POW_P2 _CFXR_GLOW_POW_P4 _CFXR_GLOW_POW_P8
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON
#pragma multi_compile_shadowcaster
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
#pragma target 3.0 //needed for VPOS
#endif
#define CFXR_URP
#define PASS_SHADOW_CASTER
#define CFXR_GLOW_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
//====================================================================================================================================
// Built-in Rendering Pipeline
SubShader
{
Pass
{
Name "BASE"
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
//vertInstancingSetup writes to global, not allowed with DXC
// #pragma never_use_dxc
// #pragma target 2.5
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:vertInstancingSetup
#pragma multi_compile_particles
#pragma multi_compile_fog
#pragma shader_feature_local _ _CFXR_GLOW_POW_P2 _CFXR_GLOW_POW_P4 _CFXR_GLOW_POW_P8
#pragma shader_feature_local _ _CFXR_HDR_BOOST
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#include "UnityStandardParticleInstancing.cginc"
#define CFXR_GLOW_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
//--------------------------------------------------------------------------------------------------------------------------------
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
//vertInstancingSetup writes to global, not allowed with DXC
// #pragma never_use_dxc
// #pragma target 2.5
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:vertInstancingSetup
#pragma shader_feature_local _ _CFXR_GLOW_POW_P2 _CFXR_GLOW_POW_P4 _CFXR_GLOW_POW_P8
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON
#pragma multi_compile_shadowcaster
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
#pragma target 3.0 //needed for VPOS
#endif
#include "UnityStandardParticleInstancing.cginc"
#define PASS_SHADOW_CASTER
#define CFXR_GLOW_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
}
CustomEditor "CartoonFX.MaterialInspector"
}

View File

@@ -1,276 +1,276 @@
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
Shader "Cartoon FX/Remaster/Particle Procedural Ring"
{
Properties
{
//# Blending
//#
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Blend Source", Float) = 5
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Blend Destination", Float) = 10
//# --------------------------------------------------------
[Toggle(_CFXR_DISSOLVE)] _UseDissolve ("Enable Dissolve", Float) = 0
//# IF_KEYWORD _CFXR_DISSOLVE
[NoScaleOffset] _DissolveTex ("Dissolve Texture", 2D) = "gray" {}
_DissolveSmooth ("Dissolve Smoothing", Range(0.0001,0.5)) = 0.1
[ToggleNoKeyword] _InvertDissolveTex ("Invert Dissolve Texture", Float) = 0
//# END_IF
//# --------------------------------------------------------
//# Textures
//#
_MainTex ("Texture", 2D) = "white" {}
[Toggle(_CFXR_SINGLE_CHANNEL)] _SingleChannel ("Single Channel Texture", Float) = 0
//# --------------------------------------------------------
//# Ring
//#
[Toggle(_CFXR_RADIAL_UV)] _UseRadialUV ("Enable Radial UVs", Float) = 0
_RingTopOffset ("Ring Offset", float) = 0.05
[Toggle(_CFXR_WORLD_SPACE_RING)] _WorldSpaceRing ("World Space", Float) = 0
//# --------------------------------------------------------
[Toggle(_CFXR_HDR_BOOST)] _HdrBoost ("Enable HDR Multiplier", Float) = 0
//# IF_KEYWORD _CFXR_HDR_BOOST
_HdrMultiply ("HDR Multiplier", Float) = 2
//# END_IF
//# --------------------------------------------------------
[Toggle(_FADING_ON)] _UseSP ("Soft Particles", Float) = 0
//# IF_KEYWORD _FADING_ON
_SoftParticlesFadeDistanceNear ("Near Fade", Float) = 0
_SoftParticlesFadeDistanceFar ("Far Fade", Float) = 1
//# END_IF
//# ========================================================
//# Shadows
//#
[KeywordEnum(Off,On,CustomTexture)] _CFXR_DITHERED_SHADOWS ("Dithered Shadows", Float) = 0
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
_ShadowStrength ("Shadows Strength Max", Range(0,1)) = 1.0
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
_DitherCustom ("Dithering 3D Texture", 3D) = "black" {}
//# END_IF
//# END_IF
}
Category
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
}
Blend [_SrcBlend] [_DstBlend]
Cull Off
ZWrite Off
//====================================================================================================================================
// Universal Rendering Pipeline
SubShader
{
Pass
{
Name "BASE"
Tags { "LightMode"="UniversalForward" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
#pragma multi_compile_fog
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_RADIAL_UV
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_HDR_BOOST
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_URP
#define CFXR_PROCEDURAL_RING_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
// Same as above with 'Universal2D' instead and DISABLE_SOFT_PARTICLES keyword
Pass
{
Name "BASE"
Tags { "LightMode"="Universal2D" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
#pragma multi_compile_fog
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_RADIAL_UV
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_HDR_BOOST
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_URP
#define DISABLE_SOFT_PARTICLES
#define CFXR_PROCEDURAL_RING_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
//--------------------------------------------------------------------------------------------------------------------------------
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_RADIAL_UV
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#pragma multi_compile_shadowcaster
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
#pragma target 3.0 //needed for VPOS
#endif
#define CFXR_URP
#define PASS_SHADOW_CASTER
#define CFXR_PROCEDURAL_RING_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
//====================================================================================================================================
// Built-in Rendering Pipeline
SubShader
{
Pass
{
Name "BASE"
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
#pragma multi_compile_particles
// #pragma multi_compile_instancing
#pragma multi_compile_fog
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_RADIAL_UV
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_HDR_BOOST
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_PROCEDURAL_RING_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
//--------------------------------------------------------------------------------------------------------------------------------
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_RADIAL_UV
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#pragma multi_compile_shadowcaster
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
#pragma target 3.0 //needed for VPOS
#endif
#define PASS_SHADOW_CASTER
#define CFXR_PROCEDURAL_RING_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
}
CustomEditor "CartoonFX.MaterialInspector"
}
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
Shader "Cartoon FX/Remaster/Particle Procedural Ring"
{
Properties
{
//# Blending
//#
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Blend Source", Float) = 5
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Blend Destination", Float) = 10
//# --------------------------------------------------------
[Toggle(_CFXR_DISSOLVE)] _UseDissolve ("Enable Dissolve", Float) = 0
//# IF_KEYWORD _CFXR_DISSOLVE
[NoScaleOffset] _DissolveTex ("Dissolve Texture", 2D) = "gray" {}
_DissolveSmooth ("Dissolve Smoothing", Range(0.0001,0.5)) = 0.1
[ToggleNoKeyword] _InvertDissolveTex ("Invert Dissolve Texture", Float) = 0
//# END_IF
//# --------------------------------------------------------
//# Textures
//#
_MainTex ("Texture", 2D) = "white" {}
[Toggle(_CFXR_SINGLE_CHANNEL)] _SingleChannel ("Single Channel Texture", Float) = 0
//# --------------------------------------------------------
//# Ring
//#
[Toggle(_CFXR_RADIAL_UV)] _UseRadialUV ("Enable Radial UVs", Float) = 0
_RingTopOffset ("Ring Offset", float) = 0.05
[Toggle(_CFXR_WORLD_SPACE_RING)] _WorldSpaceRing ("World Space", Float) = 0
//# --------------------------------------------------------
[Toggle(_CFXR_HDR_BOOST)] _HdrBoost ("Enable HDR Multiplier", Float) = 0
//# IF_KEYWORD _CFXR_HDR_BOOST
_HdrMultiply ("HDR Multiplier", Float) = 2
//# END_IF
//# --------------------------------------------------------
[Toggle(_FADING_ON)] _UseSP ("Soft Particles", Float) = 0
//# IF_KEYWORD _FADING_ON
_SoftParticlesFadeDistanceNear ("Near Fade", Float) = 0
_SoftParticlesFadeDistanceFar ("Far Fade", Float) = 1
//# END_IF
//# ========================================================
//# Shadows
//#
[KeywordEnum(Off,On,CustomTexture)] _CFXR_DITHERED_SHADOWS ("Dithered Shadows", Float) = 0
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
_ShadowStrength ("Shadows Strength Max", Range(0,1)) = 1.0
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
_DitherCustom ("Dithering 3D Texture", 3D) = "black" {}
//# END_IF
//# END_IF
}
Category
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
}
Blend [_SrcBlend] [_DstBlend]
Cull Off
ZWrite Off
//====================================================================================================================================
// Universal Rendering Pipeline
SubShader
{
Pass
{
Name "BASE"
Tags { "LightMode"="UniversalForward" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
#pragma multi_compile_fog
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_RADIAL_UV
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_HDR_BOOST
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_URP
#define CFXR_PROCEDURAL_RING_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
// Same as above with 'Universal2D' instead and DISABLE_SOFT_PARTICLES keyword
Pass
{
Name "BASE"
Tags { "LightMode"="Universal2D" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
#pragma multi_compile_fog
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_RADIAL_UV
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_HDR_BOOST
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_URP
#define DISABLE_SOFT_PARTICLES
#define CFXR_PROCEDURAL_RING_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
//--------------------------------------------------------------------------------------------------------------------------------
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_RADIAL_UV
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#pragma multi_compile_shadowcaster
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
#pragma target 3.0 //needed for VPOS
#endif
#define CFXR_URP
#define PASS_SHADOW_CASTER
#define CFXR_PROCEDURAL_RING_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
//====================================================================================================================================
// Built-in Rendering Pipeline
SubShader
{
Pass
{
Name "BASE"
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
#pragma multi_compile_particles
// #pragma multi_compile_instancing
#pragma multi_compile_fog
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_RADIAL_UV
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_HDR_BOOST
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_PROCEDURAL_RING_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
//--------------------------------------------------------------------------------------------------------------------------------
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_RADIAL_UV
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#pragma multi_compile_shadowcaster
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
#pragma target 3.0 //needed for VPOS
#endif
#define PASS_SHADOW_CASTER
#define CFXR_PROCEDURAL_RING_SHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
}
CustomEditor "CartoonFX.MaterialInspector"
}

View File

@@ -1,449 +1,449 @@
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
Shader "Cartoon FX/Remaster/Particle Ubershader"
{
Properties
{
//# Blending
//#
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Blend Source", Float) = 5
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Blend Destination", Float) = 10
[KeywordEnumNoPrefix(Alpha Blending, _ALPHABLEND_ON, Alpha Blending Premultiplied, _ALPHAPREMULTIPLY_ON, Multiplicative, _ALPHAMODULATE_ON, Additive, _CFXR_ADDITIVE)] _BlendingType ("Blending Type", Float) = 0
//#
[ToggleNoKeyword] _ZWrite ("Depth Write", Float) = 0
[Toggle(_ALPHATEST_ON)] _UseAlphaClip ("Alpha Clipping (Cutout)", Float) = 0
//# IF_KEYWORD _ALPHATEST_ON
_Cutoff ("Cutoff Threshold", Range(0.001,1)) = 0.1
//# END_IF
//# --------------------------------------------------------
[Toggle(_FADING_ON)] _UseSP ("Soft Particles", Float) = 0
//# IF_KEYWORD _FADING_ON
_SoftParticlesFadeDistanceNear ("Near Fade", Float) = 0
_SoftParticlesFadeDistanceFar ("Far Fade", Float) = 1
//# END_IF
//#
[Toggle(_CFXR_EDGE_FADING)] _UseEF ("Edge Fade", Float) = 0
//# IF_KEYWORD _CFXR_EDGE_FADING
_EdgeFadePow ("Edge Fade Power", Float) = 1
//# END_IF
//#
//# ========================================================
//# Effects
//#
[Toggle(_CFXR_DISSOLVE)] _UseDissolve ("Enable Dissolve", Float) = 0
//# IF_KEYWORD _CFXR_DISSOLVE
_DissolveTex ("Dissolve Texture", 2D) = "gray" {}
_DissolveSmooth ("Dissolve Smoothing", Range(0.0001,0.5)) = 0.1
[ToggleNoKeyword] _InvertDissolveTex ("Invert Dissolve Texture", Float) = 0
[ToggleNoKeyword] _DoubleDissolve ("Double Dissolve", Float) = 0
[Toggle(_CFXR_DISSOLVE_ALONG_UV_X)] _UseDissolveOffsetUV ("Dissolve offset along X", Float) = 0
//# IF_KEYWORD _CFXR_DISSOLVE_ALONG_UV_X
_DissolveScroll ("UV Scrolling", Vector) = (0,0,0,0)
//# END_IF
//# END_IF
//# --------------------------------------------------------
[Toggle(_CFXR_UV_DISTORTION)] _UseUVDistortion ("Enable UV Distortion", Float) = 0
//# IF_KEYWORD _CFXR_UV_DISTORTION
[NoScaleOffset] _DistortTex ("Distortion Texture", 2D) = "gray" {}
_DistortScrolling ("Scroll (XY) Tile (ZW)", Vector) = (0,0,1,1)
[Toggle(_CFXR_UV2_DISTORTION)] _UseUV2Distortion ("Use UV2", Float) = 0
_Distort ("Distortion Strength", Range(0,2.0)) = 0.1
[ToggleNoKeyword] _FadeAlongU ("Fade along Y", Float) = 0
[Toggle(_CFXR_UV_DISTORTION_ADD)] _UVDistortionAdd ("Add to base UV", Float) = 0
//# END_IF
//# ========================================================
//# Colors
//#
[NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
[Toggle(_CFXR_SINGLE_CHANNEL)] _SingleChannel ("Single Channel Texture", Float) = 0
//# --------------------------------------------------------
[KeywordEnum(Off,1x,2x)] _CFXR_OVERLAYTEX ("Enable Overlay Texture", Float) = 0
//# IF_KEYWORD _CFXR_OVERLAYTEX_1X || _CFXR_OVERLAYTEX_2X
[KeywordEnum(RGBA,RGB,A)] _CFXR_OVERLAYBLEND ("Overlay Blend Channels", Float) = 0
[NoScaleOffset] _OverlayTex ("Overlay Texture", 2D) = "white" {}
_OverlayTex_Scroll ("Overlay Scrolling / Scale", Vector) = (0.1,0.1,1,1)
//# END_IF
//# --------------------------------------------------------
[Toggle(_FLIPBOOK_BLENDING)] _UseFB ("Flipbook Blending", Float) = 0
//# --------------------------------------------------------
[Toggle(_CFXR_SECONDCOLOR_LERP)] _UseSecondColor ("Secondary Vertex Color (TEXCOORD2)", Float) = 0
//# IF_KEYWORD _CFXR_SECONDCOLOR_LERP
[NoScaleOffset] _SecondColorTex ("Second Color Map", 2D) = "black" {}
_SecondColorSmooth ("Second Color Smoothing", Range(0.0001,0.5)) = 0.2
//# END_IF
//# --------------------------------------------------------
[Toggle(_CFXR_FONT_COLORS)] _UseFontColor ("Use Font Colors", Float) = 0
// //# --------------------------------------------------------
//
// [Toggle(_CFXR_GRADIENTMAP)] _UseGradientMap ("Gradient Map", Float) = 0
// //# IF_KEYWORD _CFXR_GRADIENTMAP
// [NoScaleOffset] _GradientMap ("Gradient Map", 2D) = "black" {}
// //# END_IF
//# --------------------------------------------------------
[Toggle(_CFXR_HDR_BOOST)] _HdrBoost ("Enable HDR Multiplier", Float) = 0
//# IF_KEYWORD _CFXR_HDR_BOOST
_HdrMultiply ("HDR Multiplier", Float) = 2
//# END_IF
//# --------------------------------------------------------
//# Lighting
//#
[KeywordEnumNoPrefix(Off, _, Direct, _CFXR_LIGHTING_DIRECT, Indirect, _CFXR_LIGHTING_INDIRECT, Both, _CFXR_LIGHTING_ALL)] _UseLighting ("Mode", Float) = 0
//# IF_KEYWORD _CFXR_LIGHTING_DIRECT || _CFXR_LIGHTING_ALL
_DirectLightingRamp ("Direct Lighting Ramp", Range(0,1)) = 1.0
//# END_IF
//#
//# IF_KEYWORD _CFXR_LIGHTING_DIRECT || _CFXR_LIGHTING_INDIRECT || _CFXR_LIGHTING_ALL
[Toggle(_NORMALMAP)] _UseNormalMap ("Enable Normal Map", Float) = 0
//# IF_KEYWORD _NORMALMAP
[NoScaleOffset] _BumpMap ("Normal Map", 2D) = "bump" {}
_BumpScale ("Normal Scale", Range(-1, 1)) = 1.0
//# END_IF
//#
[Toggle(_EMISSION)] _UseEmission ("Enable Emission (TEXCOORD2)", Float) = 0
//#
[Toggle(_CFXR_LIGHTING_WPOS_OFFSET)] _UseLightingWorldPosOffset ("Enable World Pos. Offset", Float) = 0
//# IF_KEYWORD _CFXR_LIGHTING_WPOS_OFFSET
_LightingWorldPosStrength ("Offset Strength", Range(0,1)) = 0.2
//# END_IF
//#
[Toggle(_CFXR_LIGHTING_BACK)] _UseBackLighting ("Enable Backlighting", Float) = 0
//# IF_KEYWORD _CFXR_LIGHTING_BACK
_DirLightScreenAtten ("Dir. Light Screen Attenuation", Range(0, 5)) = 1.0
_BacklightTransmittance ("Backlight Transmittance", Range(0, 2)) = 1.0
//# END_IF
//#
//# IF_KEYWORD _CFXR_LIGHTING_INDIRECT || _CFXR_LIGHTING_ALL
_IndirectLightingMix ("Indirect Lighting Mix", Range(0,1)) = 0.5
//# END_IF
_ShadowColor ("Shadow Color", Color) = (0,0,0,1)
//#
//# END_IF
//# ========================================================
//# Shadows
//#
[KeywordEnum(Off,On,CustomTexture)] _CFXR_DITHERED_SHADOWS ("Dithered Shadows", Float) = 0
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
_ShadowStrength ("Shadows Strength Max", Range(0,1)) = 1.0
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
_DitherCustom ("Dithering 3D Texture", 3D) = "black" {}
//# END_IF
//# END_IF
// _ReceivedShadowsStrength ("Received Shadows Strength", Range(0,1)) = 0.5
}
Category
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
}
Blend [_SrcBlend] [_DstBlend], One One
ZWrite [_ZWrite]
Cull Off
//====================================================================================================================================
// Universal Rendering Pipeline
Subshader
{
Pass
{
Name "BASE_URP"
Tags { "LightMode"="UniversalForward" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:ParticleInstancingSetup
#pragma multi_compile_fog
//#pragma multi_compile_fwdbase
//#pragma multi_compile SHADOWS_SCREEN
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_DISSOLVE_ALONG_UV_X
#pragma shader_feature_local _ _CFXR_UV_DISTORTION
#pragma shader_feature_local _ _CFXR_UV2_DISTORTION
#pragma shader_feature_local _ _CFXR_UV_DISTORTION_ADD
// #pragma shader_feature_local _ _CFXR_GRADIENTMAP
#pragma shader_feature_local _ _CFXR_SECONDCOLOR_LERP _CFXR_FONT_COLORS
#pragma shader_feature_local _ _CFXR_OVERLAYTEX_1X _CFXR_OVERLAYTEX_2X
#pragma shader_feature_local _ _CFXR_OVERLAYBLEND_A _CFXR_OVERLAYBLEND_RGB
#pragma shader_feature_local _ _CFXR_HDR_BOOST
#pragma shader_feature_local _ _CFXR_EDGE_FADING
#pragma shader_feature_local _ _CFXR_LIGHTING_DIRECT _CFXR_LIGHTING_INDIRECT _CFXR_LIGHTING_ALL
#pragma shader_feature_local _ _CFXR_LIGHTING_WPOS_OFFSET
#pragma shader_feature_local _ _CFXR_LIGHTING_BACK
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _NORMALMAP
#pragma shader_feature_local _ _EMISSION
#pragma shader_feature_local _ _FLIPBOOK_BLENDING
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_URP
#define CFXR_UBERSHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
// Same as above with 'Universal2D' instead and DISABLE_SOFT_PARTICLES keyword
Pass
{
Name "BASE_URP"
Tags { "LightMode"="Universal2D" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:ParticleInstancingSetup
#pragma multi_compile_fog
//#pragma multi_compile_fwdbase
//#pragma multi_compile SHADOWS_SCREEN
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_DISSOLVE_ALONG_UV_X
#pragma shader_feature_local _ _CFXR_UV_DISTORTION
#pragma shader_feature_local _ _CFXR_UV2_DISTORTION
#pragma shader_feature_local _ _CFXR_UV_DISTORTION_ADD
// #pragma shader_feature_local _ _CFXR_GRADIENTMAP
#pragma shader_feature_local _ _CFXR_SECONDCOLOR_LERP _CFXR_FONT_COLORS
#pragma shader_feature_local _ _CFXR_OVERLAYTEX_1X _CFXR_OVERLAYTEX_2X
#pragma shader_feature_local _ _CFXR_OVERLAYBLEND_A _CFXR_OVERLAYBLEND_RGB
#pragma shader_feature_local _ _CFXR_HDR_BOOST
#pragma shader_feature_local _ _CFXR_EDGE_FADING
#pragma shader_feature_local _ _CFXR_LIGHTING_DIRECT _CFXR_LIGHTING_INDIRECT _CFXR_LIGHTING_ALL
#pragma shader_feature_local _ _CFXR_LIGHTING_WPOS_OFFSET
#pragma shader_feature_local _ _CFXR_LIGHTING_BACK
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _NORMALMAP
#pragma shader_feature_local _ _EMISSION
#pragma shader_feature_local _ _FLIPBOOK_BLENDING
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_UPR
#define DISABLE_SOFT_PARTICLES
#define CFXR_UBERSHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
//--------------------------------------------------------------------------------------------------------------------------------
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_DISSOLVE_ALONG_UV_X
#pragma shader_feature_local _ _CFXR_UV_DISTORTION
#pragma shader_feature_local _ _CFXR_UV2_DISTORTION
#pragma shader_feature_local _ _CFXR_UV_DISTORTION_ADD
#pragma shader_feature_local _ _CFXR_OVERLAYTEX_1X _CFXR_OVERLAYTEX_2X
#pragma shader_feature_local _ _CFXR_OVERLAYBLEND_A _CFXR_OVERLAYBLEND_RGB
#pragma shader_feature_local _ _FLIPBOOK_BLENDING
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#pragma multi_compile_shadowcaster
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
#pragma target 3.0 //needed for VPOS
#endif
#define CFXR_UPR
#define PASS_SHADOW_CASTER
#define CFXR_UBERSHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
//====================================================================================================================================
// Built-in Rendering Pipeline
SubShader
{
Pass
{
Name "BASE"
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
//vertInstancingSetup writes to global, not allowed with DXC
// #pragma never_use_dxc
// #pragma target 2.5
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:vertInstancingSetup
#pragma multi_compile_particles
#pragma multi_compile_fog
//#pragma multi_compile_fwdbase
//#pragma multi_compile SHADOWS_SCREEN
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_DISSOLVE_ALONG_UV_X
#pragma shader_feature_local _ _CFXR_UV_DISTORTION
#pragma shader_feature_local _ _CFXR_UV2_DISTORTION
#pragma shader_feature_local _ _CFXR_UV_DISTORTION_ADD
// #pragma shader_feature_local _ _CFXR_GRADIENTMAP
#pragma shader_feature_local _ _CFXR_SECONDCOLOR_LERP _CFXR_FONT_COLORS
#pragma shader_feature_local _ _CFXR_OVERLAYTEX_1X _CFXR_OVERLAYTEX_2X
#pragma shader_feature_local _ _CFXR_OVERLAYBLEND_A _CFXR_OVERLAYBLEND_RGB
#pragma shader_feature_local _ _CFXR_HDR_BOOST
#pragma shader_feature_local _ _CFXR_EDGE_FADING
#pragma shader_feature_local _ _CFXR_LIGHTING_DIRECT _CFXR_LIGHTING_INDIRECT _CFXR_LIGHTING_ALL
#pragma shader_feature_local _ _CFXR_LIGHTING_WPOS_OFFSET
#pragma shader_feature_local _ _CFXR_LIGHTING_BACK
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _NORMALMAP
#pragma shader_feature_local _ _EMISSION
#pragma shader_feature_local _ _FLIPBOOK_BLENDING
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#include "UnityStandardParticleInstancing.cginc"
#define CFXR_UBERSHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
//--------------------------------------------------------------------------------------------------------------------------------
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
//vertInstancingSetup writes to global, not allowed with DXC
// #pragma never_use_dxc
// #pragma target 2.5
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:vertInstancingSetup
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_DISSOLVE_ALONG_UV_X
#pragma shader_feature_local _ _CFXR_UV_DISTORTION
#pragma shader_feature_local _ _CFXR_UV2_DISTORTION
#pragma shader_feature_local _ _CFXR_UV_DISTORTION_ADD
#pragma shader_feature_local _ _CFXR_OVERLAYTEX_1X _CFXR_OVERLAYTEX_2X
#pragma shader_feature_local _ _CFXR_OVERLAYBLEND_A _CFXR_OVERLAYBLEND_RGB
#pragma shader_feature_local _ _FLIPBOOK_BLENDING
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#pragma multi_compile_shadowcaster
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
#pragma target 3.0 //needed for VPOS
#endif
#include "UnityStandardParticleInstancing.cginc"
#define PASS_SHADOW_CASTER
#define CFXR_UBERSHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
}
CustomEditor "CartoonFX.MaterialInspector"
}
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
Shader "Cartoon FX/Remaster/Particle Ubershader"
{
Properties
{
//# Blending
//#
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Blend Source", Float) = 5
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Blend Destination", Float) = 10
[KeywordEnumNoPrefix(Alpha Blending, _ALPHABLEND_ON, Alpha Blending Premultiplied, _ALPHAPREMULTIPLY_ON, Multiplicative, _ALPHAMODULATE_ON, Additive, _CFXR_ADDITIVE)] _BlendingType ("Blending Type", Float) = 0
//#
[ToggleNoKeyword] _ZWrite ("Depth Write", Float) = 0
[Toggle(_ALPHATEST_ON)] _UseAlphaClip ("Alpha Clipping (Cutout)", Float) = 0
//# IF_KEYWORD _ALPHATEST_ON
_Cutoff ("Cutoff Threshold", Range(0.001,1)) = 0.1
//# END_IF
//# --------------------------------------------------------
[Toggle(_FADING_ON)] _UseSP ("Soft Particles", Float) = 0
//# IF_KEYWORD _FADING_ON
_SoftParticlesFadeDistanceNear ("Near Fade", Float) = 0
_SoftParticlesFadeDistanceFar ("Far Fade", Float) = 1
//# END_IF
//#
[Toggle(_CFXR_EDGE_FADING)] _UseEF ("Edge Fade", Float) = 0
//# IF_KEYWORD _CFXR_EDGE_FADING
_EdgeFadePow ("Edge Fade Power", Float) = 1
//# END_IF
//#
//# ========================================================
//# Effects
//#
[Toggle(_CFXR_DISSOLVE)] _UseDissolve ("Enable Dissolve", Float) = 0
//# IF_KEYWORD _CFXR_DISSOLVE
_DissolveTex ("Dissolve Texture", 2D) = "gray" {}
_DissolveSmooth ("Dissolve Smoothing", Range(0.0001,0.5)) = 0.1
[ToggleNoKeyword] _InvertDissolveTex ("Invert Dissolve Texture", Float) = 0
[ToggleNoKeyword] _DoubleDissolve ("Double Dissolve", Float) = 0
[Toggle(_CFXR_DISSOLVE_ALONG_UV_X)] _UseDissolveOffsetUV ("Dissolve offset along X", Float) = 0
//# IF_KEYWORD _CFXR_DISSOLVE_ALONG_UV_X
_DissolveScroll ("UV Scrolling", Vector) = (0,0,0,0)
//# END_IF
//# END_IF
//# --------------------------------------------------------
[Toggle(_CFXR_UV_DISTORTION)] _UseUVDistortion ("Enable UV Distortion", Float) = 0
//# IF_KEYWORD _CFXR_UV_DISTORTION
[NoScaleOffset] _DistortTex ("Distortion Texture", 2D) = "gray" {}
_DistortScrolling ("Scroll (XY) Tile (ZW)", Vector) = (0,0,1,1)
[Toggle(_CFXR_UV2_DISTORTION)] _UseUV2Distortion ("Use UV2", Float) = 0
_Distort ("Distortion Strength", Range(0,2.0)) = 0.1
[ToggleNoKeyword] _FadeAlongU ("Fade along Y", Float) = 0
[Toggle(_CFXR_UV_DISTORTION_ADD)] _UVDistortionAdd ("Add to base UV", Float) = 0
//# END_IF
//# ========================================================
//# Colors
//#
[NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
[Toggle(_CFXR_SINGLE_CHANNEL)] _SingleChannel ("Single Channel Texture", Float) = 0
//# --------------------------------------------------------
[KeywordEnum(Off,1x,2x)] _CFXR_OVERLAYTEX ("Enable Overlay Texture", Float) = 0
//# IF_KEYWORD _CFXR_OVERLAYTEX_1X || _CFXR_OVERLAYTEX_2X
[KeywordEnum(RGBA,RGB,A)] _CFXR_OVERLAYBLEND ("Overlay Blend Channels", Float) = 0
[NoScaleOffset] _OverlayTex ("Overlay Texture", 2D) = "white" {}
_OverlayTex_Scroll ("Overlay Scrolling / Scale", Vector) = (0.1,0.1,1,1)
//# END_IF
//# --------------------------------------------------------
[Toggle(_FLIPBOOK_BLENDING)] _UseFB ("Flipbook Blending", Float) = 0
//# --------------------------------------------------------
[Toggle(_CFXR_SECONDCOLOR_LERP)] _UseSecondColor ("Secondary Vertex Color (TEXCOORD2)", Float) = 0
//# IF_KEYWORD _CFXR_SECONDCOLOR_LERP
[NoScaleOffset] _SecondColorTex ("Second Color Map", 2D) = "black" {}
_SecondColorSmooth ("Second Color Smoothing", Range(0.0001,0.5)) = 0.2
//# END_IF
//# --------------------------------------------------------
[Toggle(_CFXR_FONT_COLORS)] _UseFontColor ("Use Font Colors", Float) = 0
// //# --------------------------------------------------------
//
// [Toggle(_CFXR_GRADIENTMAP)] _UseGradientMap ("Gradient Map", Float) = 0
// //# IF_KEYWORD _CFXR_GRADIENTMAP
// [NoScaleOffset] _GradientMap ("Gradient Map", 2D) = "black" {}
// //# END_IF
//# --------------------------------------------------------
[Toggle(_CFXR_HDR_BOOST)] _HdrBoost ("Enable HDR Multiplier", Float) = 0
//# IF_KEYWORD _CFXR_HDR_BOOST
_HdrMultiply ("HDR Multiplier", Float) = 2
//# END_IF
//# --------------------------------------------------------
//# Lighting
//#
[KeywordEnumNoPrefix(Off, _, Direct, _CFXR_LIGHTING_DIRECT, Indirect, _CFXR_LIGHTING_INDIRECT, Both, _CFXR_LIGHTING_ALL)] _UseLighting ("Mode", Float) = 0
//# IF_KEYWORD _CFXR_LIGHTING_DIRECT || _CFXR_LIGHTING_ALL
_DirectLightingRamp ("Direct Lighting Ramp", Range(0,1)) = 1.0
//# END_IF
//#
//# IF_KEYWORD _CFXR_LIGHTING_DIRECT || _CFXR_LIGHTING_INDIRECT || _CFXR_LIGHTING_ALL
[Toggle(_NORMALMAP)] _UseNormalMap ("Enable Normal Map", Float) = 0
//# IF_KEYWORD _NORMALMAP
[NoScaleOffset] _BumpMap ("Normal Map", 2D) = "bump" {}
_BumpScale ("Normal Scale", Range(-1, 1)) = 1.0
//# END_IF
//#
[Toggle(_EMISSION)] _UseEmission ("Enable Emission (TEXCOORD2)", Float) = 0
//#
[Toggle(_CFXR_LIGHTING_WPOS_OFFSET)] _UseLightingWorldPosOffset ("Enable World Pos. Offset", Float) = 0
//# IF_KEYWORD _CFXR_LIGHTING_WPOS_OFFSET
_LightingWorldPosStrength ("Offset Strength", Range(0,1)) = 0.2
//# END_IF
//#
[Toggle(_CFXR_LIGHTING_BACK)] _UseBackLighting ("Enable Backlighting", Float) = 0
//# IF_KEYWORD _CFXR_LIGHTING_BACK
_DirLightScreenAtten ("Dir. Light Screen Attenuation", Range(0, 5)) = 1.0
_BacklightTransmittance ("Backlight Transmittance", Range(0, 2)) = 1.0
//# END_IF
//#
//# IF_KEYWORD _CFXR_LIGHTING_INDIRECT || _CFXR_LIGHTING_ALL
_IndirectLightingMix ("Indirect Lighting Mix", Range(0,1)) = 0.5
//# END_IF
_ShadowColor ("Shadow Color", Color) = (0,0,0,1)
//#
//# END_IF
//# ========================================================
//# Shadows
//#
[KeywordEnum(Off,On,CustomTexture)] _CFXR_DITHERED_SHADOWS ("Dithered Shadows", Float) = 0
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
_ShadowStrength ("Shadows Strength Max", Range(0,1)) = 1.0
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
_DitherCustom ("Dithering 3D Texture", 3D) = "black" {}
//# END_IF
//# END_IF
// _ReceivedShadowsStrength ("Received Shadows Strength", Range(0,1)) = 0.5
}
Category
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
}
Blend [_SrcBlend] [_DstBlend], One One
ZWrite [_ZWrite]
Cull Off
//====================================================================================================================================
// Universal Rendering Pipeline
Subshader
{
Pass
{
Name "BASE_URP"
Tags { "LightMode"="UniversalForward" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:ParticleInstancingSetup
#pragma multi_compile_fog
//#pragma multi_compile_fwdbase
//#pragma multi_compile SHADOWS_SCREEN
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_DISSOLVE_ALONG_UV_X
#pragma shader_feature_local _ _CFXR_UV_DISTORTION
#pragma shader_feature_local _ _CFXR_UV2_DISTORTION
#pragma shader_feature_local _ _CFXR_UV_DISTORTION_ADD
// #pragma shader_feature_local _ _CFXR_GRADIENTMAP
#pragma shader_feature_local _ _CFXR_SECONDCOLOR_LERP _CFXR_FONT_COLORS
#pragma shader_feature_local _ _CFXR_OVERLAYTEX_1X _CFXR_OVERLAYTEX_2X
#pragma shader_feature_local _ _CFXR_OVERLAYBLEND_A _CFXR_OVERLAYBLEND_RGB
#pragma shader_feature_local _ _CFXR_HDR_BOOST
#pragma shader_feature_local _ _CFXR_EDGE_FADING
#pragma shader_feature_local _ _CFXR_LIGHTING_DIRECT _CFXR_LIGHTING_INDIRECT _CFXR_LIGHTING_ALL
#pragma shader_feature_local _ _CFXR_LIGHTING_WPOS_OFFSET
#pragma shader_feature_local _ _CFXR_LIGHTING_BACK
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _NORMALMAP
#pragma shader_feature_local _ _EMISSION
#pragma shader_feature_local _ _FLIPBOOK_BLENDING
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_URP
#define CFXR_UBERSHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
// Same as above with 'Universal2D' instead and DISABLE_SOFT_PARTICLES keyword
Pass
{
Name "BASE_URP"
Tags { "LightMode"="Universal2D" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 2.0
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:ParticleInstancingSetup
#pragma multi_compile_fog
//#pragma multi_compile_fwdbase
//#pragma multi_compile SHADOWS_SCREEN
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_DISSOLVE_ALONG_UV_X
#pragma shader_feature_local _ _CFXR_UV_DISTORTION
#pragma shader_feature_local _ _CFXR_UV2_DISTORTION
#pragma shader_feature_local _ _CFXR_UV_DISTORTION_ADD
// #pragma shader_feature_local _ _CFXR_GRADIENTMAP
#pragma shader_feature_local _ _CFXR_SECONDCOLOR_LERP _CFXR_FONT_COLORS
#pragma shader_feature_local _ _CFXR_OVERLAYTEX_1X _CFXR_OVERLAYTEX_2X
#pragma shader_feature_local _ _CFXR_OVERLAYBLEND_A _CFXR_OVERLAYBLEND_RGB
#pragma shader_feature_local _ _CFXR_HDR_BOOST
#pragma shader_feature_local _ _CFXR_EDGE_FADING
#pragma shader_feature_local _ _CFXR_LIGHTING_DIRECT _CFXR_LIGHTING_INDIRECT _CFXR_LIGHTING_ALL
#pragma shader_feature_local _ _CFXR_LIGHTING_WPOS_OFFSET
#pragma shader_feature_local _ _CFXR_LIGHTING_BACK
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _NORMALMAP
#pragma shader_feature_local _ _EMISSION
#pragma shader_feature_local _ _FLIPBOOK_BLENDING
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#define CFXR_UPR
#define DISABLE_SOFT_PARTICLES
#define CFXR_UBERSHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
//--------------------------------------------------------------------------------------------------------------------------------
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_DISSOLVE_ALONG_UV_X
#pragma shader_feature_local _ _CFXR_UV_DISTORTION
#pragma shader_feature_local _ _CFXR_UV2_DISTORTION
#pragma shader_feature_local _ _CFXR_UV_DISTORTION_ADD
#pragma shader_feature_local _ _CFXR_OVERLAYTEX_1X _CFXR_OVERLAYTEX_2X
#pragma shader_feature_local _ _CFXR_OVERLAYBLEND_A _CFXR_OVERLAYBLEND_RGB
#pragma shader_feature_local _ _FLIPBOOK_BLENDING
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#pragma multi_compile_shadowcaster
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
#pragma target 3.0 //needed for VPOS
#endif
#define CFXR_UPR
#define PASS_SHADOW_CASTER
#define CFXR_UBERSHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
//====================================================================================================================================
// Built-in Rendering Pipeline
SubShader
{
Pass
{
Name "BASE"
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
//vertInstancingSetup writes to global, not allowed with DXC
// #pragma never_use_dxc
// #pragma target 2.5
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:vertInstancingSetup
#pragma multi_compile_particles
#pragma multi_compile_fog
//#pragma multi_compile_fwdbase
//#pragma multi_compile SHADOWS_SCREEN
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_DISSOLVE_ALONG_UV_X
#pragma shader_feature_local _ _CFXR_UV_DISTORTION
#pragma shader_feature_local _ _CFXR_UV2_DISTORTION
#pragma shader_feature_local _ _CFXR_UV_DISTORTION_ADD
// #pragma shader_feature_local _ _CFXR_GRADIENTMAP
#pragma shader_feature_local _ _CFXR_SECONDCOLOR_LERP _CFXR_FONT_COLORS
#pragma shader_feature_local _ _CFXR_OVERLAYTEX_1X _CFXR_OVERLAYTEX_2X
#pragma shader_feature_local _ _CFXR_OVERLAYBLEND_A _CFXR_OVERLAYBLEND_RGB
#pragma shader_feature_local _ _CFXR_HDR_BOOST
#pragma shader_feature_local _ _CFXR_EDGE_FADING
#pragma shader_feature_local _ _CFXR_LIGHTING_DIRECT _CFXR_LIGHTING_INDIRECT _CFXR_LIGHTING_ALL
#pragma shader_feature_local _ _CFXR_LIGHTING_WPOS_OFFSET
#pragma shader_feature_local _ _CFXR_LIGHTING_BACK
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage
#pragma shader_feature_local _ _NORMALMAP
#pragma shader_feature_local _ _EMISSION
#pragma shader_feature_local _ _FLIPBOOK_BLENDING
#pragma shader_feature_local _ _FADING_ON
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#include "UnityStandardParticleInstancing.cginc"
#define CFXR_UBERSHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
//--------------------------------------------------------------------------------------------------------------------------------
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
BlendOp Add
Blend One Zero
ZWrite On
Cull Off
CGPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
//vertInstancingSetup writes to global, not allowed with DXC
// #pragma never_use_dxc
// #pragma target 2.5
// #pragma multi_compile_instancing
// #pragma instancing_options procedural:vertInstancingSetup
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL
#pragma shader_feature_local _ _CFXR_DISSOLVE
#pragma shader_feature_local _ _CFXR_DISSOLVE_ALONG_UV_X
#pragma shader_feature_local _ _CFXR_UV_DISTORTION
#pragma shader_feature_local _ _CFXR_UV2_DISTORTION
#pragma shader_feature_local _ _CFXR_UV_DISTORTION_ADD
#pragma shader_feature_local _ _CFXR_OVERLAYTEX_1X _CFXR_OVERLAYTEX_2X
#pragma shader_feature_local _ _CFXR_OVERLAYBLEND_A _CFXR_OVERLAYBLEND_RGB
#pragma shader_feature_local _ _FLIPBOOK_BLENDING
#pragma shader_feature_local _ _ALPHATEST_ON
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE
#pragma multi_compile_shadowcaster
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
#pragma target 3.0 //needed for VPOS
#endif
#include "UnityStandardParticleInstancing.cginc"
#define PASS_SHADOW_CASTER
#define CFXR_UBERSHADER
#include "CFXR_PASSES.cginc"
ENDCG
}
}
}
CustomEditor "CartoonFX.MaterialInspector"
}

View File

@@ -1,360 +1,360 @@
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
#pragma exclude_renderers gles
#endif
#if defined(GLOBAL_DISABLE_SOFT_PARTICLES) && !defined(DISABLE_SOFT_PARTICLES)
#define DISABLE_SOFT_PARTICLES
#endif
#if defined(CFXR_URP)
float LinearEyeDepthURP(float depth, float4 zBufferParam)
{
return 1.0 / (zBufferParam.z * depth + zBufferParam.w);
}
float SoftParticles(float near, float far, float4 projection)
{
float sceneZ = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(projection)).r;
#if defined(SOFT_PARTICLES_ORTHOGRAPHIC)
// orthographic camera
#if defined(UNITY_REVERSED_Z)
sceneZ = 1.0f - sceneZ;
#endif
sceneZ = (sceneZ * _ProjectionParams.z) + _ProjectionParams.y;
#else
// perspective camera
sceneZ = LinearEyeDepthURP(sceneZ, _ZBufferParams);
#endif
float fade = saturate (far * ((sceneZ - near) - projection.z));
return fade;
}
#else
float SoftParticles(float near, float far, float4 projection)
{
float sceneZ = (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(projection)));
#if defined(SOFT_PARTICLES_ORTHOGRAPHIC)
// orthographic camera
#if defined(UNITY_REVERSED_Z)
sceneZ = 1.0f - sceneZ;
#endif
sceneZ = (sceneZ * _ProjectionParams.z) + _ProjectionParams.y;
#else
// perspective camera
sceneZ = LinearEyeDepth(sceneZ);
#endif
float fade = saturate (far * ((sceneZ - near) - projection.z));
return fade;
}
#endif
float LinearToGammaSpaceApprox(float value)
{
return max(1.055h * pow(value, 0.416666667h) - 0.055h, 0.h);
}
// Same as UnityStandardUtils.cginc, but without the SHADER_TARGET limitation
half3 UnpackScaleNormal_CFXR(half4 packednormal, half bumpScale)
{
#if defined(UNITY_NO_DXT5nm)
half3 normal = packednormal.xyz * 2 - 1;
// #if (SHADER_TARGET >= 30)
// SM2.0: instruction count limitation
// SM2.0: normal scaler is not supported
normal.xy *= bumpScale;
// #endif
return normal;
#else
// This do the trick
packednormal.x *= packednormal.w;
half3 normal;
normal.xy = (packednormal.xy * 2 - 1);
// #if (SHADER_TARGET >= 30)
// SM2.0: instruction count limitation
// SM2.0: normal scaler is not supported
normal.xy *= bumpScale;
// #endif
normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
return normal;
#endif
}
//Macros
// Project Position
#if !defined(PASS_SHADOW_CASTER) && !defined(GLOBAL_DISABLE_SOFT_PARTICLES) && !defined(DISABLE_SOFT_PARTICLES) && ( (defined(SOFTPARTICLES_ON) || defined(CFXR_URP) || defined(SOFT_PARTICLES_ORTHOGRAPHIC)) && defined(_FADING_ON) )
#define vertProjPos(o, clipPos) \
o.projPos = ComputeScreenPos(clipPos); \
COMPUTE_EYEDEPTH(o.projPos.z);
#else
#define vertProjPos(o, clipPos)
#endif
// Soft Particles
#if !defined(PASS_SHADOW_CASTER) && !defined(GLOBAL_DISABLE_SOFT_PARTICLES) && !defined(DISABLE_SOFT_PARTICLES) && ((defined(SOFTPARTICLES_ON) || defined(CFXR_URP) || defined(SOFT_PARTICLES_ORTHOGRAPHIC)) && defined(_FADING_ON))
#define fragSoftParticlesFade(i, color) \
color *= SoftParticles(_SoftParticlesFadeDistanceNear, _SoftParticlesFadeDistanceFar, i.projPos);
#else
#define fragSoftParticlesFade(i, color)
#endif
// Edge fade (note: particle meshes are already in world space)
#if !defined(PASS_SHADOW_CASTER) && defined(_CFXR_EDGE_FADING)
#define vertEdgeFade(v, color) \
float3 viewDir = UnityWorldSpaceViewDir(v.vertex); \
float ndv = abs(dot(normalize(viewDir), v.normal.xyz)); \
color *= saturate(pow(ndv, _EdgeFadePow));
#else
#define vertEdgeFade(v, color)
#endif
// Fog
#if _ALPHABLEND_ON
#define applyFog(i, color, alpha) UNITY_APPLY_FOG_COLOR(i.fogCoord, color, unity_FogColor);
#elif _ALPHAPREMULTIPLY_ON
#define applyFog(i, color, alpha) UNITY_APPLY_FOG_COLOR(i.fogCoord, color, alpha * unity_FogColor);
#elif _CFXR_ADDITIVE
#define applyFog(i, color, alpha) UNITY_APPLY_FOG_COLOR(i.fogCoord, color, half4(0, 0, 0, 0));
#elif _ALPHAMODULATE_ON
#define applyFog(i, color, alpha) UNITY_APPLY_FOG_COLOR(i.fogCoord, color, half4(1, 1, 1, 1));
#else
#define applyFog(i, color, alpha) UNITY_APPLY_FOG_COLOR(i.fogCoord, color, unity_FogColor);
#endif
// Vertex program
#if defined(PASS_SHADOW_CASTER)
void vert(appdata v, v2f_shadowCaster o, out float4 opos)
#else
v2f vert(appdata v, v2f o)
#endif
{
UNITY_TRANSFER_FOG(o, o.pos);
vertProjPos(o, o.pos);
vertEdgeFade(v, o.color.a);
#if defined(PASS_SHADOW_CASTER)
TRANSFER_SHADOW_CASTER_NOPOS(o, opos);
#else
return o;
#endif
}
// Fragment program
#if defined(PASS_SHADOW_CASTER)
float4 frag(v2f_shadowCaster i, UNITY_VPOS_TYPE vpos, half3 particleColor, half particleAlpha, half dissolve, half dissolveTime, half doubleDissolveWidth) : SV_Target
#else
half4 frag(v2f i, half3 particleColor, half particleAlpha, half dissolve, half dissolveTime, half doubleDissolveWidth) : SV_Target
#endif
{
#if _CFXR_DISSOLVE
// Dissolve
half time = lerp(-_DissolveSmooth, 1+_DissolveSmooth, dissolveTime);
particleAlpha *= smoothstep(dissolve - _DissolveSmooth, dissolve + _DissolveSmooth, time);
if (doubleDissolveWidth > 0)
{
half dissolveSubtract = smoothstep(dissolve - _DissolveSmooth, dissolve + _DissolveSmooth, time - doubleDissolveWidth);
particleAlpha = saturate(particleAlpha - dissolveSubtract);
}
#endif
//Blending
#if _ALPHAPREMULTIPLY_ON
particleColor *= particleAlpha;
#endif
#if _ALPHAMODULATE_ON
particleColor.rgb = lerp(float3(1,1,1), particleColor.rgb, particleAlpha);
#endif
#if _ALPHATEST_ON
clip(particleAlpha - _Cutoff);
#endif
#if !defined(PASS_SHADOW_CASTER)
// Fog & Soft Particles
applyFog(i, particleColor, particleAlpha);
fragSoftParticlesFade(i, particleAlpha);
#endif
// Prevent alpha from exceeding 1
particleAlpha = min(particleAlpha, 1.0);
#if !defined(PASS_SHADOW_CASTER)
return float4(particleColor, particleAlpha);
#else
//--------------------------------------------------------------------------------------------------------------------------------
// Shadow Caster Pass
#if _CFXR_ADDITIVE
half alpha = max(particleColor.r, max(particleColor.g, particleColor.b)) * particleAlpha;
#else
half alpha = particleAlpha;
#endif
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
alpha = min(alpha, _ShadowStrength);
// Use dither mask for alpha blended shadows, based on pixel position xy
// and alpha level. Our dither texture is 4x4x16.
#if _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
half texSize = _DitherCustom_TexelSize.z;
alpha = tex3D(_DitherCustom, float3(vpos.xy*(1 / texSize), alpha*(1 - (1 / (texSize*texSize))))).a;
#else
alpha = tex3D(_DitherMaskLOD, float3(vpos.xy*0.25, alpha*0.9375)).a;
#endif
#endif
clip(alpha - 0.01);
SHADOW_CASTER_FRAGMENT(i)
#endif
}
// ================================================================================================================================
// ParticlesInstancing.hlsl
// ================================================================================================================================
#if defined(CFXR_URP)
#if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED) && !defined(SHADER_TARGET_SURFACE_ANALYSIS)
#define UNITY_PARTICLE_INSTANCING_ENABLED
#endif
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
#ifndef UNITY_PARTICLE_INSTANCE_DATA
#define UNITY_PARTICLE_INSTANCE_DATA DefaultParticleInstanceData
#endif
struct DefaultParticleInstanceData
{
float3x4 transform;
uint color;
float animFrame;
};
StructuredBuffer<UNITY_PARTICLE_INSTANCE_DATA> unity_ParticleInstanceData;
float4 unity_ParticleUVShiftData;
float unity_ParticleUseMeshColors;
void ParticleInstancingMatrices(out float4x4 objectToWorld, out float4x4 worldToObject)
{
UNITY_PARTICLE_INSTANCE_DATA data = unity_ParticleInstanceData[unity_InstanceID];
// transform matrix
objectToWorld._11_21_31_41 = float4(data.transform._11_21_31, 0.0f);
objectToWorld._12_22_32_42 = float4(data.transform._12_22_32, 0.0f);
objectToWorld._13_23_33_43 = float4(data.transform._13_23_33, 0.0f);
objectToWorld._14_24_34_44 = float4(data.transform._14_24_34, 1.0f);
// inverse transform matrix (TODO: replace with a library implementation if/when available)
float3x3 worldToObject3x3;
worldToObject3x3[0] = objectToWorld[1].yzx * objectToWorld[2].zxy - objectToWorld[1].zxy * objectToWorld[2].yzx;
worldToObject3x3[1] = objectToWorld[0].zxy * objectToWorld[2].yzx - objectToWorld[0].yzx * objectToWorld[2].zxy;
worldToObject3x3[2] = objectToWorld[0].yzx * objectToWorld[1].zxy - objectToWorld[0].zxy * objectToWorld[1].yzx;
float det = dot(objectToWorld[0].xyz, worldToObject3x3[0]);
worldToObject3x3 = transpose(worldToObject3x3);
worldToObject3x3 *= rcp(det);
float3 worldToObjectPosition = mul(worldToObject3x3, -objectToWorld._14_24_34);
worldToObject._11_21_31_41 = float4(worldToObject3x3._11_21_31, 0.0f);
worldToObject._12_22_32_42 = float4(worldToObject3x3._12_22_32, 0.0f);
worldToObject._13_23_33_43 = float4(worldToObject3x3._13_23_33, 0.0f);
worldToObject._14_24_34_44 = float4(worldToObjectPosition, 1.0f);
}
void ParticleInstancingSetup()
{
ParticleInstancingMatrices(unity_ObjectToWorld, unity_WorldToObject);
}
#else
void ParticleInstancingSetup() {}
#endif
#endif
// ================================================================================================================================
// Instancing functions
// ================================================================================================================================
float4 UnpackFromR8G8B8A8(uint rgba)
{
return float4(rgba & 255, (rgba >> 8) & 255, (rgba >> 16) & 255, (rgba >> 24) & 255) * (1.0 / 255);
}
half4 GetParticleColor(half4 color)
{
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
#if !defined(UNITY_PARTICLE_INSTANCE_DATA_NO_COLOR)
UNITY_PARTICLE_INSTANCE_DATA data = unity_ParticleInstanceData[unity_InstanceID];
color = lerp(half4(1.0, 1.0, 1.0, 1.0), color, unity_ParticleUseMeshColors);
color *= UnpackFromR8G8B8A8(data.color);
#endif
#endif
return color;
}
void GetParticleTexcoords(out float2 outputTexcoord, out float2 outputTexcoord2, out float outputBlend, in float4 inputTexcoords, in float inputBlend)
{
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
if (unity_ParticleUVShiftData.x != 0.0)
{
UNITY_PARTICLE_INSTANCE_DATA data = unity_ParticleInstanceData[unity_InstanceID];
float numTilesX = unity_ParticleUVShiftData.y;
float2 animScale = unity_ParticleUVShiftData.zw;
#ifdef UNITY_PARTICLE_INSTANCE_DATA_NO_ANIM_FRAME
float sheetIndex = 0.0;
#else
float sheetIndex = data.animFrame;
#endif
float index0 = floor(sheetIndex);
float vIdx0 = floor(index0 / numTilesX);
float uIdx0 = floor(index0 - vIdx0 * numTilesX);
float2 offset0 = float2(uIdx0 * animScale.x, (1.0 - animScale.y) - vIdx0 * animScale.y); // Copied from built-in as is and it looks like upside-down flip
outputTexcoord = inputTexcoords.xy * animScale.xy + offset0.xy;
#ifdef _FLIPBOOKBLENDING_ON
float index1 = floor(sheetIndex + 1.0);
float vIdx1 = floor(index1 / numTilesX);
float uIdx1 = floor(index1 - vIdx1 * numTilesX);
float2 offset1 = float2(uIdx1 * animScale.x, (1.0 - animScale.y) - vIdx1 * animScale.y);
outputTexcoord2.xy = inputTexcoords.xy * animScale.xy + offset1.xy;
outputBlend = frac(sheetIndex);
#endif
}
else
#endif
{
outputTexcoord = inputTexcoords.xy;
#ifdef _FLIPBOOKBLENDING_ON
outputTexcoord2.xy = inputTexcoords.zw;
outputBlend = inputBlend;
#endif
}
#ifndef _FLIPBOOKBLENDING_ON
outputTexcoord2.xy = inputTexcoords.xy;
outputBlend = 0.5;
#endif
}
void GetParticleTexcoords(out float2 outputTexcoord, in float2 inputTexcoord)
{
float2 dummyTexcoord2 = 0.0;
float dummyBlend = 0.0;
GetParticleTexcoords(outputTexcoord, dummyTexcoord2, dummyBlend, inputTexcoord.xyxy, 0.0);
}
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
#pragma exclude_renderers gles
#endif
#if defined(GLOBAL_DISABLE_SOFT_PARTICLES) && !defined(DISABLE_SOFT_PARTICLES)
#define DISABLE_SOFT_PARTICLES
#endif
#if defined(CFXR_URP)
float LinearEyeDepthURP(float depth, float4 zBufferParam)
{
return 1.0 / (zBufferParam.z * depth + zBufferParam.w);
}
float SoftParticles(float near, float far, float4 projection)
{
float sceneZ = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(projection)).r;
#if defined(SOFT_PARTICLES_ORTHOGRAPHIC)
// orthographic camera
#if defined(UNITY_REVERSED_Z)
sceneZ = 1.0f - sceneZ;
#endif
sceneZ = (sceneZ * _ProjectionParams.z) + _ProjectionParams.y;
#else
// perspective camera
sceneZ = LinearEyeDepthURP(sceneZ, _ZBufferParams);
#endif
float fade = saturate (far * ((sceneZ - near) - projection.z));
return fade;
}
#else
float SoftParticles(float near, float far, float4 projection)
{
float sceneZ = (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(projection)));
#if defined(SOFT_PARTICLES_ORTHOGRAPHIC)
// orthographic camera
#if defined(UNITY_REVERSED_Z)
sceneZ = 1.0f - sceneZ;
#endif
sceneZ = (sceneZ * _ProjectionParams.z) + _ProjectionParams.y;
#else
// perspective camera
sceneZ = LinearEyeDepth(sceneZ);
#endif
float fade = saturate (far * ((sceneZ - near) - projection.z));
return fade;
}
#endif
float LinearToGammaSpaceApprox(float value)
{
return max(1.055h * pow(value, 0.416666667h) - 0.055h, 0.h);
}
// Same as UnityStandardUtils.cginc, but without the SHADER_TARGET limitation
half3 UnpackScaleNormal_CFXR(half4 packednormal, half bumpScale)
{
#if defined(UNITY_NO_DXT5nm)
half3 normal = packednormal.xyz * 2 - 1;
// #if (SHADER_TARGET >= 30)
// SM2.0: instruction count limitation
// SM2.0: normal scaler is not supported
normal.xy *= bumpScale;
// #endif
return normal;
#else
// This do the trick
packednormal.x *= packednormal.w;
half3 normal;
normal.xy = (packednormal.xy * 2 - 1);
// #if (SHADER_TARGET >= 30)
// SM2.0: instruction count limitation
// SM2.0: normal scaler is not supported
normal.xy *= bumpScale;
// #endif
normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
return normal;
#endif
}
//Macros
// Project Position
#if !defined(PASS_SHADOW_CASTER) && !defined(GLOBAL_DISABLE_SOFT_PARTICLES) && !defined(DISABLE_SOFT_PARTICLES) && ( (defined(SOFTPARTICLES_ON) || defined(CFXR_URP) || defined(SOFT_PARTICLES_ORTHOGRAPHIC)) && defined(_FADING_ON) )
#define vertProjPos(o, clipPos) \
o.projPos = ComputeScreenPos(clipPos); \
COMPUTE_EYEDEPTH(o.projPos.z);
#else
#define vertProjPos(o, clipPos)
#endif
// Soft Particles
#if !defined(PASS_SHADOW_CASTER) && !defined(GLOBAL_DISABLE_SOFT_PARTICLES) && !defined(DISABLE_SOFT_PARTICLES) && ((defined(SOFTPARTICLES_ON) || defined(CFXR_URP) || defined(SOFT_PARTICLES_ORTHOGRAPHIC)) && defined(_FADING_ON))
#define fragSoftParticlesFade(i, color) \
color *= SoftParticles(_SoftParticlesFadeDistanceNear, _SoftParticlesFadeDistanceFar, i.projPos);
#else
#define fragSoftParticlesFade(i, color)
#endif
// Edge fade (note: particle meshes are already in world space)
#if !defined(PASS_SHADOW_CASTER) && defined(_CFXR_EDGE_FADING)
#define vertEdgeFade(v, color) \
float3 viewDir = UnityWorldSpaceViewDir(v.vertex); \
float ndv = abs(dot(normalize(viewDir), v.normal.xyz)); \
color *= saturate(pow(ndv, _EdgeFadePow));
#else
#define vertEdgeFade(v, color)
#endif
// Fog
#if _ALPHABLEND_ON
#define applyFog(i, color, alpha) UNITY_APPLY_FOG_COLOR(i.fogCoord, color, unity_FogColor);
#elif _ALPHAPREMULTIPLY_ON
#define applyFog(i, color, alpha) UNITY_APPLY_FOG_COLOR(i.fogCoord, color, alpha * unity_FogColor);
#elif _CFXR_ADDITIVE
#define applyFog(i, color, alpha) UNITY_APPLY_FOG_COLOR(i.fogCoord, color, half4(0, 0, 0, 0));
#elif _ALPHAMODULATE_ON
#define applyFog(i, color, alpha) UNITY_APPLY_FOG_COLOR(i.fogCoord, color, half4(1, 1, 1, 1));
#else
#define applyFog(i, color, alpha) UNITY_APPLY_FOG_COLOR(i.fogCoord, color, unity_FogColor);
#endif
// Vertex program
#if defined(PASS_SHADOW_CASTER)
void vert(appdata v, v2f_shadowCaster o, out float4 opos)
#else
v2f vert(appdata v, v2f o)
#endif
{
UNITY_TRANSFER_FOG(o, o.pos);
vertProjPos(o, o.pos);
vertEdgeFade(v, o.color.a);
#if defined(PASS_SHADOW_CASTER)
TRANSFER_SHADOW_CASTER_NOPOS(o, opos);
#else
return o;
#endif
}
// Fragment program
#if defined(PASS_SHADOW_CASTER)
float4 frag(v2f_shadowCaster i, UNITY_VPOS_TYPE vpos, half3 particleColor, half particleAlpha, half dissolve, half dissolveTime, half doubleDissolveWidth) : SV_Target
#else
half4 frag(v2f i, half3 particleColor, half particleAlpha, half dissolve, half dissolveTime, half doubleDissolveWidth) : SV_Target
#endif
{
#if _CFXR_DISSOLVE
// Dissolve
half time = lerp(-_DissolveSmooth, 1+_DissolveSmooth, dissolveTime);
particleAlpha *= smoothstep(dissolve - _DissolveSmooth, dissolve + _DissolveSmooth, time);
if (doubleDissolveWidth > 0)
{
half dissolveSubtract = smoothstep(dissolve - _DissolveSmooth, dissolve + _DissolveSmooth, time - doubleDissolveWidth);
particleAlpha = saturate(particleAlpha - dissolveSubtract);
}
#endif
//Blending
#if _ALPHAPREMULTIPLY_ON
particleColor *= particleAlpha;
#endif
#if _ALPHAMODULATE_ON
particleColor.rgb = lerp(float3(1,1,1), particleColor.rgb, particleAlpha);
#endif
#if _ALPHATEST_ON
clip(particleAlpha - _Cutoff);
#endif
#if !defined(PASS_SHADOW_CASTER)
// Fog & Soft Particles
applyFog(i, particleColor, particleAlpha);
fragSoftParticlesFade(i, particleAlpha);
#endif
// Prevent alpha from exceeding 1
particleAlpha = min(particleAlpha, 1.0);
#if !defined(PASS_SHADOW_CASTER)
return float4(particleColor, particleAlpha);
#else
//--------------------------------------------------------------------------------------------------------------------------------
// Shadow Caster Pass
#if _CFXR_ADDITIVE
half alpha = max(particleColor.r, max(particleColor.g, particleColor.b)) * particleAlpha;
#else
half alpha = particleAlpha;
#endif
#if (_CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE) && !defined(SHADER_API_GLES)
alpha = min(alpha, _ShadowStrength);
// Use dither mask for alpha blended shadows, based on pixel position xy
// and alpha level. Our dither texture is 4x4x16.
#if _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE
half texSize = _DitherCustom_TexelSize.z;
alpha = tex3D(_DitherCustom, float3(vpos.xy*(1 / texSize), alpha*(1 - (1 / (texSize*texSize))))).a;
#else
alpha = tex3D(_DitherMaskLOD, float3(vpos.xy*0.25, alpha*0.9375)).a;
#endif
#endif
clip(alpha - 0.01);
SHADOW_CASTER_FRAGMENT(i)
#endif
}
// ================================================================================================================================
// ParticlesInstancing.hlsl
// ================================================================================================================================
#if defined(CFXR_URP)
#if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED) && !defined(SHADER_TARGET_SURFACE_ANALYSIS)
#define UNITY_PARTICLE_INSTANCING_ENABLED
#endif
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
#ifndef UNITY_PARTICLE_INSTANCE_DATA
#define UNITY_PARTICLE_INSTANCE_DATA DefaultParticleInstanceData
#endif
struct DefaultParticleInstanceData
{
float3x4 transform;
uint color;
float animFrame;
};
StructuredBuffer<UNITY_PARTICLE_INSTANCE_DATA> unity_ParticleInstanceData;
float4 unity_ParticleUVShiftData;
float unity_ParticleUseMeshColors;
void ParticleInstancingMatrices(out float4x4 objectToWorld, out float4x4 worldToObject)
{
UNITY_PARTICLE_INSTANCE_DATA data = unity_ParticleInstanceData[unity_InstanceID];
// transform matrix
objectToWorld._11_21_31_41 = float4(data.transform._11_21_31, 0.0f);
objectToWorld._12_22_32_42 = float4(data.transform._12_22_32, 0.0f);
objectToWorld._13_23_33_43 = float4(data.transform._13_23_33, 0.0f);
objectToWorld._14_24_34_44 = float4(data.transform._14_24_34, 1.0f);
// inverse transform matrix (TODO: replace with a library implementation if/when available)
float3x3 worldToObject3x3;
worldToObject3x3[0] = objectToWorld[1].yzx * objectToWorld[2].zxy - objectToWorld[1].zxy * objectToWorld[2].yzx;
worldToObject3x3[1] = objectToWorld[0].zxy * objectToWorld[2].yzx - objectToWorld[0].yzx * objectToWorld[2].zxy;
worldToObject3x3[2] = objectToWorld[0].yzx * objectToWorld[1].zxy - objectToWorld[0].zxy * objectToWorld[1].yzx;
float det = dot(objectToWorld[0].xyz, worldToObject3x3[0]);
worldToObject3x3 = transpose(worldToObject3x3);
worldToObject3x3 *= rcp(det);
float3 worldToObjectPosition = mul(worldToObject3x3, -objectToWorld._14_24_34);
worldToObject._11_21_31_41 = float4(worldToObject3x3._11_21_31, 0.0f);
worldToObject._12_22_32_42 = float4(worldToObject3x3._12_22_32, 0.0f);
worldToObject._13_23_33_43 = float4(worldToObject3x3._13_23_33, 0.0f);
worldToObject._14_24_34_44 = float4(worldToObjectPosition, 1.0f);
}
void ParticleInstancingSetup()
{
ParticleInstancingMatrices(unity_ObjectToWorld, unity_WorldToObject);
}
#else
void ParticleInstancingSetup() {}
#endif
#endif
// ================================================================================================================================
// Instancing functions
// ================================================================================================================================
float4 UnpackFromR8G8B8A8(uint rgba)
{
return float4(rgba & 255, (rgba >> 8) & 255, (rgba >> 16) & 255, (rgba >> 24) & 255) * (1.0 / 255);
}
half4 GetParticleColor(half4 color)
{
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
#if !defined(UNITY_PARTICLE_INSTANCE_DATA_NO_COLOR)
UNITY_PARTICLE_INSTANCE_DATA data = unity_ParticleInstanceData[unity_InstanceID];
color = lerp(half4(1.0, 1.0, 1.0, 1.0), color, unity_ParticleUseMeshColors);
color *= UnpackFromR8G8B8A8(data.color);
#endif
#endif
return color;
}
void GetParticleTexcoords(out float2 outputTexcoord, out float2 outputTexcoord2, out float outputBlend, in float4 inputTexcoords, in float inputBlend)
{
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
if (unity_ParticleUVShiftData.x != 0.0)
{
UNITY_PARTICLE_INSTANCE_DATA data = unity_ParticleInstanceData[unity_InstanceID];
float numTilesX = unity_ParticleUVShiftData.y;
float2 animScale = unity_ParticleUVShiftData.zw;
#ifdef UNITY_PARTICLE_INSTANCE_DATA_NO_ANIM_FRAME
float sheetIndex = 0.0;
#else
float sheetIndex = data.animFrame;
#endif
float index0 = floor(sheetIndex);
float vIdx0 = floor(index0 / numTilesX);
float uIdx0 = floor(index0 - vIdx0 * numTilesX);
float2 offset0 = float2(uIdx0 * animScale.x, (1.0 - animScale.y) - vIdx0 * animScale.y); // Copied from built-in as is and it looks like upside-down flip
outputTexcoord = inputTexcoords.xy * animScale.xy + offset0.xy;
#ifdef _FLIPBOOKBLENDING_ON
float index1 = floor(sheetIndex + 1.0);
float vIdx1 = floor(index1 / numTilesX);
float uIdx1 = floor(index1 - vIdx1 * numTilesX);
float2 offset1 = float2(uIdx1 * animScale.x, (1.0 - animScale.y) - vIdx1 * animScale.y);
outputTexcoord2.xy = inputTexcoords.xy * animScale.xy + offset1.xy;
outputBlend = frac(sheetIndex);
#endif
}
else
#endif
{
outputTexcoord = inputTexcoords.xy;
#ifdef _FLIPBOOKBLENDING_ON
outputTexcoord2.xy = inputTexcoords.zw;
outputBlend = inputBlend;
#endif
}
#ifndef _FLIPBOOKBLENDING_ON
outputTexcoord2.xy = inputTexcoords.xy;
outputBlend = 0.5;
#endif
}
void GetParticleTexcoords(out float2 outputTexcoord, in float2 inputTexcoord)
{
float2 dummyTexcoord2 = 0.0;
float dummyBlend = 0.0;
GetParticleTexcoords(outputTexcoord, dummyTexcoord2, dummyBlend, inputTexcoord.xyxy, 0.0);
}

View File

@@ -1,24 +1,24 @@
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
// Global settings for the Cartoon FX Remaster shaders
//--------------------------------------------------------------------------------------------------------------------------------
/* Uncomment this line if you want to globally disable soft particles */
// #define GLOBAL_DISABLE_SOFT_PARTICLES
/* Uncomment this line to do Soft Particles depth calculation in Orthographic mode */
// #define SOFT_PARTICLES_ORTHOGRAPHIC
/* Change this value if you want to globally scale the HDR effects */
#define GLOBAL_HDR_MULTIPLIER 1
/* Comment this line if you want to disable point lights for lit particles */
#define ENABLE_POINT_LIGHTS
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
// Global settings for the Cartoon FX Remaster shaders
//--------------------------------------------------------------------------------------------------------------------------------
/* Uncomment this line if you want to globally disable soft particles */
// #define GLOBAL_DISABLE_SOFT_PARTICLES
/* Uncomment this line to do Soft Particles depth calculation in Orthographic mode */
// #define SOFT_PARTICLES_ORTHOGRAPHIC
/* Change this value if you want to globally scale the HDR effects */
#define GLOBAL_HDR_MULTIPLIER 1
/* Comment this line if you want to disable point lights for lit particles */
#define ENABLE_POINT_LIGHTS
//--------------------------------------------------------------------------------------------------------------------------------

View File

@@ -1,232 +1,232 @@
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
// Copy of URP specific variables needed for lighting
// ================================================================================================================================
// Input.hlsl:
// ================================================================================================================================
#if defined(SHADER_API_MOBILE) || (defined(SHADER_API_GLCORE) && !defined(SHADER_API_SWITCH)) || defined(SHADER_API_GLES) || defined(SHADER_API_GLES3) // Workaround for bug on Nintendo Switch where SHADER_API_GLCORE is mistakenly defined
#define MAX_VISIBLE_LIGHTS 32
#else
#define MAX_VISIBLE_LIGHTS 256
#endif
// --------------------------------
float4 _MainLightPosition;
half4 _MainLightColor;
// --------------------------------
half4 _AdditionalLightsCount;
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
StructuredBuffer<LightData> _AdditionalLightsBuffer;
StructuredBuffer<int> _AdditionalLightsIndices;
#else
// GLES3 causes a performance regression in some devices when using CBUFFER.
#ifndef SHADER_API_GLES3
CBUFFER_START(AdditionalLights)
#endif
float4 _AdditionalLightsPosition[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightsColor[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightsAttenuation[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightsSpotDir[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightsOcclusionProbes[MAX_VISIBLE_LIGHTS];
#ifndef SHADER_API_GLES3
CBUFFER_END
#endif
#endif
// ================================================================================================================================
// UnityInput.hlsl:
// ================================================================================================================================
half4 unity_LightData;
half4 unity_LightIndices[2];
// --------------------------------
// ================================================================================================================================
// Macros.hlsl
// ================================================================================================================================
#define HALF_MIN 6.103515625e-5 // 2^-14, the same value for 10, 11 and 16-bit: https://www.khronos.org/opengl/wiki/Small_Float_Formats
// ================================================================================================================================
// Lighting.hlsl
// ================================================================================================================================
// Abstraction over Light shading data.
struct Light
{
half3 direction;
half3 color;
half distanceAttenuation;
half shadowAttenuation;
};
// Matches Unity Vanila attenuation
// Attenuation smoothly decreases to light range.
float DistanceAttenuation(float distanceSqr, half2 distanceAttenuation)
{
// We use a shared distance attenuation for additional directional and puctual lights
// for directional lights attenuation will be 1
float lightAtten = rcp(distanceSqr);
#if SHADER_HINT_NICE_QUALITY
// Use the smoothing factor also used in the Unity lightmapper.
half factor = distanceSqr * distanceAttenuation.x;
half smoothFactor = saturate(1.0h - factor * factor);
smoothFactor = smoothFactor * smoothFactor;
#else
// We need to smoothly fade attenuation to light range. We start fading linearly at 80% of light range
// Therefore:
// fadeDistance = (0.8 * 0.8 * lightRangeSq)
// smoothFactor = (lightRangeSqr - distanceSqr) / (lightRangeSqr - fadeDistance)
// We can rewrite that to fit a MAD by doing
// distanceSqr * (1.0 / (fadeDistanceSqr - lightRangeSqr)) + (-lightRangeSqr / (fadeDistanceSqr - lightRangeSqr)
// distanceSqr * distanceAttenuation.y + distanceAttenuation.z
half smoothFactor = saturate(distanceSqr * distanceAttenuation.x + distanceAttenuation.y);
#endif
return lightAtten * smoothFactor;
}
half AngleAttenuation(half3 spotDirection, half3 lightDirection, half2 spotAttenuation)
{
// Spot Attenuation with a linear falloff can be defined as
// (SdotL - cosOuterAngle) / (cosInnerAngle - cosOuterAngle)
// This can be rewritten as
// invAngleRange = 1.0 / (cosInnerAngle - cosOuterAngle)
// SdotL * invAngleRange + (-cosOuterAngle * invAngleRange)
// SdotL * spotAttenuation.x + spotAttenuation.y
// If we precompute the terms in a MAD instruction
half SdotL = dot(spotDirection, lightDirection);
half atten = saturate(SdotL * spotAttenuation.x + spotAttenuation.y);
return atten * atten;
}
// Fills a light struct given a perObjectLightIndex
Light GetAdditionalPerObjectLight(int perObjectLightIndex, float3 positionWS)
{
// Abstraction over Light input constants
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
float4 lightPositionWS = _AdditionalLightsBuffer[perObjectLightIndex].position;
half3 color = _AdditionalLightsBuffer[perObjectLightIndex].color.rgb;
half4 distanceAndSpotAttenuation = _AdditionalLightsBuffer[perObjectLightIndex].attenuation;
half4 spotDirection = _AdditionalLightsBuffer[perObjectLightIndex].spotDirection;
half4 lightOcclusionProbeInfo = _AdditionalLightsBuffer[perObjectLightIndex].occlusionProbeChannels;
#else
float4 lightPositionWS = _AdditionalLightsPosition[perObjectLightIndex];
half3 color = _AdditionalLightsColor[perObjectLightIndex].rgb;
half4 distanceAndSpotAttenuation = _AdditionalLightsAttenuation[perObjectLightIndex];
half4 spotDirection = _AdditionalLightsSpotDir[perObjectLightIndex];
half4 lightOcclusionProbeInfo = _AdditionalLightsOcclusionProbes[perObjectLightIndex];
#endif
// Directional lights store direction in lightPosition.xyz and have .w set to 0.0.
// This way the following code will work for both directional and punctual lights.
float3 lightVector = lightPositionWS.xyz - positionWS * lightPositionWS.w;
float distanceSqr = max(dot(lightVector, lightVector), HALF_MIN);
half3 lightDirection = half3(lightVector * rsqrt(distanceSqr));
half attenuation = DistanceAttenuation(distanceSqr, distanceAndSpotAttenuation.xy) * AngleAttenuation(spotDirection.xyz, lightDirection, distanceAndSpotAttenuation.zw);
Light light;
light.direction = lightDirection;
light.distanceAttenuation = attenuation;
/// light.shadowAttenuation = AdditionalLightRealtimeShadow(perObjectLightIndex, positionWS);
light.shadowAttenuation = 1;
light.color = color;
// In case we're using light probes, we can sample the attenuation from the `unity_ProbesOcclusion`
#if defined(LIGHTMAP_ON) || defined(_MIXED_LIGHTING_SUBTRACTIVE)
// First find the probe channel from the light.
// Then sample `unity_ProbesOcclusion` for the baked occlusion.
// If the light is not baked, the channel is -1, and we need to apply no occlusion.
// probeChannel is the index in 'unity_ProbesOcclusion' that holds the proper occlusion value.
int probeChannel = lightOcclusionProbeInfo.x;
// lightProbeContribution is set to 0 if we are indeed using a probe, otherwise set to 1.
half lightProbeContribution = lightOcclusionProbeInfo.y;
half probeOcclusionValue = unity_ProbesOcclusion[probeChannel];
light.distanceAttenuation *= max(probeOcclusionValue, lightProbeContribution);
#endif
return light;
}
uint GetPerObjectLightIndexOffset()
{
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
return unity_LightData.x;
#else
return 0;
#endif
}
// Returns a per-object index given a loop index.
// This abstract the underlying data implementation for storing lights/light indices
int GetPerObjectLightIndex(uint index)
{
/////////////////////////////////////////////////////////////////////////////////////////////
// Structured Buffer Path /
// /
// Lights and light indices are stored in StructuredBuffer. We can just index them. /
// Currently all non-mobile platforms take this path :( /
// There are limitation in mobile GPUs to use SSBO (performance / no vertex shader support) /
/////////////////////////////////////////////////////////////////////////////////////////////
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
uint offset = unity_LightData.x;
return _AdditionalLightsIndices[offset + index];
/////////////////////////////////////////////////////////////////////////////////////////////
// UBO path /
// /
// We store 8 light indices in float4 unity_LightIndices[2]; /
// Due to memory alignment unity doesn't support int[] or float[] /
// Even trying to reinterpret cast the unity_LightIndices to float[] won't work /
// it will cast to float4[] and create extra register pressure. :( /
/////////////////////////////////////////////////////////////////////////////////////////////
#elif !defined(SHADER_API_GLES)
// since index is uint shader compiler will implement
// div & mod as bitfield ops (shift and mask).
// TODO: Can we index a float4? Currently compiler is
// replacing unity_LightIndicesX[i] with a dp4 with identity matrix.
// u_xlat16_40 = dot(unity_LightIndices[int(u_xlatu13)], ImmCB_0_0_0[u_xlati1]);
// This increases both arithmetic and register pressure.
return unity_LightIndices[index / 4][index % 4];
#else
// Fallback to GLES2. No bitfield magic here :(.
// We limit to 4 indices per object and only sample unity_4LightIndices0.
// Conditional moves are branch free even on mali-400
// small arithmetic cost but no extra register pressure from ImmCB_0_0_0 matrix.
half2 lightIndex2 = (index < 2.0h) ? unity_LightIndices[0].xy : unity_LightIndices[0].zw;
half i_rem = (index < 2.0h) ? index : index - 2.0h;
return (i_rem < 1.0h) ? lightIndex2.x : lightIndex2.y;
#endif
}
// Fills a light struct given a loop i index. This will convert the i
// index to a perObjectLightIndex
Light GetAdditionalLight(uint i, float3 positionWS)
{
int perObjectLightIndex = GetPerObjectLightIndex(i);
return GetAdditionalPerObjectLight(perObjectLightIndex, positionWS);
}
int GetAdditionalLightsCount()
{
// TODO: we need to expose in SRP api an ability for the pipeline cap the amount of lights
// in the culling. This way we could do the loop branch with an uniform
// This would be helpful to support baking exceeding lights in SH as well
return min(_AdditionalLightsCount.x, unity_LightData.y);
//--------------------------------------------------------------------------------------------------------------------------------
// Cartoon FX
// (c) 2012-2020 Jean Moreno
//--------------------------------------------------------------------------------------------------------------------------------
// Copy of URP specific variables needed for lighting
// ================================================================================================================================
// Input.hlsl:
// ================================================================================================================================
#if defined(SHADER_API_MOBILE) || (defined(SHADER_API_GLCORE) && !defined(SHADER_API_SWITCH)) || defined(SHADER_API_GLES) || defined(SHADER_API_GLES3) // Workaround for bug on Nintendo Switch where SHADER_API_GLCORE is mistakenly defined
#define MAX_VISIBLE_LIGHTS 32
#else
#define MAX_VISIBLE_LIGHTS 256
#endif
// --------------------------------
float4 _MainLightPosition;
half4 _MainLightColor;
// --------------------------------
half4 _AdditionalLightsCount;
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
StructuredBuffer<LightData> _AdditionalLightsBuffer;
StructuredBuffer<int> _AdditionalLightsIndices;
#else
// GLES3 causes a performance regression in some devices when using CBUFFER.
#ifndef SHADER_API_GLES3
CBUFFER_START(AdditionalLights)
#endif
float4 _AdditionalLightsPosition[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightsColor[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightsAttenuation[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightsSpotDir[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightsOcclusionProbes[MAX_VISIBLE_LIGHTS];
#ifndef SHADER_API_GLES3
CBUFFER_END
#endif
#endif
// ================================================================================================================================
// UnityInput.hlsl:
// ================================================================================================================================
half4 unity_LightData;
half4 unity_LightIndices[2];
// --------------------------------
// ================================================================================================================================
// Macros.hlsl
// ================================================================================================================================
#define HALF_MIN 6.103515625e-5 // 2^-14, the same value for 10, 11 and 16-bit: https://www.khronos.org/opengl/wiki/Small_Float_Formats
// ================================================================================================================================
// Lighting.hlsl
// ================================================================================================================================
// Abstraction over Light shading data.
struct Light
{
half3 direction;
half3 color;
half distanceAttenuation;
half shadowAttenuation;
};
// Matches Unity Vanila attenuation
// Attenuation smoothly decreases to light range.
float DistanceAttenuation(float distanceSqr, half2 distanceAttenuation)
{
// We use a shared distance attenuation for additional directional and puctual lights
// for directional lights attenuation will be 1
float lightAtten = rcp(distanceSqr);
#if SHADER_HINT_NICE_QUALITY
// Use the smoothing factor also used in the Unity lightmapper.
half factor = distanceSqr * distanceAttenuation.x;
half smoothFactor = saturate(1.0h - factor * factor);
smoothFactor = smoothFactor * smoothFactor;
#else
// We need to smoothly fade attenuation to light range. We start fading linearly at 80% of light range
// Therefore:
// fadeDistance = (0.8 * 0.8 * lightRangeSq)
// smoothFactor = (lightRangeSqr - distanceSqr) / (lightRangeSqr - fadeDistance)
// We can rewrite that to fit a MAD by doing
// distanceSqr * (1.0 / (fadeDistanceSqr - lightRangeSqr)) + (-lightRangeSqr / (fadeDistanceSqr - lightRangeSqr)
// distanceSqr * distanceAttenuation.y + distanceAttenuation.z
half smoothFactor = saturate(distanceSqr * distanceAttenuation.x + distanceAttenuation.y);
#endif
return lightAtten * smoothFactor;
}
half AngleAttenuation(half3 spotDirection, half3 lightDirection, half2 spotAttenuation)
{
// Spot Attenuation with a linear falloff can be defined as
// (SdotL - cosOuterAngle) / (cosInnerAngle - cosOuterAngle)
// This can be rewritten as
// invAngleRange = 1.0 / (cosInnerAngle - cosOuterAngle)
// SdotL * invAngleRange + (-cosOuterAngle * invAngleRange)
// SdotL * spotAttenuation.x + spotAttenuation.y
// If we precompute the terms in a MAD instruction
half SdotL = dot(spotDirection, lightDirection);
half atten = saturate(SdotL * spotAttenuation.x + spotAttenuation.y);
return atten * atten;
}
// Fills a light struct given a perObjectLightIndex
Light GetAdditionalPerObjectLight(int perObjectLightIndex, float3 positionWS)
{
// Abstraction over Light input constants
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
float4 lightPositionWS = _AdditionalLightsBuffer[perObjectLightIndex].position;
half3 color = _AdditionalLightsBuffer[perObjectLightIndex].color.rgb;
half4 distanceAndSpotAttenuation = _AdditionalLightsBuffer[perObjectLightIndex].attenuation;
half4 spotDirection = _AdditionalLightsBuffer[perObjectLightIndex].spotDirection;
half4 lightOcclusionProbeInfo = _AdditionalLightsBuffer[perObjectLightIndex].occlusionProbeChannels;
#else
float4 lightPositionWS = _AdditionalLightsPosition[perObjectLightIndex];
half3 color = _AdditionalLightsColor[perObjectLightIndex].rgb;
half4 distanceAndSpotAttenuation = _AdditionalLightsAttenuation[perObjectLightIndex];
half4 spotDirection = _AdditionalLightsSpotDir[perObjectLightIndex];
half4 lightOcclusionProbeInfo = _AdditionalLightsOcclusionProbes[perObjectLightIndex];
#endif
// Directional lights store direction in lightPosition.xyz and have .w set to 0.0.
// This way the following code will work for both directional and punctual lights.
float3 lightVector = lightPositionWS.xyz - positionWS * lightPositionWS.w;
float distanceSqr = max(dot(lightVector, lightVector), HALF_MIN);
half3 lightDirection = half3(lightVector * rsqrt(distanceSqr));
half attenuation = DistanceAttenuation(distanceSqr, distanceAndSpotAttenuation.xy) * AngleAttenuation(spotDirection.xyz, lightDirection, distanceAndSpotAttenuation.zw);
Light light;
light.direction = lightDirection;
light.distanceAttenuation = attenuation;
/// light.shadowAttenuation = AdditionalLightRealtimeShadow(perObjectLightIndex, positionWS);
light.shadowAttenuation = 1;
light.color = color;
// In case we're using light probes, we can sample the attenuation from the `unity_ProbesOcclusion`
#if defined(LIGHTMAP_ON) || defined(_MIXED_LIGHTING_SUBTRACTIVE)
// First find the probe channel from the light.
// Then sample `unity_ProbesOcclusion` for the baked occlusion.
// If the light is not baked, the channel is -1, and we need to apply no occlusion.
// probeChannel is the index in 'unity_ProbesOcclusion' that holds the proper occlusion value.
int probeChannel = lightOcclusionProbeInfo.x;
// lightProbeContribution is set to 0 if we are indeed using a probe, otherwise set to 1.
half lightProbeContribution = lightOcclusionProbeInfo.y;
half probeOcclusionValue = unity_ProbesOcclusion[probeChannel];
light.distanceAttenuation *= max(probeOcclusionValue, lightProbeContribution);
#endif
return light;
}
uint GetPerObjectLightIndexOffset()
{
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
return unity_LightData.x;
#else
return 0;
#endif
}
// Returns a per-object index given a loop index.
// This abstract the underlying data implementation for storing lights/light indices
int GetPerObjectLightIndex(uint index)
{
/////////////////////////////////////////////////////////////////////////////////////////////
// Structured Buffer Path /
// /
// Lights and light indices are stored in StructuredBuffer. We can just index them. /
// Currently all non-mobile platforms take this path :( /
// There are limitation in mobile GPUs to use SSBO (performance / no vertex shader support) /
/////////////////////////////////////////////////////////////////////////////////////////////
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
uint offset = unity_LightData.x;
return _AdditionalLightsIndices[offset + index];
/////////////////////////////////////////////////////////////////////////////////////////////
// UBO path /
// /
// We store 8 light indices in float4 unity_LightIndices[2]; /
// Due to memory alignment unity doesn't support int[] or float[] /
// Even trying to reinterpret cast the unity_LightIndices to float[] won't work /
// it will cast to float4[] and create extra register pressure. :( /
/////////////////////////////////////////////////////////////////////////////////////////////
#elif !defined(SHADER_API_GLES)
// since index is uint shader compiler will implement
// div & mod as bitfield ops (shift and mask).
// TODO: Can we index a float4? Currently compiler is
// replacing unity_LightIndicesX[i] with a dp4 with identity matrix.
// u_xlat16_40 = dot(unity_LightIndices[int(u_xlatu13)], ImmCB_0_0_0[u_xlati1]);
// This increases both arithmetic and register pressure.
return unity_LightIndices[index / 4][index % 4];
#else
// Fallback to GLES2. No bitfield magic here :(.
// We limit to 4 indices per object and only sample unity_4LightIndices0.
// Conditional moves are branch free even on mali-400
// small arithmetic cost but no extra register pressure from ImmCB_0_0_0 matrix.
half2 lightIndex2 = (index < 2.0h) ? unity_LightIndices[0].xy : unity_LightIndices[0].zw;
half i_rem = (index < 2.0h) ? index : index - 2.0h;
return (i_rem < 1.0h) ? lightIndex2.x : lightIndex2.y;
#endif
}
// Fills a light struct given a loop i index. This will convert the i
// index to a perObjectLightIndex
Light GetAdditionalLight(uint i, float3 positionWS)
{
int perObjectLightIndex = GetPerObjectLightIndex(i);
return GetAdditionalPerObjectLight(perObjectLightIndex, positionWS);
}
int GetAdditionalLightsCount()
{
// TODO: we need to expose in SRP api an ability for the pipeline cap the amount of lights
// in the culling. This way we could do the loop branch with an uniform
// This would be helpful to support baking exceeding lights in SH as well
return min(_AdditionalLightsCount.x, unity_LightData.y);
}