306 lines
13 KiB
C#
306 lines
13 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using System.Collections;
|
|
|
|
namespace VLB
|
|
{
|
|
public static class MaterialManager
|
|
{
|
|
public static MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock();
|
|
|
|
public enum BlendingMode
|
|
{
|
|
Additive,
|
|
SoftAdditive,
|
|
TraditionalTransparency,
|
|
Count
|
|
}
|
|
|
|
public enum ColorGradient
|
|
{
|
|
Off,
|
|
MatrixLow,
|
|
MatrixHigh,
|
|
Count
|
|
}
|
|
|
|
public enum Noise3D
|
|
{
|
|
Off,
|
|
On,
|
|
Count
|
|
}
|
|
|
|
public static class SD
|
|
{
|
|
public enum DepthBlend
|
|
{
|
|
Off,
|
|
On,
|
|
Count
|
|
}
|
|
|
|
public enum DynamicOcclusion
|
|
{
|
|
Off,
|
|
ClippingPlane,
|
|
DepthTexture,
|
|
Count
|
|
}
|
|
|
|
public enum MeshSkewing
|
|
{
|
|
Off,
|
|
On,
|
|
Count
|
|
}
|
|
|
|
public enum ShaderAccuracy
|
|
{
|
|
Fast,
|
|
High,
|
|
Count
|
|
}
|
|
}
|
|
|
|
public static class HD
|
|
{
|
|
public enum Attenuation
|
|
{
|
|
Linear,
|
|
Quadratic,
|
|
Count
|
|
}
|
|
|
|
public enum Shadow
|
|
{
|
|
Off,
|
|
On,
|
|
Count
|
|
}
|
|
|
|
public enum Cookie
|
|
{
|
|
Off,
|
|
SingleChannel,
|
|
RGBA,
|
|
Count
|
|
}
|
|
}
|
|
|
|
static readonly UnityEngine.Rendering.BlendMode[] BlendingMode_SrcFactor = new UnityEngine.Rendering.BlendMode[(int)BlendingMode.Count]
|
|
{
|
|
UnityEngine.Rendering.BlendMode.One, // Additive
|
|
UnityEngine.Rendering.BlendMode.OneMinusDstColor, // SoftAdditive
|
|
UnityEngine.Rendering.BlendMode.SrcAlpha, // TraditionalTransparency
|
|
};
|
|
|
|
static readonly UnityEngine.Rendering.BlendMode[] BlendingMode_DstFactor = new UnityEngine.Rendering.BlendMode[(int)BlendingMode.Count]
|
|
{
|
|
UnityEngine.Rendering.BlendMode.One, // Additive
|
|
UnityEngine.Rendering.BlendMode.One, // SoftAdditive
|
|
UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha, // TraditionalTransparency
|
|
};
|
|
|
|
static readonly bool[] BlendingMode_AlphaAsBlack = new bool[(int)BlendingMode.Count]
|
|
{
|
|
true, // Additive
|
|
true, // SoftAdditive
|
|
false, // TraditionalTransparency
|
|
};
|
|
|
|
interface IStaticProperties
|
|
{
|
|
int GetPropertiesCount();
|
|
int GetMaterialID();
|
|
void ApplyToMaterial(Material mat);
|
|
ShaderMode GetShaderMode();
|
|
}
|
|
|
|
// STATIC PROPERTIES SD
|
|
public struct StaticPropertiesSD : IStaticProperties
|
|
{
|
|
public ShaderMode GetShaderMode() { return ShaderMode.SD; }
|
|
public static int staticPropertiesCount { get { return (int)BlendingMode.Count * (int)Noise3D.Count * (int)SD.DepthBlend.Count * (int)ColorGradient.Count * (int)SD.DynamicOcclusion.Count * (int)SD.MeshSkewing.Count * (int)SD.ShaderAccuracy.Count; } }
|
|
public int GetPropertiesCount() { return staticPropertiesCount; }
|
|
|
|
public BlendingMode blendingMode;
|
|
public Noise3D noise3D;
|
|
public SD.DepthBlend depthBlend;
|
|
public ColorGradient colorGradient;
|
|
public SD.DynamicOcclusion dynamicOcclusion;
|
|
public SD.MeshSkewing meshSkewing;
|
|
public SD.ShaderAccuracy shaderAccuracy;
|
|
|
|
int blendingModeID { get { return (int)blendingMode; } }
|
|
int noise3DID { get { return Config.Instance.featureEnabledNoise3D ? (int)noise3D : 0; } }
|
|
int depthBlendID { get { return Config.Instance.featureEnabledDepthBlend ? (int)depthBlend : 0; } }
|
|
int colorGradientID { get { return Config.Instance.featureEnabledColorGradient != FeatureEnabledColorGradient.Off ? (int)colorGradient : 0; } }
|
|
int dynamicOcclusionID { get { return Config.Instance.featureEnabledDynamicOcclusion ? (int)dynamicOcclusion : 0; } }
|
|
int meshSkewingID { get { return Config.Instance.featureEnabledMeshSkewing ? (int)meshSkewing : 0; } }
|
|
int shaderAccuracyID { get { return Config.Instance.featureEnabledShaderAccuracyHigh ? (int)shaderAccuracy : 0; } }
|
|
|
|
public int GetMaterialID()
|
|
{
|
|
return (((((((blendingModeID)
|
|
* (int)Noise3D.Count + noise3DID)
|
|
* (int)SD.DepthBlend.Count + depthBlendID)
|
|
* (int)ColorGradient.Count + colorGradientID)
|
|
* (int)SD.DynamicOcclusion.Count + dynamicOcclusionID)
|
|
* (int)SD.MeshSkewing.Count + meshSkewingID)
|
|
* (int)SD.ShaderAccuracy.Count + shaderAccuracyID)
|
|
;
|
|
}
|
|
|
|
public void ApplyToMaterial(Material mat)
|
|
{
|
|
mat.SetKeywordEnabled(ShaderKeywords.AlphaAsBlack, BlendingMode_AlphaAsBlack[(int)blendingMode]);
|
|
mat.SetKeywordEnabled(ShaderKeywords.ColorGradientMatrixLow, colorGradient == ColorGradient.MatrixLow);
|
|
mat.SetKeywordEnabled(ShaderKeywords.ColorGradientMatrixHigh, colorGradient == ColorGradient.MatrixHigh);
|
|
mat.SetKeywordEnabled(ShaderKeywords.SD.DepthBlend, depthBlend == SD.DepthBlend.On);
|
|
mat.SetKeywordEnabled(ShaderKeywords.Noise3D, noise3D == Noise3D.On);
|
|
mat.SetKeywordEnabled(ShaderKeywords.SD.OcclusionClippingPlane, dynamicOcclusion == SD.DynamicOcclusion.ClippingPlane);
|
|
mat.SetKeywordEnabled(ShaderKeywords.SD.OcclusionDepthTexture, dynamicOcclusion == SD.DynamicOcclusion.DepthTexture);
|
|
mat.SetKeywordEnabled(ShaderKeywords.SD.MeshSkewing, meshSkewing == SD.MeshSkewing.On);
|
|
mat.SetKeywordEnabled(ShaderKeywords.SD.ShaderAccuracyHigh, shaderAccuracy == SD.ShaderAccuracy.High);
|
|
|
|
mat.SetBlendingMode(ShaderProperties.BlendSrcFactor, BlendingMode_SrcFactor[(int)blendingMode]);
|
|
mat.SetBlendingMode(ShaderProperties.BlendDstFactor, BlendingMode_DstFactor[(int)blendingMode]);
|
|
mat.SetZTest(ShaderProperties.ZTest, CompareFunction.LessEqual);
|
|
}
|
|
}
|
|
|
|
// STATIC PROPERTIES HD
|
|
public struct StaticPropertiesHD : IStaticProperties
|
|
{
|
|
public ShaderMode GetShaderMode() { return ShaderMode.HD; }
|
|
public static int staticPropertiesCount { get { return (int)BlendingMode.Count * (int)HD.Attenuation.Count * (int)Noise3D.Count * (int)ColorGradient.Count * (int)HD.Shadow.Count * (int)HD.Cookie.Count * Config.Instance.raymarchingQualitiesCount; } }
|
|
public int GetPropertiesCount() { return staticPropertiesCount; }
|
|
|
|
public BlendingMode blendingMode;
|
|
public HD.Attenuation attenuation;
|
|
public Noise3D noise3D;
|
|
public ColorGradient colorGradient;
|
|
public HD.Shadow shadow;
|
|
public HD.Cookie cookie;
|
|
public int raymarchingQualityIndex;
|
|
|
|
int blendingModeID { get { return (int)blendingMode; } }
|
|
int attenuationID { get { return (int)attenuation; } }
|
|
int noise3DID { get { return Config.Instance.featureEnabledNoise3D ? (int)noise3D : 0; } }
|
|
int colorGradientID { get { return Config.Instance.featureEnabledColorGradient != FeatureEnabledColorGradient.Off ? (int)colorGradient : 0; } }
|
|
int dynamicOcclusionID { get { return Config.Instance.featureEnabledShadow ? (int)shadow : 0; } }
|
|
int cookieID { get { return Config.Instance.featureEnabledCookie ? (int)cookie : 0; } }
|
|
int raymarchingQualityID { get { return raymarchingQualityIndex; } }
|
|
|
|
public int GetMaterialID()
|
|
{
|
|
return (((((((blendingModeID)
|
|
* (int)HD.Attenuation.Count + attenuationID)
|
|
* (int)Noise3D.Count + noise3DID)
|
|
* (int)ColorGradient.Count + colorGradientID)
|
|
* (int)HD.Shadow.Count + dynamicOcclusionID)
|
|
* (int)HD.Cookie.Count + cookieID)
|
|
* (int)Config.Instance.raymarchingQualitiesCount + raymarchingQualityID)
|
|
;
|
|
}
|
|
|
|
public void ApplyToMaterial(Material mat)
|
|
{
|
|
mat.SetKeywordEnabled(ShaderKeywords.AlphaAsBlack, BlendingMode_AlphaAsBlack[(int)blendingMode]);
|
|
mat.SetKeywordEnabled(ShaderKeywords.HD.AttenuationLinear, attenuation == HD.Attenuation.Linear);
|
|
mat.SetKeywordEnabled(ShaderKeywords.HD.AttenuationQuad, attenuation == HD.Attenuation.Quadratic);
|
|
mat.SetKeywordEnabled(ShaderKeywords.ColorGradientMatrixLow, colorGradient == ColorGradient.MatrixLow);
|
|
mat.SetKeywordEnabled(ShaderKeywords.ColorGradientMatrixHigh, colorGradient == ColorGradient.MatrixHigh);
|
|
mat.SetKeywordEnabled(ShaderKeywords.Noise3D, noise3D == Noise3D.On);
|
|
mat.SetKeywordEnabled(ShaderKeywords.HD.Shadow, shadow == HD.Shadow.On);
|
|
mat.SetKeywordEnabled(ShaderKeywords.HD.CookieSingleChannel, cookie == HD.Cookie.SingleChannel);
|
|
mat.SetKeywordEnabled(ShaderKeywords.HD.CookieRGBA, cookie == HD.Cookie.RGBA);
|
|
|
|
for (int i = 0; i < Config.Instance.raymarchingQualitiesCount; ++i)
|
|
mat.SetKeywordEnabled(ShaderKeywords.HD.GetRaymarchingQuality(i), raymarchingQualityIndex == i);
|
|
|
|
mat.SetBlendingMode(ShaderProperties.BlendSrcFactor, BlendingMode_SrcFactor[(int)blendingMode]);
|
|
mat.SetBlendingMode(ShaderProperties.BlendDstFactor, BlendingMode_DstFactor[(int)blendingMode]);
|
|
mat.SetZTest(ShaderProperties.ZTest, CompareFunction.Always);
|
|
}
|
|
}
|
|
|
|
public static Material NewMaterialPersistent(Shader shader, bool gpuInstanced)
|
|
{
|
|
if (!shader)
|
|
{
|
|
Debug.LogError("Invalid VLB Shader. Please try to reset the VLB Config asset or reinstall the plugin.");
|
|
return null;
|
|
}
|
|
|
|
var material = new Material(shader);
|
|
BatchingHelper.SetMaterialProperties(material, gpuInstanced);
|
|
return material;
|
|
}
|
|
|
|
class MaterialsGroup
|
|
{
|
|
public Material[] materials = null;
|
|
|
|
public MaterialsGroup(int count)
|
|
{
|
|
Debug.Assert(count > 0);
|
|
materials = new Material[count];
|
|
}
|
|
}
|
|
|
|
// SD Instanced Material Access
|
|
static Hashtable ms_MaterialsGroupSD = new Hashtable(1);
|
|
public static Material GetInstancedMaterial(uint groupID, ref StaticPropertiesSD staticProps)
|
|
{
|
|
IStaticProperties iStaticProp = staticProps;
|
|
return GetInstancedMaterial(ms_MaterialsGroupSD, groupID, ref iStaticProp);
|
|
}
|
|
|
|
// HD Instanced Material Access
|
|
static Hashtable ms_MaterialsGroupHD = new Hashtable(1);
|
|
public static Material GetInstancedMaterial(uint groupID, ref StaticPropertiesHD staticProps)
|
|
{
|
|
IStaticProperties iStaticProp = staticProps;
|
|
return GetInstancedMaterial(ms_MaterialsGroupHD, groupID, ref iStaticProp);
|
|
}
|
|
|
|
static Material GetInstancedMaterial(Hashtable groups, uint groupID, ref IStaticProperties staticProps) // pass StaticProperties by ref to avoid per value arg copy
|
|
{
|
|
MaterialsGroup group = (MaterialsGroup)groups[groupID];
|
|
if (group == null)
|
|
{
|
|
group = new MaterialsGroup(staticProps.GetPropertiesCount());
|
|
groups[groupID] = group;
|
|
}
|
|
|
|
int matID = staticProps.GetMaterialID();
|
|
Debug.Assert(matID < staticProps.GetPropertiesCount());
|
|
Debug.Assert(group.materials != null);
|
|
var mat = group.materials[matID];
|
|
if (mat == null)
|
|
{
|
|
mat = Config.Instance.NewMaterialTransient(staticProps.GetShaderMode(), gpuInstanced:true);
|
|
if(mat)
|
|
{
|
|
group.materials[matID] = mat;
|
|
staticProps.ApplyToMaterial(mat);
|
|
}
|
|
}
|
|
|
|
return mat;
|
|
}
|
|
|
|
// Material Utils
|
|
enum ZWrite { Off = 0, On = 1 }
|
|
static void SetBlendingMode(this Material mat, int nameID, BlendMode value) { mat.SetInt(nameID, (int)value); }
|
|
static void SetStencilRef(this Material mat, int nameID, int value) { mat.SetInt(nameID, value); }
|
|
static void SetStencilComp(this Material mat, int nameID, CompareFunction value) { mat.SetInt(nameID, (int)value); }
|
|
static void SetStencilOp(this Material mat, int nameID, StencilOp value) { mat.SetInt(nameID, (int)value); }
|
|
static void SetCull(this Material mat, int nameID, CullMode value) { mat.SetInt(nameID, (int)value); }
|
|
static void SetZWrite(this Material mat, int nameID, ZWrite value) { mat.SetInt(nameID, (int)value); }
|
|
static void SetZTest(this Material mat, int nameID, CompareFunction value) { mat.SetInt(nameID, (int)value); }
|
|
}
|
|
}
|