This commit is contained in:
SoulliesOfficial
2026-07-17 17:46:16 -04:00
parent b00ac27e3a
commit 40fa80cd70
1178 changed files with 51090 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
using System.Collections.Generic;
namespace NBShader
{
/// <summary>
/// Hard-coded catalog of raw shader feature keywords managed by the NBShader runtime tier system.
/// Keywords not listed here are never changed by <see cref="NBShaderFeatureRuntime"/>.
/// </summary>
public static class NBShaderFeatureCatalog
{
/// <summary>
/// Shader name used by NBShader materials.
/// </summary>
public const string ShaderName = "Effects/NBShader";
/// <summary>
/// Default file name for optional NBShader runtime settings assets.
/// User projects decide how those assets are loaded at runtime.
/// </summary>
public const string RuntimeSettingsAssetName = "NBShaderFeatureRuntimeSettings";
/// <summary>
/// Raw shader_feature keywords currently managed by NBShader tiering. The '_' placeholder and
/// multi_compile keywords are intentionally excluded.
/// </summary>
public static readonly string[] RawKeywords =
{
"NB_DEBUG_DISSOLVE",
"NB_DEBUG_DISTORT",
"NB_DEBUG_FRESNEL",
"NB_DEBUG_MASK",
"NB_DEBUG_PNOISE",
"NB_DEBUG_VERTEX_OFFSET",
"VFX_SIX_WAY_ABSORPTION",
"_ALPHAMODULATE_ON",
"_ALPHAPREMULTIPLY_ON",
"_ALPHATEST_ON",
"_CHROMATIC_ABERRATION",
"_COLORMAPBLEND",
"_COLOR_RAMP",
"_COLOR_RAMP_MAP",
"_DEPTH_DECAL",
"_DEPTH_OUTLINE",
"_DISSOLVE",
"_DISSOLVE_MASK",
"_DISSOLVE_RAMP",
"_DISSOLVE_RAMP_MAP",
"_DISTANCE_FADE",
"_DISTORT_REFRACTION",
"_EMISSION",
"_FLIPBOOKBLENDING_ON",
"_FRESNEL",
"_FX_LIGHT_MODE_BLINN_PHONG",
"_FX_LIGHT_MODE_HALF_LAMBERT",
"_FX_LIGHT_MODE_PBR",
"_FX_LIGHT_MODE_SIX_WAY",
"_FX_LIGHT_MODE_UNLIT",
"_HOUDINI_VAT_DYNAMIC_REMESH",
"_HOUDINI_VAT_PARTICLE_SPRITE",
"_HOUDINI_VAT_RIGIDBODY",
"_HOUDINI_VAT_SOFTBODY",
"_MASKMAP_ON",
"_MASKMAP2_ON",
"_MASKMAP3_ON",
"_MATCAP",
"_NOISEMAP",
"_NOISE_MASKMAP",
"_NORMALMAP",
"_OVERRIDE_Z",
"_PARALLAX_MAPPING",
"_PARCUSTOMDATA_ON",
"_PROGRAM_NOISE",
"_PROGRAM_NOISE_SIMPLE",
"_PROGRAM_NOISE_VORONOI",
"_SCREEN_DISTORT_MODE",
"_SCRIPTABLETIME",
"_SHARED_UV",
"_SOFTPARTICLES_ON",
"_SPECULAR_COLOR",
"_STENCIL_WITHOUT_PLAYER",
"_TYFLOW_VAT_ABSOLUTE",
"_TYFLOW_VAT_RELATIVE",
"_TYFLOW_VAT_SKIN_PR",
"_TYFLOW_VAT_SKIN_PRSAVE",
"_TYFLOW_VAT_SKIN_PRSXYZ",
"_TYFLOW_VAT_SKIN_R",
"_UNSCALETIME",
"_VAT",
"_VAT_HOUDINI",
"_VAT_TYFLOW",
"_VERTEX_OFFSET",
"_VERTEX_OFFSET_MASKMAP"
};
internal static readonly HashSet<string> RawKeywordSet = new HashSet<string>(RawKeywords);
/// <summary>
/// Returns true when the keyword is explicitly managed by the NBShader feature tier system.
/// Catalog-external keywords must be ignored by tier application and build stripping.
/// </summary>
public static bool IsManagedKeyword(string keyword)
{
return !string.IsNullOrEmpty(keyword) && RawKeywordSet.Contains(keyword);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: faf1ed0560444790b66010208bd2934f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,183 @@
using System.Collections.Generic;
using UnityEngine;
namespace NBShader
{
/// <summary>
/// Runtime API for applying NBShader feature tiers to materials.
/// </summary>
public static class NBShaderFeatureRuntime
{
/// <summary>
/// Applies an NBShader feature tier to one material in place. Only materials whose shader name is
/// "Effects/NBShader" are processed. Managed Catalog keywords and shader passes are derived from
/// serialized material intent, then filtered by the target tier.
/// </summary>
/// <param name="material">Material to process. Null materials are ignored.</param>
/// <param name="tier">
/// Target tier. When null, Ultra is used. This overload does not load runtime settings, so it keeps all
/// managed Catalog keywords and pass features available.
/// </param>
/// <remarks>
/// If lower-tier shader variants have been stripped from the build, call this API before the material is
/// used for rendering. Otherwise Unity can request a missing variant and select a similar available variant.
/// </remarks>
public static void ApplyTier(Material material, NBShaderFeatureTier? tier = null)
{
ApplyTierInternal(material, null, tier);
}
/// <summary>
/// Applies an NBShader feature tier using a user-loaded runtime settings asset.
/// Pass null for <paramref name="tier"/> to resolve the tier from the settings quality mapping.
/// </summary>
public static void ApplyTier(Material material, NBShaderFeatureRuntimeSettings settings, NBShaderFeatureTier? tier)
{
ApplyTierInternal(material, settings, tier);
}
/// <summary>
/// Applies an NBShader feature tier to multiple materials in place. Only materials whose shader name is
/// "Effects/NBShader" are processed. Catalog-external keywords are left unchanged unless they are
/// explicitly tied to a managed NBShader feature.
/// </summary>
/// <param name="materials">Materials to process. Null collections and null entries are ignored.</param>
/// <param name="tier">
/// Target tier. When null, Ultra is used. This overload does not load runtime settings, so it keeps all
/// managed Catalog keywords and pass features available.
/// </param>
/// <remarks>
/// If lower-tier shader variants have been stripped from the build, call this API before the materials are
/// used for rendering. Otherwise Unity can request a missing variant and select a similar available variant.
/// </remarks>
public static void ApplyTier(IEnumerable<Material> materials, NBShaderFeatureTier? tier = null)
{
ApplyTierInternal(materials, null, tier);
}
/// <summary>
/// Applies an NBShader feature tier to multiple materials using a user-loaded runtime settings asset.
/// Pass null for <paramref name="tier"/> to resolve the tier from the settings quality mapping.
/// </summary>
public static void ApplyTier(IEnumerable<Material> materials, NBShaderFeatureRuntimeSettings settings, NBShaderFeatureTier? tier)
{
ApplyTierInternal(materials, settings, tier);
}
private static void ApplyTierInternal(IEnumerable<Material> materials, NBShaderFeatureRuntimeSettings settings, NBShaderFeatureTier? tier)
{
if (materials == null)
{
return;
}
foreach (Material material in materials)
{
ApplyTierInternal(material, settings, tier);
}
}
private static void ApplyTierInternal(Material material, NBShaderFeatureRuntimeSettings settings, NBShaderFeatureTier? tier)
{
if (!IsNBShaderMaterial(material))
{
return;
}
NBShaderFeatureTier resolvedTier = tier.HasValue ? tier.Value : ResolveTierFromQuality(settings);
HashSet<string> allowed = settings != null
? settings.BuildAllowedSet(resolvedTier)
: BuildAllowAllCatalogKeywordSet();
HashSet<string> allowedPassFeatures = settings != null
? settings.BuildAllowedPassFeatureSet(resolvedTier)
: null;
NBShaderMaterialIntentResult result = NBShaderMaterialIntentResolver.Resolve(material, resolvedTier, allowed, allowedPassFeatures);
ApplyResolvedIntent(material, result);
}
private static bool IsNBShaderMaterial(Material material)
{
return material != null
&& material.shader != null
&& material.shader.name == NBShaderFeatureCatalog.ShaderName;
}
private static void ApplyResolvedIntent(Material material, NBShaderMaterialIntentResult result)
{
if (material == null || result == null)
{
return;
}
var effectiveKeywords = new HashSet<string>(result.effectiveKeywords);
for (int i = 0; i < NBShaderFeatureCatalog.RawKeywords.Length; i++)
{
string keyword = NBShaderFeatureCatalog.RawKeywords[i];
bool shouldEnable = effectiveKeywords.Contains(keyword);
if (material.IsKeywordEnabled(keyword) != shouldEnable)
{
if (shouldEnable)
{
material.EnableKeyword(keyword);
}
else
{
material.DisableKeyword(keyword);
}
}
}
bool evaluateShVertex = effectiveKeywords.Contains("_FX_LIGHT_MODE_SIX_WAY");
if (material.IsKeywordEnabled("EVALUATE_SH_VERTEX") != evaluateShVertex)
{
if (evaluateShVertex)
{
material.EnableKeyword("EVALUATE_SH_VERTEX");
}
else
{
material.DisableKeyword("EVALUATE_SH_VERTEX");
}
}
for (int i = 0; i < result.passes.Length; i++)
{
NBShaderPassIntent pass = result.passes[i];
if (!string.IsNullOrEmpty(pass.passName) &&
material.GetShaderPassEnabled(pass.passName) != pass.included)
{
material.SetShaderPassEnabled(pass.passName, pass.included);
}
}
}
private static NBShaderFeatureTier ResolveTierFromQuality(NBShaderFeatureRuntimeSettings settings)
{
if (settings == null)
{
return NBShaderFeatureTier.Ultra;
}
string qualityName = GetCurrentQualityName();
NBShaderFeatureTier tier;
return settings.TryGetTierForQualityName(qualityName, out tier) ? tier : NBShaderFeatureTier.Ultra;
}
private static string GetCurrentQualityName()
{
string[] names = QualitySettings.names;
int index = QualitySettings.GetQualityLevel();
if (names != null && index >= 0 && index < names.Length)
{
return names[index];
}
return string.Empty;
}
private static HashSet<string> BuildAllowAllCatalogKeywordSet()
{
return new HashSet<string>(NBShaderFeatureCatalog.RawKeywords);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b6115ddf8278414a953d467dc43f637c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace NBShader
{
/// <summary>
/// Optional runtime settings for NBShader feature tiering. User projects own asset creation and
/// runtime loading; pass the loaded asset to <see cref="NBShaderFeatureRuntime"/> when tier gating is required.
/// </summary>
[CreateAssetMenu(fileName = NBShaderFeatureCatalog.RuntimeSettingsAssetName, menuName = "NBShader/Feature Runtime Settings")]
public sealed class NBShaderFeatureRuntimeSettings : ScriptableObject
{
[Serializable]
public sealed class QualityTierMapping
{
public string qualityName;
public NBShaderFeatureTier tier = NBShaderFeatureTier.Ultra;
}
[Header("Allowed Raw Shader Feature Keywords")]
public string[] lowAllowedKeywords = CloneCatalogKeywords();
public string[] mediumAllowedKeywords = CloneCatalogKeywords();
public string[] highAllowedKeywords = CloneCatalogKeywords();
public string[] ultraAllowedKeywords = CloneCatalogKeywords();
[Header("Allowed Shader Pass Features")]
public string[] lowAllowedPassFeatures = CloneCatalogPassFeatures();
public string[] mediumAllowedPassFeatures = CloneCatalogPassFeatures();
public string[] highAllowedPassFeatures = CloneCatalogPassFeatures();
public string[] ultraAllowedPassFeatures = CloneCatalogPassFeatures();
[Header("QualitySettings Name To Tier")]
public QualityTierMapping[] qualityTierMappings = new QualityTierMapping[0];
public string[] GetAllowedKeywords(NBShaderFeatureTier tier)
{
switch (tier)
{
case NBShaderFeatureTier.Low:
return lowAllowedKeywords ?? NBShaderFeatureCatalog.RawKeywords;
case NBShaderFeatureTier.Medium:
return mediumAllowedKeywords ?? NBShaderFeatureCatalog.RawKeywords;
case NBShaderFeatureTier.High:
return highAllowedKeywords ?? NBShaderFeatureCatalog.RawKeywords;
default:
return ultraAllowedKeywords ?? NBShaderFeatureCatalog.RawKeywords;
}
}
public string[] GetAllowedPassFeatures(NBShaderFeatureTier tier)
{
switch (tier)
{
case NBShaderFeatureTier.Low:
return lowAllowedPassFeatures ?? NBShaderPassFeatureCatalog.RawPassFeatureIds;
case NBShaderFeatureTier.Medium:
return mediumAllowedPassFeatures ?? NBShaderPassFeatureCatalog.RawPassFeatureIds;
case NBShaderFeatureTier.High:
return highAllowedPassFeatures ?? NBShaderPassFeatureCatalog.RawPassFeatureIds;
default:
return ultraAllowedPassFeatures ?? NBShaderPassFeatureCatalog.RawPassFeatureIds;
}
}
public bool TryGetTierForQualityName(string qualityName, out NBShaderFeatureTier tier)
{
tier = NBShaderFeatureTier.Ultra;
if (string.IsNullOrEmpty(qualityName) || qualityTierMappings == null)
{
return false;
}
for (int i = 0; i < qualityTierMappings.Length; i++)
{
QualityTierMapping mapping = qualityTierMappings[i];
if (mapping != null && string.Equals(mapping.qualityName, qualityName, StringComparison.OrdinalIgnoreCase))
{
tier = mapping.tier;
return true;
}
}
return false;
}
internal HashSet<string> BuildAllowedSet(NBShaderFeatureTier tier)
{
string[] keywords = GetAllowedKeywords(tier);
HashSet<string> allowed = new HashSet<string>();
for (int i = 0; i < keywords.Length; i++)
{
string keyword = keywords[i];
if (NBShaderFeatureCatalog.IsManagedKeyword(keyword))
{
allowed.Add(keyword);
}
}
return allowed;
}
internal HashSet<string> BuildAllowedPassFeatureSet(NBShaderFeatureTier tier)
{
string[] passFeatures = GetAllowedPassFeatures(tier);
HashSet<string> allowed = new HashSet<string>();
for (int i = 0; i < passFeatures.Length; i++)
{
string passFeature = passFeatures[i];
if (NBShaderPassFeatureCatalog.IsManagedPassFeature(passFeature))
{
allowed.Add(passFeature);
}
}
return allowed;
}
private static string[] CloneCatalogKeywords()
{
return (string[])NBShaderFeatureCatalog.RawKeywords.Clone();
}
private static string[] CloneCatalogPassFeatures()
{
return (string[])NBShaderPassFeatureCatalog.RawPassFeatureIds.Clone();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c77ae8665b4443efa5ab2f470a2939b6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,13 @@
namespace NBShader
{
/// <summary>
/// Runtime NBShader feature tiers, ordered from the smallest keyword budget to the full feature set.
/// </summary>
public enum NBShaderFeatureTier
{
Low = 0,
Medium = 1,
High = 2,
Ultra = 3
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0ad18474c2a04675834e005ab993b7c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,773 @@
using UnityEngine;
namespace NBShader
{
public class NBShaderFlags : ShaderFlagsBase
{
public const string FlagsName = "_W9ParticleShaderFlags";
public static int FlagsId = Shader.PropertyToID(FlagsName);
public const string Flags1Name = "_W9ParticleShaderFlags1";
public static int Flags1Id = Shader.PropertyToID(Flags1Name);
public const string WrapFlagsName = "_W9ParticleShaderWrapFlags";
public static int WrapFlagsId = Shader.PropertyToID(WrapFlagsName);
public const string foldOutFlagName = "_NBShaderGUIFoldToggle";
public static int foldOutFlagId = Shader.PropertyToID(foldOutFlagName);
public const string foldOutFlagName1 = "_NBShaderGUIFoldToggle1";
public static int foldOutFlagId1 = Shader.PropertyToID(foldOutFlagName1);
public const string foldOutFlagName2 = "_NBShaderGUIFoldToggle2";
public static int foldOutFlagId2 = Shader.PropertyToID(foldOutFlagName2);
public const string colorChannelFlagName = "_W9ParticleShaderColorChannelFlag";
public static int colorChannelFlagId = Shader.PropertyToID(colorChannelFlagName);
public const string pNoiseBlendFlagName = "_W9ParticleShaderPNoiseBlendFlag";
public static int pNoiseBlendFlagId = Shader.PropertyToID(pNoiseBlendFlagName);
// public const string WrapFlags2Name = "_W9ParticleShaderWrapFlags2";
// public static int WrapFlags2Id = Shader.PropertyToID(WrapFlags2Name);
public override int GetShaderFlagsId(int index = 0)
{
switch (index)
{
case 0:
return FlagsId;
case 1:
return Flags1Id;
case 2:
return WrapFlagsId;
//FoldOut必须要紧挨着因为按照Index去拿AnimBool
case 3:
return foldOutFlagId;
case 4:
return foldOutFlagId1;
case 5:
return foldOutFlagId2;
case 6:
return colorChannelFlagId;
case 7:
return pNoiseBlendFlagId;
// case 8:
// return WrapFlags2Id;
default:
return FlagsId;
}
}
protected override string GetShaderFlagsName(int index = 0)
{
switch (index)
{
case 0:
return FlagsName;
case 1:
return Flags1Name;
case 2:
return WrapFlagsName;
case 3:
return foldOutFlagName;
case 4:
return foldOutFlagName1;
case 5:
return colorChannelFlagName;
default:
return FlagsName;
}
}
public NBShaderFlags(Material material = null) : base(material)
{
}
public const int FLAG_BIT_SATURABILITY_ON = 1 << 0;
public const int FLAG_BIT_PARTICLE_NOISE_CHORATICABERRAT_WITH_NOISE = 1 << 1;
public const int FLAG_BIT_PARTICLE_FRESNEL_FADE_ON = 1 << 2;
public const int FLAG_BIT_PARTICLE_FRESNEL_COLOR_ON = 1 << 3;
public const int FLAG_BIT_PARTICLE_USETEXCOORD2 = 1 << 4;
// public const int FLAG_BIT_PARTICLE_DISTANCEFADE_ON = 1 << 5; // Obsolete/reserved: keyword-driven (_DISTANCE_FADE).
// public const int FLAG_BIT_PARTICLE_CHORATICABERRAT = 1 << 6; // Obsolete/reserved: keyword-driven (_CHROMATIC_ABERRATION).
public const int FLAG_BIT_PARTILCE_MASKMAPROTATIONANIMATION_ON = 1 << 7;
public const int FLAG_BIT_PARTICLE_POLARCOORDINATES_ON = 1 << 8;
public const int FLAG_BIT_PARTICLE_UTWIRL_ON = 1 << 9;
public const int FLAG_BIT_PARTICLE_LINEARTOGAMMA_ON = 1 << 10;
// public const int FLAG_BIT_PARTICLE_FRESNEL_ON = 1 << 11; // Obsolete/reserved: keyword-driven (_FRESNEL).
public const int FLAG_BIT_PARTICLE_NOISEMAP_NORMALIZEED_ON = 1 << 12;
public const int FLAG_BIT_PARTICLE_FRESNEL_COLOR_AFFETCT_BY_ALPHA = 1 << 13;
public const int FLAG_BIT_PARTICLE_UIEFFECT_ON = 1 << 14;
public const int FLAG_BIT_PARTICLE_UNSCALETIME_ON = 1 << 15;
public const int FLAG_BIT_PARTICLE_SCRIPTABLETIME_ON = 1 << 16;
public const int FLAG_BIT_PARTICLE_CUSTOMDATA1_ON = 1 << 17;
public const int FLAG_BIT_PARTICLE_FRESNEL_INVERT_ON = 1 << 18;
public const int FLAG_BIT_HUESHIFT_ON = 1 << 19;
public const int FLAG_BIT_PARTICLE_CUSTOMDATA2_ON = 1 << 20;
public const int FLAG_BIT_PARTICLE_NORMALMAP_MASK_MODE = 1 << 21;
public const int FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX = 1 << 22;
// public const int FLAG_BIT_PARTICLE_RAMP_COLOR_MAP_MODE_ON = 1 << 23; // Obsolete/reserved: keyword-driven (_COLOR_RAMP_MAP).
public const int FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD = 1 << 24;
public const int FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE = 1 << 25;
// public const int FLAG_BIT_PARTICLE_DISSOLVE_RAMP_MAP = 1 << 26; // Obsolete/reserved: keyword-driven (_DISSOLVE_RAMP_MAP).
// public const int FLAG_BIT_PARTICLE_DISSOLVE_MASK = 1 << 27; // Obsolete/reserved: keyword-driven (_DISSOLVE_MASK).
public const int FLAG_BIT_PARTICLE_BACKCOLOR = 1 << 28;
public const int FLAG_BIT_PARTICLE_COLOR_MULTI_ALPHA = 1 << 29;
// public const int FLAG_BIT_PARTICLE_VERTEX_OFFSET_ON = 1 << 30; // Obsolete/reserved: keyword-driven (_VERTEX_OFFSET).
public const int FLAG_BIT_PARTICLE_VERTEX_OFFSET_NORMAL_DIR = 1 << 31;
public const int FLAG_BIT_PARTICLE_1_TRANSPARENT_MODE = 1 << 0;
public const int FLAG_BIT_PARTICLE_1_TRANSPARENT_SHADOW_DITHER = 1 << 1;
public const int FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT = 1 << 2;
public const int FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT = 1 << 3;
public const int FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT = 1 << 4;
public const int FLAG_BIT_PARTICLE_1_DISSOLVE_LINE_MASK = 1 << 5;
public const int FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY = 1 << 6;
public const int FLAG_BIT_PARTICLE_1_MASK_REFINE = 1 << 7;
public const int FLAG_BIT_PARTICLE_1_SCREEN_DISTORT_ALPHA_REFINE = 1 << 8;
public const int FLAG_BIT_PARTICLE_1_IGNORE_VERTEX_COLOR = 1 << 9;
// public const int FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_SIMPLE = 1 << 10; // Obsolete/reserved: keyword-driven (_PROGRAM_NOISE_SIMPLE).
// public const int FLAG_BIT_PARTICLE_1_DISSOVLE_USE_RAMP = 1 << 11; // Obsolete/reserved: keyword-driven (_DISSOLVE_RAMP).
// public const int FLAG_BIT_PARTICLE_1_MASK_MAP2 = 1 << 12; // Obsolete/reserved: keyword-driven (_MASKMAP2_ON).
// public const int FLAG_BIT_PARTICLE_1_MASK_MAP3 = 1 << 13; // Obsolete/reserved: keyword-driven (_MASKMAP3_ON).
// public const int FLAG_BIT_PARTICLE_1_NOISE_MASKMAP = 1 << 14; // Obsolete/reserved: keyword-driven (_NOISE_MASKMAP).
public const int FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER = 1 << 15;
// public const int FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_VORONOI = 1 << 16; // Obsolete/reserved: keyword-driven (_PROGRAM_NOISE_VORONOI).
public const int FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE = 1 << 17;
public const int FLAG_BIT_PARTICLE_1_USE_TEXCOORD1 = 1 << 18;
public const int FLAG_BIT_PARTICLE_1_USE_TEXCOORD2 = 1 << 19;
public const int FLAG_BIT_PARTICLE_1_CYLINDER_CORDINATE = 1 << 20;
public const int FLAG_BIT_PARTICLE_1_UV_FROM_MESH = 1 << 21; //3D条件下如果不是来源于Mesh就默认来源于粒子。
public const int FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE = 1 << 22; //3D条件下如果不是来源于Mesh就默认来源于粒子。
public const int FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM = 1 << 23; //3D条件下如果不是来源于Mesh就默认来源于粒子。
public const int FLAG_BIT_PARTICLE_1_MAINTEX_CONTRAST = 1 << 24;
public const int FLAG_BIT_PARTICLE_1_VERTEXOFFSET_START_FROM_ZERO = 1 << 25;
// public const int FLAG_BIT_PARTICLE_1_VERTEXOFFSET_MASKMAP = 1 << 26; // Obsolete/reserved: keyword-driven (_VERTEX_OFFSET_MASKMAP).
public const int FLAG_BIT_PARTICLE_1_MAINTEX_COLOR_REFINE = 1 << 27;
public const int FLAG_BIT_PARTICLE_1_BUMP_TEX_UV_FOLLOW_MAINTEX = 1 << 28;
public const int FLAG_BIT_PARTICLE_1_SIXWAY_RAMPMAP = 1 << 29;
public const int FLAG_BIT_PARTICLE_1_MATCAP_MULTY_MODE = 1 << 30;
public const int FLAG_BIT_WRAPMODE_BASEMAP = 1 << 0;
public const int FLAG_BIT_WRAPMODE_MASKMAP = 1 << 1;
public const int FLAG_BIT_WRAPMODE_MASKMAP2 = 1 << 2;
public const int FLAG_BIT_WRAPMODE_NOISEMAP = 1 << 3;
public const int FLAG_BIT_WRAPMODE_EMISSIONMAP = 1 << 4;
public const int FLAG_BIT_WRAPMODE_DISSOLVE_MAP = 1 << 5;
public const int FLAG_BIT_WRAPMODE_DISSOLVE_MASKMAP = 1 << 6;
public const int FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP = 1 << 7;
public const int FLAG_BIT_WRAPMODE_COLORBLENDMAP = 1 << 8;
public const int FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP = 1 << 9;
public const int FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP = 1 << 10;
public const int FLAG_BIT_WRAPMODE_MASKMAP3 = 1 << 11;
public const int FLAG_BIT_WRAPMODE_NOISE_MASKMAP = 1 << 12;
public const int FLAG_BIT_WRAPMODE_VERTEXOFFSET_MASKMAP = 1 << 13;
public const int FLAG_BIT_WRAPMODE_BUMPTEX = 1 << 14;
public const int FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP = 1 << 15;
// public const int FLAG_BIT_WRAPMODE2_SHAREDUV = 1 << 0;
public const int foldOutBitMeshOption = 1 << 0;
public const int foldOutBitMainTexOption = 1 << 1;
public const int foldOutBitBaseOption = 1 << 2;
public const int foldOutBitFeatureOption = 1 << 3;
public const int foldOutBitBaseMap = 1 << 4;
public const int foldOutBitMask = 1 << 5;
public const int foldOutBitMaskMap = 1 << 6;
public const int foldOutBitMask2 = 1 << 7;
public const int foldOutBitMask3 = 1 << 8;
public const int foldOutBitTwril = 1 << 9;
public const int foldOutBitPolar = 1 << 10;
public const int foldOutBitHueShift = 1 << 11;
public const int foldOutBitSaturability = 1 << 12;
public const int foldOutBitDistanceFade = 1 << 13;
public const int foldOutBitSoftParticles = 1 << 14;
public const int foldOutBitMaskRotate = 1 << 15;
public const int foldOutBitNoise = 1 << 16;
public const int foldOutBitNoiseMap = 1 << 17;
public const int foldOutBitNoiseMaskToggle = 1 << 18;
public const int foldOutBitEmission = 1 << 19;
public const int foldOutBitDistortionChoraticaberrat = 1 << 20;
public const int foldOutDissolve = 1 << 21;
public const int foldOutDissolveMap = 1 << 22;
public const int foldOutProgramNoise = 1 << 23;
public const int foldOutDissolveRampMap = 1 << 24;
public const int foldOutDissolveMask = 1 << 25;
public const int foldOutColorBlend = 1 << 26;
public const int foldOutFresnel = 1 << 27;
public const int foldOutDepthOutline = 1 << 28;
public const int foldOutVertexOffset = 1 << 29;
public const int foldOutParallexMapping = 1 << 30;
// public const int foldOutBit1Portal= 1 << 31;
public const int foldOutBit1UVModeMainTex = 1 << 0;
public const int foldOutBit1UVModeMaskMap = 1 << 1;
public const int foldOutBit1UVModeMaskMap2 = 1 << 2;
public const int foldOutBit1UVModeMaskMap3 = 1 << 3;
public const int foldOutBit1UVModeNoiseMap = 1 << 4;
public const int foldOutBit1UVModeNoiseMaskMap = 1 << 5;
public const int foldOutBit1UVModeEmissionMap = 1 << 6;
public const int foldOutBit1UVModeDissolveMap = 1 << 7;
public const int foldOutBit1UVModeDissolveMaskMap = 1 << 8;
public const int foldOutBit1UVModeColorBlendMap = 1 << 9;
public const int foldOutBit1UVModeVertexOffsetMap = 1 << 10;
public const int foldOutBit1UVModeVertexOffsetMaskMap = 1 << 11;
public const int foldOutBit1UVModeBumpTex = 1 << 12;
public const int foldOutBit1UVModeRampColorMap = 1 << 13;
public const int foldOutBit1UVModeProgramNoise = 1 << 14;
//留一些位置给以后可能会增加的贴图。
public const int foldOutBit1Portal = 1 << 20;
public const int foldOutBit1ZOffset = 1 << 21;
public const int foldOutBit1CustomStencilTest = 1 << 22;
public const int foldOutBit1TaOption = 1 << 23;
public const int foldOutBit1MianTexContrast = 1 << 24;
public const int foldOutBit1VertexOffsetMask = 1 << 25;
public const int foldOutBit1MainTexColorRefine = 1 << 26;
public const int foldOutBit1LightOption = 1 << 27;
public const int foldOutBit1ShaderKeyword = 1 << 28;
public const int foldOutBit1BumpTex = 1 << 29;
public const int foldOutBit2BumpTexToggle = 1 << 0;
public const int foldOutBit2MatCapToggle = 1 << 1;
public const int foldOutBit2RampColor = 1 << 2;
public const int foldOutBit2DissolveLine = 1 << 3;
public const int foldOutBit2BaseBackColor = 1 << 4;
public const int foldOutBit2MaskRefine = 1 << 5;
public const int foldOutBit2ScreenDistortAlphaRefine = 1 << 6;
public const int foldOutBit2ProgramNoiseSimple = 1 << 7;
public const int foldOutBit2ProgramNoiseVoronoi = 1 << 8;
public const int foldOutBit2ColorAdjustment = 1 << 9;
public const int foldOutBit2SharedUV = 1 << 10;
public const int foldOutBit2SharedUVMode = 1 << 11;
public const int foldOutBit2VAT = 1 << 12;
#region CustomDataCodes
public const string CustomDataFlag0Name = "_W9ParticleCustomDataFlag0";
public const string CustomDataFlag1Name = "_W9ParticleCustomDataFlag1";
public const string CustomDataFlag2Name = "_W9ParticleCustomDataFlag2";
public const string CustomDataFlag3Name = "_W9ParticleCustomDataFlag3";
public static int CustomDataFlag0Id = Shader.PropertyToID(CustomDataFlag0Name);
public static int CustomDataFlag1Id = Shader.PropertyToID(CustomDataFlag1Name);
public static int CustomDataFlag2Id = Shader.PropertyToID(CustomDataFlag2Name);
public static int CustomDataFlag3Id = Shader.PropertyToID(CustomDataFlag3Name);
public enum CutomDataComponent
{
Off,
CustomData1X,
CustomData1Y,
CustomData1Z,
CustomData1W,
CustomData2X,
CustomData2Y,
CustomData2Z,
CustomData2W,
UnKnownOrMixed = -1
}
public const int FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_X = 0 * 4;
public const int FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_Y = 1 * 4;
public const int FLAGBIT_POS_0_CUSTOMDATA_DISSOLVE_INTENSITY = 2 * 4;
public const int FLAGBIT_POS_0_CUSTOMDATA_HUESHIFT = 3 * 4;
public const int FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_X = 4 * 4;
public const int FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_Y = 5 * 4;
public const int FLAGBIT_POS_0_CUSTOMDATA_FRESNEL_OFFSET = 6 * 4;
public const int FLAGBIT_POS_0_CUSTOMDATA_CHORATICABERRAT_INTENSITY = 7 * 4;
public const int FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_X = 0 * 4;
public const int FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_Y = 1 * 4;
public const int FLAGBIT_POS_1_CUSTOMDATA_NOISE_INTENSITY = 2 * 4;
public const int FLAGBIT_POS_1_CUSTOMDATA_SATURATE = 3 * 4;
public const int FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_X = 4 * 4;
public const int FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_Y = 5 * 4;
public const int FLAGBIT_POS_1_CUSTOMDATA_VERTEXOFFSET_INTENSITY = 6 * 4;
public const int FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_MASK_INTENSITY = 7 * 4;
public const int FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_X = 0 * 4;
public const int FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_Y = 1 * 4;
public const int FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_X = 2 * 4;
public const int FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_Y = 3 * 4;
public const int FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_X = 4 * 4;
public const int FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_Y = 5 * 4;
public const int FLAGBIT_POS_2_CUSTOMDATA_MAINTEX_CONTRAST = 6 * 4;
public const int FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME = 7 * 4;
public const int FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_X = 0 * 4;
public const int FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_Y = 1 * 4;
public const int FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_X = 2 * 4;
public const int FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_Y = 3 * 4;
public const int FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_X = 4 * 4;
public const int FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_Y = 5 * 4;
public const int FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_X = 6 * 4;
public const int FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_Y = 7 * 4;
public const int isCustomDataBit = 1 << 3;
public const int Data12Bit = 1 << 2; //true CustomData1 / false CustomData2
public const int DataXYorZWBit = 1 << 1; //true xy / false zw
public const int DataXZorYWBit = 1 << 0; //true xz / false yw
public const int CustomData1XBit = isCustomDataBit | Data12Bit | DataXYorZWBit | DataXZorYWBit;
public const int CustomData1YBit = isCustomDataBit | Data12Bit | DataXYorZWBit;
public const int CustomData1ZBit = isCustomDataBit | Data12Bit | DataXZorYWBit;
public const int CustomData1WBit = isCustomDataBit | Data12Bit;
public const int CustomData2XBit = isCustomDataBit | DataXYorZWBit | DataXZorYWBit;
public const int CustomData2YBit = isCustomDataBit | DataXYorZWBit;
public const int CustomData2ZBit = isCustomDataBit | DataXZorYWBit;
public const int CustomData2WBit = isCustomDataBit;
private int GetCustomDataFlagID(int dataIndex)
{
switch (dataIndex)
{
case 0:
return CustomDataFlag0Id;
case 1:
return CustomDataFlag1Id;
case 2:
return CustomDataFlag2Id;
case 3:
return CustomDataFlag3Id;
}
return 0;
}
public string GetCustomDataFlagPropertyName(int dataIndex)
{
switch (dataIndex)
{
case 0:
return CustomDataFlag0Name;
case 1:
return CustomDataFlag1Name;
case 2:
return CustomDataFlag2Name;
case 3:
return CustomDataFlag3Name;
}
return null;
}
public CutomDataComponent GetCustomDataFlag(int dataBitPos, int dataIndex)
{
int bit = material.GetInteger(GetCustomDataFlagID(dataIndex));
bit = bit >> dataBitPos;
bit &= 15; // binary 1111
if ((bit & isCustomDataBit) == 0)
{
return CutomDataComponent.Off;
}
else if (bit == CustomData1XBit)
{
return CutomDataComponent.CustomData1X;
}
else if (bit == CustomData1YBit)
{
return CutomDataComponent.CustomData1Y;
}
else if (bit == CustomData1ZBit)
{
return CutomDataComponent.CustomData1Z;
}
else if (bit == CustomData1WBit)
{
return CutomDataComponent.CustomData1W;
}
else if (bit == CustomData2XBit)
{
return CutomDataComponent.CustomData2X;
}
else if (bit == CustomData2YBit)
{
return CutomDataComponent.CustomData2Y;
}
else if (bit == CustomData2ZBit)
{
return CutomDataComponent.CustomData2Z;
}
else if (bit == CustomData2WBit)
{
return CutomDataComponent.CustomData2W;
}
else
{
}
Debug.Log("不可能存在的情况");
return CutomDataComponent.Off;
}
public void SetCustomDataFlag(CutomDataComponent cutomDataComponent, int dataBitPos, int dataIndex)
{
int bit = 0;
switch (cutomDataComponent)
{
case CutomDataComponent.Off:
bit = 0;
break;
case CutomDataComponent.CustomData1X:
bit = CustomData1XBit;
break;
case CutomDataComponent.CustomData1Y:
bit = CustomData1YBit;
break;
case CutomDataComponent.CustomData1Z:
bit = CustomData1ZBit;
break;
case CutomDataComponent.CustomData1W:
bit = CustomData1WBit;
break;
case CutomDataComponent.CustomData2X:
bit = CustomData2XBit;
break;
case CutomDataComponent.CustomData2Y:
bit = CustomData2YBit;
break;
case CutomDataComponent.CustomData2Z:
bit = CustomData2ZBit;
break;
case CutomDataComponent.CustomData2W:
bit = CustomData2WBit;
break;
}
bit = bit << dataBitPos;
int clearBit = ~(15 << dataBitPos); //~ (1111 << dataBitPos)
int materialBit = material.GetInteger(GetCustomDataFlagID(dataIndex));
materialBit = materialBit & clearBit;
materialBit = materialBit | bit;
material.SetInteger(GetCustomDataFlagID(dataIndex), materialBit);
}
public bool IsCustomDataOn()
{
int prop0Flag = material.GetInteger(CustomDataFlag0Id);
int prop1Flag = material.GetInteger(CustomDataFlag1Id);
int prop2Flag = material.GetInteger(CustomDataFlag2Id);
int prop3Flag = material.GetInteger(CustomDataFlag3Id);
uint dataOnBit = 0b_1000_1000_1000_1000_1000_1000_1000_1000; //10001000100010001000100010001000;
return ((prop0Flag & dataOnBit) > 0) || ((prop1Flag & dataOnBit) > 0) || ((prop2Flag & dataOnBit) > 0) ||
((prop3Flag & dataOnBit) > 0);
}
bool CheckCustomData(int dataIndex, int flagIndex)
{
int flagID = 0;
switch (flagIndex)
{
case 0:
flagID = CustomDataFlag0Id;
break;
case 1:
flagID = CustomDataFlag1Id;
break;
case 2:
flagID = CustomDataFlag2Id;
break;
case 3:
flagID = CustomDataFlag3Id;
break;
}
int flag = material.GetInteger(flagID);
int i = 0;
while (i < 8)
{
int bit = flag >> (4 * i);
if (dataIndex == 1)
{
if ((bit & 0b_1000) > 0 && (bit & 0b_0100) > 0)
{
return true;
}
}
else if (dataIndex == 2)
{
if ((bit & 0b_1000) > 0 && (bit & 0b_0100) == 0)
{
return true;
}
}
i += 1;
}
return false;
}
public bool IsCustomData1On()
{
if (!IsCustomDataOn())
{
return false;
}
bool isCustomData1On = false;
isCustomData1On |= CheckCustomData(1, 0);
isCustomData1On |= CheckCustomData(1, 1);
isCustomData1On |= CheckCustomData(1, 2);
isCustomData1On |= CheckCustomData(1, 3);
return isCustomData1On;
}
public bool IsCustomData2On()
{
if (!IsCustomDataOn())
{
return false;
}
bool isCustomData1On = false;
isCustomData1On |= CheckCustomData(2, 0);
isCustomData1On |= CheckCustomData(2, 1);
isCustomData1On |= CheckCustomData(2, 2);
isCustomData1On |= CheckCustomData(2, 3);
return isCustomData1On;
}
#endregion
public const string UVModeFlag0Name = "_UVModeFlag0";
public const string UVModeFlagType0Name = "_UVModeFlagType0";
public static int UVModeFlag0PropID = Shader.PropertyToID(UVModeFlag0Name);
public static int UVModeFlagType0PropID = Shader.PropertyToID(UVModeFlagType0Name);
public string GetUVModePropName(int dataIndex)
{
switch (dataIndex)
{
case 0:
return UVModeFlag0Name;
}
return null;
}
public enum UVMode
{
DefaultUVChannel, //0 0b_00 modeIndex 00
SpecialUVChannel, //1 0b_01 modeIndex 00
PolarOrTwirl, //2 0b_10 modeIndex 00
Cylinder, //3 0b_11 modeIndex 00
MainTex, //0 0b_00 modeIndex 01
ScreenUV, //1 0b_01 modeIndex 01
WorldPos, //2 0b_10 modeIndex 01
ObjectPos, //3 0b_11 modeIndex 01
CommonUV, //0 0b_00 modeIndex 10
UnknownOrMixed = -1
}
public const int FLAG_BIT_UVMODE_POS_0_MAINTEX = 0 * 2;
public const int FLAG_BIT_UVMODE_POS_0_MASKMAP = 1 * 2;
public const int FLAG_BIT_UVMODE_POS_0_MASKMAP_2 = 2 * 2;
public const int FLAG_BIT_UVMODE_POS_0_MASKMAP_3 = 3 * 2;
public const int FLAG_BIT_UVMODE_POS_0_NOISE_MAP = 4 * 2;
public const int FLAG_BIT_UVMODE_POS_0_NOISE_MASK_MAP = 5 * 2;
public const int FLAG_BIT_UVMODE_POS_0_EMISSION_MAP = 6 * 2;
public const int FLAG_BIT_UVMODE_POS_0_DISSOLVE_MAP = 7 * 2;
public const int FLAG_BIT_UVMODE_POS_0_DISSOLVE_MASK_MAP = 8 * 2;
public const int FLAG_BIT_UVMODE_POS_0_COLOR_BLEND_MAP = 9 * 2;
public const int FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MAP = 10 * 2;
public const int FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MASKMAP = 11 * 2;
public const int FLAG_BIT_UVMODE_POS_0_BUMPMAP = 12 * 2;
public const int FLAG_BIT_UVMODE_POS_0_RAMP_COLOR_MAP = 13 * 2;
public const int FLAG_BIT_UVMODE_POS_0_PROGRAM_NOISE = 14 * 2;
public const int FLAG_BIT_UVMODE_POS_0_SHAREDUV = 15 * 2;
public void GetUVModeFlagPropID(int flagIndex, out int flagID, out int flagTypeID)
{
switch (flagIndex)
{
case 0:
flagID = UVModeFlag0PropID;
flagTypeID = UVModeFlagType0PropID;
return;
}
flagID = 0;
flagTypeID = 0;
}
public void SetUVMode(UVMode mode, int uvModePos, int flagIndex = 0)
{
GetUVModeFlagPropID(flagIndex, out int uvModeFlagPropId, out int uvModeFlagTypePropId);
int uvModeFlag = material.GetInteger(uvModeFlagPropId);
int uvModeFlagType = material.GetInteger(uvModeFlagTypePropId);
int clearFlag = 0b_11 << uvModePos;
clearFlag = ~ clearFlag;
uvModeFlag &= clearFlag;
int modeBit = (int)mode % 4 << uvModePos;
uvModeFlag |= modeBit;
uvModeFlagType &= clearFlag;
int typeBit = (int)mode / 4 << uvModePos;
uvModeFlagType |= typeBit;
material.SetInteger(uvModeFlagPropId, uvModeFlag);
material.SetInteger(uvModeFlagTypePropId, uvModeFlagType);
}
public UVMode GetUVMode(int uvModePos, int flagIndex = 0)
{
GetUVModeFlagPropID(flagIndex, out int uvModeFlagPropId, out int uvModeFlagTypePropId);
int uvModeFlag = material.GetInteger(uvModeFlagPropId);
uvModeFlag = uvModeFlag >> uvModePos;
uvModeFlag &= 0b_11;
int uvModeFlagType = material.GetInteger(uvModeFlagTypePropId);
uvModeFlagType = uvModeFlagType >> uvModePos;
uvModeFlagType &= 0b_11;
return (UVMode)(uvModeFlag + 4 * uvModeFlagType);
}
public bool CheckIsUVModeOn(UVMode mode)
{
uint uvModeFlag0 = (uint)material.GetInteger(UVModeFlag0PropID);
uint uvModeFlagType0 = (uint)material.GetInteger(UVModeFlagType0PropID);
uint uvModeflagBit = (uint)mode % 4;
uint uvModeflagTypeBit = (uint)mode / 4;
bool isUvMode = false;
for (int i = 0; i < 16; i++)
{
uint checkflagBit = uvModeFlag0 >> (i * 2);
checkflagBit = checkflagBit & 0b_11;
uint checkflagTypeBit = uvModeflagTypeBit >> (i * 2);
checkflagTypeBit = checkflagTypeBit & 0b_11;
if (checkflagBit == uvModeflagBit && checkflagTypeBit == uvModeflagTypeBit)
{
isUvMode = true;
break;
}
}
return isUvMode;
}
public const int FLAG_BIT_COLOR_CHANNEL_POS_0_MAINTEX_ALPHA = 0 * 2;
public const int FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP1 = 1 * 2;
public const int FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP2 = 2 * 2;
public const int FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP3 = 3 * 2;
public const int FLAG_BIT_COLOR_CHANNEL_POS_0_NOISE_MASK = 4 * 2;
public const int FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MAP = 5 * 2;
public const int FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MASK_MAP = 6 * 2;
public const int FLAG_BIT_COLOR_CHANNEL_POS_0_RAMP_COLOR_MAP = 7 * 2;
public enum ColorChannel
{
X,
Y,
Z,
W,
UnKnownOrMixedValue
}
public void SetColorChanel(ColorChannel channel, int colorChannelFlagPos)
{
int colorChannelFlag = material.GetInteger(colorChannelFlagId);
int clearFlag = 0b_11 << colorChannelFlagPos;
clearFlag = ~ clearFlag;
colorChannelFlag &= clearFlag;
int channelBit = (int)channel << colorChannelFlagPos;
colorChannelFlag |= channelBit;
material.SetInteger(colorChannelFlagId, colorChannelFlag);
}
public ColorChannel GetColorChanel(int colorChannelFlagPos)
{
int colorChannelFlag = material.GetInteger(colorChannelFlagId);
colorChannelFlag = colorChannelFlag >> colorChannelFlagPos;
colorChannelFlag &= 0b_11;
return (ColorChannel)colorChannelFlag;
}
public const int FLAG_BIT_PNOISE_BLEND_POS_0_BASE_BLEND = 0 * 3;
public const int FLAG_BIT_PNOISE_BLEND_POS_0_MASK = 1 * 3;
public const int FLAG_BIT_PNOISE_BLEND_POS_0_DISSOLVE = 2 * 3;
public const int FLAG_BIT_PNOISE_BLEND_POS_0_DISTORT = 3 * 3;
public const int FLAG_BIT_PNOISE_BLEND_POS_0_MAINTEX = 4 * 3;
public enum PNoiseBlendMode
{
NotUse = 0,
Multiply = 1,
Min = 2,
HardLight = 3,
UnKnownOrMixedValue = -1
//后续看看要不要更多吧
}
public void SetPNoiseBlendMode(PNoiseBlendMode mode, int pNoiseBlendModeFlagPos)
{
int pNoiseBlendFlag = material.GetInteger(pNoiseBlendFlagId);
int blendMode = (int)mode;
if (blendMode < 0) return;
int clearFlag = 0b_111 << pNoiseBlendModeFlagPos;
clearFlag = ~clearFlag;
pNoiseBlendFlag &= clearFlag;
int pNoiseBlendBit = blendMode << pNoiseBlendModeFlagPos;
//先不考虑超过4个选项2bit的情况
pNoiseBlendFlag |= pNoiseBlendBit;
material.SetInteger(pNoiseBlendFlagId, pNoiseBlendFlag);
}
public PNoiseBlendMode GetPNoiseBlendMode(int pNoiseBlendModeFlagPos)
{
int pNoiseBlendFlag = material.GetInteger(pNoiseBlendFlagId);
pNoiseBlendFlag = pNoiseBlendFlag >> pNoiseBlendModeFlagPos;
pNoiseBlendFlag &= 0b_111;
//先不考虑超过4个选项2bit的情况
return (PNoiseBlendMode)pNoiseBlendFlag;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2b35030d15614953b769ad23d9fe5dfe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
namespace NBShader
{
/// <summary>
/// Serialized material mode values used by NBShader intent resolution.
/// These values mirror shader properties and must remain compatible with existing materials.
/// </summary>
internal static class NBShaderMaterialIntentProtocol
{
public const int MeshSourceParticle = 0;
public const int MeshSourceUIEffectRawImage = 2;
public const int MeshSourceUIEffectSprite = 3;
public const int MeshSourceUIEffectBaseMap = 4;
public const int MeshSourceUIParticle = 5;
public const int TransparentOpaque = 0;
public const int TransparentTransparent = 1;
public const int TransparentCutOff = 2;
public const int FxLightUnlit = 0;
public const int FxLightBlinnPhong = 1;
public const int FxLightHalfLambert = 2;
public const int FxLightPbr = 3;
public const int FxLightSixWay = 4;
public const int BlendAlpha = 0;
public const int BlendPremultiply = 1;
public const int BlendAdditive = 2;
public const int BlendMultiply = 3;
public const int BlendOpaque = 4;
public const int TimeUnscaled = 1;
public const int TimeScriptable = 2;
public const int VatTyflow = 1;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c88a6a4a7ec940c4aa97cfdcf4a8349e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,574 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace NBShader
{
/// <summary>
/// Resolves the serialized material feature intent into tier-filtered keywords and pass requirements.
/// This class is read-only: it never changes material properties, keywords, or shader pass state.
/// </summary>
internal static class NBShaderMaterialIntentResolver
{
private static readonly KeywordToggleBinding[] ToggleKeywordBindings =
{
new KeywordToggleBinding("_SoftParticlesEnabled", "_SOFTPARTICLES_ON"),
new KeywordToggleBinding("_DistanceFade_Toggle", "_DISTANCE_FADE"),
new KeywordToggleBinding("_StencilWithoutPlayerToggle", "_STENCIL_WITHOUT_PLAYER"),
new KeywordToggleBinding("_Mask_Toggle", "_MASKMAP_ON"),
new KeywordToggleBinding("_noisemapEnabled", "_NOISEMAP"),
new KeywordToggleBinding("_EmissionEnabled", "_EMISSION"),
new KeywordToggleBinding("_ColorBlendMap_Toggle", "_COLORMAPBLEND"),
new KeywordToggleBinding("_RampColorToggle", "_COLOR_RAMP"),
new KeywordToggleBinding("_Dissolve_Toggle", "_DISSOLVE"),
new KeywordToggleBinding("_ProgramNoise_Toggle", "_PROGRAM_NOISE"),
new KeywordToggleBinding("_SharedUVToggle", "_SHARED_UV"),
new KeywordToggleBinding("_fresnelEnabled", "_FRESNEL"),
new KeywordToggleBinding("_ParallaxMapping_Toggle", "_PARALLAX_MAPPING"),
new KeywordToggleBinding("_VertexOffset_Toggle", "_VERTEX_OFFSET"),
new KeywordToggleBinding("_FlipbookBlending", "_FLIPBOOKBLENDING_ON"),
new KeywordToggleBinding("_BumpMapToggle", "_NORMALMAP"),
new KeywordToggleBinding("_MatCapToggle", "_MATCAP"),
new KeywordToggleBinding("_BlinnPhongSpecularToggle", "_SPECULAR_COLOR"),
new KeywordToggleBinding("_SixWayColorAbsorptionToggle", "VFX_SIX_WAY_ABSORPTION"),
new KeywordToggleBinding("_DepthDecal_Toggle", "_DEPTH_DECAL"),
new KeywordToggleBinding("_DepthOutline_Toggle", "_DEPTH_OUTLINE"),
new KeywordToggleBinding("_OverrideZ_Toggle", "_OVERRIDE_Z"),
new KeywordToggleBinding("_Mask2_Toggle", "_MASKMAP2_ON"),
new KeywordToggleBinding("_Mask3_Toggle", "_MASKMAP3_ON"),
new KeywordToggleBinding("_noiseMaskMap_Toggle", "_NOISE_MASKMAP"),
new KeywordToggleBinding("_Distortion_Choraticaberrat_Toggle", "_CHROMATIC_ABERRATION"),
new KeywordToggleBinding("_DissolveMask_Toggle", "_DISSOLVE_MASK"),
new KeywordToggleBinding("_Dissolve_useRampMap_Toggle", "_DISSOLVE_RAMP"),
new KeywordToggleBinding("_ProgramNoise_Simple_Toggle", "_PROGRAM_NOISE_SIMPLE"),
new KeywordToggleBinding("_ProgramNoise_Voronoi_Toggle", "_PROGRAM_NOISE_VORONOI"),
new KeywordToggleBinding("_VertexOffset_Mask_Toggle", "_VERTEX_OFFSET_MASKMAP"),
new KeywordToggleBinding("_NB_Debug_Dissolve", "NB_DEBUG_DISSOLVE"),
new KeywordToggleBinding("_NB_Debug_Distort", "NB_DEBUG_DISTORT"),
new KeywordToggleBinding("_NB_Debug_Fresnel", "NB_DEBUG_FRESNEL"),
new KeywordToggleBinding("_NB_Debug_Mask", "NB_DEBUG_MASK"),
new KeywordToggleBinding("_NB_Debug_PNoise", "NB_DEBUG_PNOISE"),
new KeywordToggleBinding("_NB_Debug_VertexOffset", "NB_DEBUG_VERTEX_OFFSET")
};
private static readonly string[] HoudiniVatKeywords =
{
"_HOUDINI_VAT_SOFTBODY",
"_HOUDINI_VAT_RIGIDBODY",
"_HOUDINI_VAT_DYNAMIC_REMESH",
"_HOUDINI_VAT_PARTICLE_SPRITE"
};
private static readonly string[] TyflowVatKeywords =
{
"_TYFLOW_VAT_ABSOLUTE",
"_TYFLOW_VAT_RELATIVE",
"_TYFLOW_VAT_SKIN_R",
"_TYFLOW_VAT_SKIN_PR",
"_TYFLOW_VAT_SKIN_PRSAVE",
"_TYFLOW_VAT_SKIN_PRSXYZ"
};
public static bool IsNBShaderMaterial(Material material)
{
return material != null &&
material.shader != null &&
material.shader.name == NBShaderFeatureCatalog.ShaderName;
}
public static NBShaderMaterialIntentResult Resolve(Material material, NBShaderFeatureTier tier)
{
return Resolve(
material,
tier,
NBShaderFeatureCatalog.RawKeywords,
NBShaderPassFeatureCatalog.GetDefaultAllowedPassFeatures(tier));
}
public static NBShaderMaterialIntentResult Resolve(
Material material,
NBShaderFeatureTier tier,
IEnumerable<string> allowedManagedKeywords,
IEnumerable<string> allowedPassFeatureIds)
{
var allowedKeywords = BuildAllowedKeywordSet(allowedManagedKeywords);
var allowedPassFeatures = BuildAllowedPassFeatureSet(allowedPassFeatureIds);
var intendedKeywords = ResolveIntendedManagedKeywords(material);
var effectiveKeywords = FilterAllowedKeywords(intendedKeywords, allowedKeywords);
ApplyKeywordDependencies(effectiveKeywords);
var strippedKeywords = BuildDifference(intendedKeywords, effectiveKeywords);
var passIntents = ResolvePassIntents(material, effectiveKeywords, allowedPassFeatures);
return new NBShaderMaterialIntentResult(
material,
tier,
ToCatalogOrderedArray(intendedKeywords),
ToCatalogOrderedArray(effectiveKeywords),
ToCatalogOrderedArray(strippedKeywords),
passIntents);
}
private static HashSet<string> ResolveIntendedManagedKeywords(Material material)
{
var keywords = new HashSet<string>(StringComparer.Ordinal);
if (!IsNBShaderMaterial(material))
return keywords;
for (var i = 0; i < ToggleKeywordBindings.Length; i++)
{
var binding = ToggleKeywordBindings[i];
if (GetFloat(material, binding.propertyName, 0f) > 0.5f)
AddManagedKeyword(keywords, binding.keyword);
}
int meshMode = GetInt(material, "_MeshSourceMode", 0);
int transparentMode = GetInt(material, "_TransparentMode", NBShaderMaterialIntentProtocol.TransparentTransparent);
if (transparentMode == NBShaderMaterialIntentProtocol.TransparentCutOff)
AddManagedKeyword(keywords, "_ALPHATEST_ON");
int blendMode = ResolveBlendMode(material, transparentMode);
switch (blendMode)
{
case NBShaderMaterialIntentProtocol.BlendPremultiply:
case NBShaderMaterialIntentProtocol.BlendAdditive:
AddManagedKeyword(keywords, "_ALPHAPREMULTIPLY_ON");
break;
case NBShaderMaterialIntentProtocol.BlendMultiply:
AddManagedKeyword(keywords, "_ALPHAMODULATE_ON");
break;
}
if (IsParticleMeshSource(meshMode))
AddManagedKeyword(keywords, "_PARCUSTOMDATA_ON");
switch (GetInt(material, "_TimeMode", 0))
{
case NBShaderMaterialIntentProtocol.TimeUnscaled:
AddManagedKeyword(keywords, "_UNSCALETIME");
break;
case NBShaderMaterialIntentProtocol.TimeScriptable:
AddManagedKeyword(keywords, "_SCRIPTABLETIME");
break;
}
switch (GetInt(material, "_FxLightMode", NBShaderMaterialIntentProtocol.FxLightUnlit))
{
case NBShaderMaterialIntentProtocol.FxLightUnlit:
AddManagedKeyword(keywords, "_FX_LIGHT_MODE_UNLIT");
break;
case NBShaderMaterialIntentProtocol.FxLightBlinnPhong:
AddManagedKeyword(keywords, "_FX_LIGHT_MODE_BLINN_PHONG");
break;
case NBShaderMaterialIntentProtocol.FxLightHalfLambert:
AddManagedKeyword(keywords, "_FX_LIGHT_MODE_HALF_LAMBERT");
break;
case NBShaderMaterialIntentProtocol.FxLightPbr:
AddManagedKeyword(keywords, "_FX_LIGHT_MODE_PBR");
break;
case NBShaderMaterialIntentProtocol.FxLightSixWay:
AddManagedKeyword(keywords, "_FX_LIGHT_MODE_SIX_WAY");
break;
}
if (GetInt(material, "_DistortMode", 0) == 1)
AddManagedKeyword(keywords, "_DISTORT_REFRACTION");
if (GetInt(material, "_RampColorSourceMode", 0) == 1)
AddManagedKeyword(keywords, "_COLOR_RAMP_MAP");
if (GetInt(material, "_DissolveRampSourceMode", 0) == 1 &&
GetFloat(material, "_Dissolve_useRampMap_Toggle", 0f) > 0.5f)
{
AddManagedKeyword(keywords, "_DISSOLVE_RAMP_MAP");
}
if (!IsUIEffectMeshSource(meshMode) && GetInt(material, "_ScreenDistortModeToggle", 0) != 0)
AddManagedKeyword(keywords, "_SCREEN_DISTORT_MODE");
ResolveVatKeywords(material, keywords);
return keywords;
}
private static void ResolveVatKeywords(Material material, HashSet<string> keywords)
{
if (GetFloat(material, "_VAT_Toggle", 0f) <= 0.5f)
return;
keywords.Remove("_FLIPBOOKBLENDING_ON");
AddManagedKeyword(keywords, "_VAT");
if (GetInt(material, "_VATMode", 0) == NBShaderMaterialIntentProtocol.VatTyflow)
{
AddManagedKeyword(keywords, "_VAT_TYFLOW");
AddIndexedKeyword(keywords, TyflowVatKeywords, GetInt(material, "_TyFlowVATSubMode", 0));
}
else
{
AddManagedKeyword(keywords, "_VAT_HOUDINI");
AddIndexedKeyword(keywords, HoudiniVatKeywords, GetInt(material, "_HoudiniVATSubMode", 0));
}
}
private static NBShaderPassIntent[] ResolvePassIntents(
Material material,
HashSet<string> effectiveKeywords,
HashSet<string> allowedPassFeatures)
{
var result = new List<NBShaderPassIntent>(7);
bool isNBShaderMaterial = IsNBShaderMaterial(material);
int meshMode = GetInt(material, "_MeshSourceMode", 0);
int transparentMode = GetInt(material, "_TransparentMode", NBShaderMaterialIntentProtocol.TransparentTransparent);
bool uiEffect = IsUIEffectMeshSource(meshMode);
int screenDistortMode = isNBShaderMaterial ? GetInt(material, "_ScreenDistortModeToggle", 0) : 0;
bool screenDistortKeywordEnabled = effectiveKeywords.Contains("_SCREEN_DISTORT_MODE");
bool screenDistortEnabled = !uiEffect && screenDistortMode != 0 && screenDistortKeywordEnabled;
bool disableMainPass = GetFloat(material, "_DisableMainPassToggle", 0f) > 0.5f;
bool mainPassEnabled = isNBShaderMaterial && (!screenDistortEnabled || !disableMainPass);
result.Add(NBShaderPassIntent.CreateCore(
NBShaderPassFeatureCatalog.MainForwardPassName,
mainPassEnabled,
mainPassEnabled ? "main pass" : "disabled by screen distort material intent"));
AddManagedPass(
result,
NBShaderPassFeatureCatalog.BackFirstPassId,
!uiEffect &&
transparentMode == NBShaderMaterialIntentProtocol.TransparentTransparent &&
GetFloat(material, "_BackFirstPassToggle", 0f) > 0.5f,
allowedPassFeatures,
"back first material toggle");
AddManagedPass(
result,
NBShaderPassFeatureCatalog.CameraOpaqueDistortPassId,
screenDistortEnabled && screenDistortMode == 2,
allowedPassFeatures,
"camera opaque screen distort material mode");
AddManagedPass(
result,
NBShaderPassFeatureCatalog.DeferredDistortPassId,
screenDistortEnabled && screenDistortMode == 1,
allowedPassFeatures,
"deferred screen distort material mode");
AddManagedPass(
result,
NBShaderPassFeatureCatalog.DepthOnlyPassId,
!uiEffect && ResolveZWrite(material, transparentMode),
allowedPassFeatures,
"depth write material state");
AddManagedPass(
result,
NBShaderPassFeatureCatalog.ShadowCasterPassId,
!uiEffect &&
GetFloat(material, "_AffectsShadows", 0f) > 0.5f &&
IsKnownTransparentMode(GetInt(material, "_TransparentMode", NBShaderMaterialIntentProtocol.TransparentTransparent)),
allowedPassFeatures,
"shadow material state");
AddManagedPass(
result,
NBShaderPassFeatureCatalog.Universal2DPassId,
isNBShaderMaterial,
allowedPassFeatures,
"URP 2D renderer pass");
return result.ToArray();
}
private static void AddManagedPass(
List<NBShaderPassIntent> result,
string featureId,
bool enabledByMaterial,
HashSet<string> allowedPassFeatures,
string reason)
{
NBShaderPassFeatureInfo feature;
if (!NBShaderPassFeatureCatalog.TryGetPassFeature(featureId, out feature))
return;
bool allowedByTier = allowedPassFeatures == null || allowedPassFeatures.Contains(featureId);
result.Add(new NBShaderPassIntent(
featureId,
feature.passName,
enabledByMaterial,
allowedByTier,
enabledByMaterial && allowedByTier,
reason));
}
private static HashSet<string> BuildAllowedKeywordSet(IEnumerable<string> allowedManagedKeywords)
{
var result = new HashSet<string>(StringComparer.Ordinal);
if (allowedManagedKeywords == null)
{
for (var i = 0; i < NBShaderFeatureCatalog.RawKeywords.Length; i++)
result.Add(NBShaderFeatureCatalog.RawKeywords[i]);
return result;
}
foreach (var keyword in allowedManagedKeywords)
{
if (NBShaderFeatureCatalog.IsManagedKeyword(keyword))
result.Add(keyword);
}
return result;
}
private static HashSet<string> BuildAllowedPassFeatureSet(IEnumerable<string> allowedPassFeatureIds)
{
if (allowedPassFeatureIds == null)
return null;
var result = new HashSet<string>(StringComparer.Ordinal);
foreach (var featureId in allowedPassFeatureIds)
{
if (NBShaderPassFeatureCatalog.IsManagedPassFeature(featureId))
result.Add(featureId);
}
return result;
}
private static HashSet<string> FilterAllowedKeywords(HashSet<string> source, HashSet<string> allowed)
{
var result = new HashSet<string>(StringComparer.Ordinal);
foreach (var keyword in source)
{
if (allowed.Contains(keyword))
result.Add(keyword);
}
return result;
}
private static void ApplyKeywordDependencies(HashSet<string> keywords)
{
RemoveIfParentMissing(keywords, "_MASKMAP_ON", "_MASKMAP2_ON", "_MASKMAP3_ON", "NB_DEBUG_MASK");
RemoveIfParentMissing(keywords, "_NOISEMAP", "_NOISE_MASKMAP", "NB_DEBUG_DISTORT", "_SCREEN_DISTORT_MODE", "_DISTORT_REFRACTION");
RemoveIfParentMissing(keywords, "_COLOR_RAMP", "_COLOR_RAMP_MAP");
RemoveIfParentMissing(keywords, "_DISSOLVE", "_DISSOLVE_MASK", "_DISSOLVE_RAMP", "NB_DEBUG_DISSOLVE");
RemoveIfParentMissing(keywords, "_DISSOLVE_RAMP", "_DISSOLVE_RAMP_MAP");
RemoveIfParentMissing(keywords, "_PROGRAM_NOISE", "_PROGRAM_NOISE_SIMPLE", "_PROGRAM_NOISE_VORONOI", "NB_DEBUG_PNOISE");
RemoveIfParentMissing(keywords, "_FRESNEL", "NB_DEBUG_FRESNEL");
RemoveIfParentMissing(keywords, "_VERTEX_OFFSET", "_VERTEX_OFFSET_MASKMAP", "NB_DEBUG_VERTEX_OFFSET");
RemoveIfParentMissing(keywords, "_VAT", "_VAT_HOUDINI", "_VAT_TYFLOW");
RemoveIfParentMissing(keywords, "_VAT_HOUDINI", HoudiniVatKeywords);
RemoveIfParentMissing(keywords, "_VAT_TYFLOW", TyflowVatKeywords);
RemoveIfParentMissing(keywords, "_FX_LIGHT_MODE_SIX_WAY", "VFX_SIX_WAY_ABSORPTION");
}
private static void RemoveIfParentMissing(HashSet<string> keywords, string parentKeyword, params string[] dependentKeywords)
{
if (keywords.Contains(parentKeyword) || dependentKeywords == null)
return;
for (var i = 0; i < dependentKeywords.Length; i++)
keywords.Remove(dependentKeywords[i]);
}
private static HashSet<string> BuildDifference(HashSet<string> source, HashSet<string> retained)
{
var result = new HashSet<string>(StringComparer.Ordinal);
foreach (var keyword in source)
{
if (!retained.Contains(keyword))
result.Add(keyword);
}
return result;
}
private static void AddManagedKeyword(HashSet<string> keywords, string keyword)
{
if (NBShaderFeatureCatalog.IsManagedKeyword(keyword))
keywords.Add(keyword);
}
private static void AddIndexedKeyword(HashSet<string> keywords, string[] source, int index)
{
if (source == null || index < 0 || index >= source.Length)
return;
AddManagedKeyword(keywords, source[index]);
}
private static string[] ToCatalogOrderedArray(HashSet<string> keywords)
{
if (keywords == null || keywords.Count == 0)
return new string[0];
var result = new List<string>();
for (var i = 0; i < NBShaderFeatureCatalog.RawKeywords.Length; i++)
{
var keyword = NBShaderFeatureCatalog.RawKeywords[i];
if (keywords.Contains(keyword))
result.Add(keyword);
}
return result.ToArray();
}
private static bool IsParticleMeshSource(int mode)
{
return mode == NBShaderMaterialIntentProtocol.MeshSourceParticle ||
mode == NBShaderMaterialIntentProtocol.MeshSourceUIParticle;
}
private static bool IsUIEffectMeshSource(int mode)
{
return mode == NBShaderMaterialIntentProtocol.MeshSourceUIEffectRawImage ||
mode == NBShaderMaterialIntentProtocol.MeshSourceUIEffectSprite ||
mode == NBShaderMaterialIntentProtocol.MeshSourceUIEffectBaseMap ||
mode == NBShaderMaterialIntentProtocol.MeshSourceUIParticle;
}
private static bool IsKnownTransparentMode(int mode)
{
return mode == NBShaderMaterialIntentProtocol.TransparentOpaque ||
mode == NBShaderMaterialIntentProtocol.TransparentTransparent ||
mode == NBShaderMaterialIntentProtocol.TransparentCutOff;
}
private static int ResolveBlendMode(Material material, int transparentMode)
{
if (!IsKnownTransparentMode(transparentMode))
return GetInt(material, "_Blend", 0);
if (transparentMode == NBShaderMaterialIntentProtocol.TransparentOpaque ||
transparentMode == NBShaderMaterialIntentProtocol.TransparentCutOff)
return NBShaderMaterialIntentProtocol.BlendOpaque;
int blendMode = GetInt(material, "_Blend", 0);
return blendMode == NBShaderMaterialIntentProtocol.BlendOpaque
? NBShaderMaterialIntentProtocol.BlendAlpha
: blendMode;
}
private static bool ResolveZWrite(Material material, int transparentMode)
{
bool zWrite;
if (transparentMode == NBShaderMaterialIntentProtocol.TransparentOpaque ||
transparentMode == NBShaderMaterialIntentProtocol.TransparentCutOff)
{
zWrite = true;
}
else if (transparentMode == NBShaderMaterialIntentProtocol.TransparentTransparent)
{
zWrite = false;
}
else
{
zWrite = GetInt(material, "_ZWrite", 0) == 1;
}
float forceZWrite = GetFloat(material, "_ForceZWriteToggle", 0f);
if (forceZWrite > 0.5f && forceZWrite < 1.5f)
return true;
if (forceZWrite > 1.5f)
return false;
return zWrite;
}
private static float GetFloat(Material material, string propertyName, float fallback)
{
return material != null && material.HasProperty(propertyName) ? material.GetFloat(propertyName) : fallback;
}
private static int GetInt(Material material, string propertyName, int fallback)
{
return Mathf.RoundToInt(GetFloat(material, propertyName, fallback));
}
private struct KeywordToggleBinding
{
public readonly string propertyName;
public readonly string keyword;
public KeywordToggleBinding(string propertyName, string keyword)
{
this.propertyName = propertyName;
this.keyword = keyword;
}
}
}
internal sealed class NBShaderMaterialIntentResult
{
public readonly Material material;
public readonly NBShaderFeatureTier tier;
public readonly string[] intendedManagedKeywords;
public readonly string[] effectiveKeywords;
public readonly string[] strippedManagedKeywords;
public readonly NBShaderPassIntent[] passes;
public readonly string[] includedPassNames;
public readonly string[] strippedPassNames;
public NBShaderMaterialIntentResult(
Material material,
NBShaderFeatureTier tier,
string[] intendedManagedKeywords,
string[] effectiveKeywords,
string[] strippedManagedKeywords,
NBShaderPassIntent[] passes)
{
this.material = material;
this.tier = tier;
this.intendedManagedKeywords = intendedManagedKeywords ?? new string[0];
this.effectiveKeywords = effectiveKeywords ?? new string[0];
this.strippedManagedKeywords = strippedManagedKeywords ?? new string[0];
this.passes = passes ?? new NBShaderPassIntent[0];
includedPassNames = BuildPassNameArray(this.passes, true);
strippedPassNames = BuildPassNameArray(this.passes, false);
}
private static string[] BuildPassNameArray(NBShaderPassIntent[] passes, bool included)
{
var result = new List<string>();
for (var i = 0; i < passes.Length; i++)
{
var pass = passes[i];
if (pass.included == included && !string.IsNullOrEmpty(pass.passName))
result.Add(pass.passName);
}
return result.ToArray();
}
}
internal sealed class NBShaderPassIntent
{
public readonly string featureId;
public readonly string passName;
public readonly bool enabledByMaterial;
public readonly bool allowedByTier;
public readonly bool included;
public readonly string reason;
public NBShaderPassIntent(
string featureId,
string passName,
bool enabledByMaterial,
bool allowedByTier,
bool included,
string reason)
{
this.featureId = featureId;
this.passName = passName;
this.enabledByMaterial = enabledByMaterial;
this.allowedByTier = allowedByTier;
this.included = included;
this.reason = reason;
}
public static NBShaderPassIntent CreateCore(string passName, bool included, string reason)
{
return new NBShaderPassIntent(null, passName, included, true, included, reason);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b6fbac1987464c5f9bf46b3b121d4c21
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,106 @@
using System.Collections.Generic;
namespace NBShader
{
/// <summary>
/// Catalog of NBShader passes that can be controlled by feature tiering.
/// UniversalForward is the primary pass and is intentionally not listed as a tier feature.
/// </summary>
internal static class NBShaderPassFeatureCatalog
{
public const string MainForwardPassName = "UniversalForward";
public const string BackFirstPassId = "pass.backFirst";
public const string CameraOpaqueDistortPassId = "pass.screenDistort.cameraOpaque";
public const string DeferredDistortPassId = "pass.screenDistort.deferred";
public const string DepthOnlyPassId = "pass.depthOnly";
public const string ShadowCasterPassId = "pass.shadowCaster";
public const string Universal2DPassId = "pass.universal2D";
public static readonly NBShaderPassFeatureInfo[] RawPassFeatures =
{
new NBShaderPassFeatureInfo(BackFirstPassId, "SRPDefaultUnlit", "Back First Pass"),
new NBShaderPassFeatureInfo(CameraOpaqueDistortPassId, "NBCameraOpaqueDistortPass", "Camera Opaque Distort Pass"),
new NBShaderPassFeatureInfo(DeferredDistortPassId, "NBDeferredDistortPass", "Deferred Distort Pass"),
new NBShaderPassFeatureInfo(DepthOnlyPassId, "DepthOnly", "Depth Only Pass"),
new NBShaderPassFeatureInfo(ShadowCasterPassId, "ShadowCaster", "Shadow Caster Pass"),
new NBShaderPassFeatureInfo(Universal2DPassId, "Universal2D", "Universal 2D Pass")
};
public static readonly string[] RawPassFeatureIds = BuildRawPassFeatureIds();
private static readonly HashSet<string> RawPassFeatureIdSet = new HashSet<string>(RawPassFeatureIds);
private static readonly Dictionary<string, NBShaderPassFeatureInfo> PassFeaturesById = BuildPassFeaturesById();
private static readonly Dictionary<string, NBShaderPassFeatureInfo> PassFeaturesByPassName = BuildPassFeaturesByPassName();
public static bool IsManagedPassFeature(string featureId)
{
return !string.IsNullOrEmpty(featureId) && RawPassFeatureIdSet.Contains(featureId);
}
public static bool TryGetPassFeature(string featureId, out NBShaderPassFeatureInfo feature)
{
if (string.IsNullOrEmpty(featureId))
{
feature = null;
return false;
}
return PassFeaturesById.TryGetValue(featureId, out feature);
}
public static bool TryGetPassFeatureByPassName(string passName, out NBShaderPassFeatureInfo feature)
{
if (string.IsNullOrEmpty(passName))
{
feature = null;
return false;
}
return PassFeaturesByPassName.TryGetValue(passName, out feature);
}
public static string[] GetDefaultAllowedPassFeatures(NBShaderFeatureTier tier)
{
return (string[])RawPassFeatureIds.Clone();
}
private static string[] BuildRawPassFeatureIds()
{
var result = new string[RawPassFeatures.Length];
for (var i = 0; i < RawPassFeatures.Length; i++)
result[i] = RawPassFeatures[i].id;
return result;
}
private static Dictionary<string, NBShaderPassFeatureInfo> BuildPassFeaturesById()
{
var result = new Dictionary<string, NBShaderPassFeatureInfo>();
for (var i = 0; i < RawPassFeatures.Length; i++)
result[RawPassFeatures[i].id] = RawPassFeatures[i];
return result;
}
private static Dictionary<string, NBShaderPassFeatureInfo> BuildPassFeaturesByPassName()
{
var result = new Dictionary<string, NBShaderPassFeatureInfo>();
for (var i = 0; i < RawPassFeatures.Length; i++)
result[RawPassFeatures[i].passName] = RawPassFeatures[i];
return result;
}
}
internal sealed class NBShaderPassFeatureInfo
{
public readonly string id;
public readonly string passName;
public readonly string displayName;
public NBShaderPassFeatureInfo(string id, string passName, string displayName)
{
this.id = id;
this.passName = passName;
this.displayName = displayName;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3238bc94e7aff1147a510c286ad0a673
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a81bdbda432342429bd339932aee1d15
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("com.xuanxuan.nb.shaders2.Editor")]

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f4991907da0943fe9b83896151ba7d2b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
{
"name": "com.xuanxuan.nb.shaders2",
"rootNamespace": "",
"references": [
"GUID:8f9e4d586616f13449cfeb86c5f704c2"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: aed681b6b9e69ff4dbd8d55e012b87ff
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: