Boat Attack使用了Universal RP的许多新图形功能,可以用于探索 Universal RP 的使用方式和技巧。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

204 行
7.5 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor.ShaderGraph.Drawing;
using UnityEngine;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.ShaderGraph
{
static class BuiltinKeyword
{
[BuiltinKeyword]
public static KeywordDescriptor QualityKeyword()
{
return new KeywordDescriptor()
{
displayName = "Material Quality",
referenceName = "MATERIAL_QUALITY",
type = KeywordType.Enum,
definition = KeywordDefinition.ShaderFeature,
scope = KeywordScope.Global,
value = 0,
entries = new KeywordEntry[]
{
new KeywordEntry("High", "HIGH"),
new KeywordEntry("Medium", "MEDIUM"),
new KeywordEntry("Low", "LOW"),
},
};
}
}
static class KeywordUtil
{
public static IEnumerable<KeywordDescriptor> GetBuiltinKeywordDescriptors() =>
TypeCache.GetMethodsWithAttribute<BuiltinKeywordAttribute>()
.Where(method => method.IsStatic && method.ReturnType == typeof(KeywordDescriptor))
.Select(method =>
(KeywordDescriptor) method.Invoke(null, new object[0] { }));
public static ConcreteSlotValueType ToConcreteSlotValueType(this KeywordType keywordType)
{
switch(keywordType)
{
case KeywordType.Boolean:
return ConcreteSlotValueType.Boolean;
case KeywordType.Enum:
return ConcreteSlotValueType.Vector1;
default:
throw new ArgumentOutOfRangeException();
}
}
public static string ToDeclarationString(this KeywordDefinition keywordDefinition)
{
switch(keywordDefinition)
{
case KeywordDefinition.MultiCompile:
return "multi_compile";
case KeywordDefinition.ShaderFeature:
return "shader_feature";
default:
return string.Empty;
}
}
public static string ToDeclarationString(this KeywordDescriptor keyword)
{
// Get definition type using scope
string scopeString = keyword.scope == KeywordScope.Local ? "_local" : string.Empty;
string definitionString = $"{keyword.definition.ToDeclarationString()}{scopeString}";
switch(keyword.type)
{
case KeywordType.Boolean:
return $"#pragma {definitionString} _ {keyword.referenceName}";
case KeywordType.Enum:
var enumEntryDefinitions = keyword.entries.Select(x => $"{keyword.referenceName}_{x.referenceName}");
string enumEntriesString = string.Join(" ", enumEntryDefinitions);
return $"#pragma {definitionString} {enumEntriesString}";
default:
throw new ArgumentOutOfRangeException();
}
}
public static int GetKeywordPermutationCount(this GraphData graph)
{
// Gather all unique keywords from the Graph including Sub Graphs
IEnumerable<ShaderKeyword> allKeywords = graph.keywords;
var subGraphNodes = graph.GetNodes<SubGraphNode>();
foreach(SubGraphNode subGraphNode in subGraphNodes)
{
allKeywords = allKeywords.Union(subGraphNode.asset.keywords);
}
allKeywords = allKeywords.Distinct();
// Get permutation count for all Keywords
int permutationCount = 1;
foreach(ShaderKeyword keyword in allKeywords)
{
if(keyword.keywordType == KeywordType.Boolean)
permutationCount *= 2;
else
permutationCount *= keyword.entries.Count;
}
return permutationCount;
}
public static string GetKeywordPermutationSetConditional(List<int> permutationSet)
{
StringBuilder sb = new StringBuilder();
sb.Append("#if ");
for(int i = 0; i < permutationSet.Count; i++)
{
// Subsequent permutation predicates require ||
if(i != 0)
sb.Append(" || ");
// Append permutation
sb.Append($"defined(KEYWORD_PERMUTATION_{permutationSet[i]})");
}
return sb.ToString();
}
public static void GetKeywordPermutationDeclarations(ShaderStringBuilder sb, List<List<KeyValuePair<ShaderKeyword, int>>> permutations)
{
if (permutations.Count == 0)
return;
for(int p = 0; p < permutations.Count; p++)
{
// ShaderStringBuilder.Append doesnt apply indentation
sb.AppendIndentation();
// Append correct if
bool isLast = false;
if(p == 0)
{
sb.Append("#if ");
}
else if(p == permutations.Count - 1)
{
sb.Append("#else");
isLast = true;
}
else
{
sb.Append("#elif ");
}
// Last permutation is always #else
if(!isLast)
{
// Track whether && is required
bool appendAnd = false;
// Iterate all keywords that are part of the permutation
for(int i = 0; i < permutations[p].Count; i++)
{
// When previous keyword was inserted subsequent requires &&
string and = appendAnd ? " && " : string.Empty;
switch(permutations[p][i].Key.keywordType)
{
case KeywordType.Enum:
{
sb.Append($"{and}defined({permutations[p][i].Key.referenceName}_{permutations[p][i].Key.entries[permutations[p][i].Value].referenceName})");
appendAnd = true;
break;
}
case KeywordType.Boolean:
{
// HLSL does not support a !value predicate
if(permutations[p][i].Value != 0)
{
continue;
}
sb.Append($"{and}defined({permutations[p][i].Key.referenceName})");
appendAnd = true;
break;
}
default:
throw new ArgumentOutOfRangeException();
}
}
}
sb.AppendNewLine();
// Define the matching permutation keyword
sb.IncreaseIndent();
sb.AppendLine($"#define KEYWORD_PERMUTATION_{p}");
sb.DecreaseIndent();
}
// End statement
sb.AppendLine("#endif");
}
}
}