using UnityEngine; namespace Thousandto.Launcher.ExternalLibs { [ExecuteInEditMode] public class FuncellShaderScript : MonoBehaviour { #region//可视变量 [SerializeField, TooltipAttribute("高度雾正对光时的颜色")] private Color _heightFogSunColor = Color.white; private Color _heightFogSunColor_cache = Color.white; [SerializeField, TooltipAttribute("高度雾背光时的颜色")] private Color _heightFogColor = Color.blue; private Color _heightFogColor_cache = Color.blue; [SerializeField, TooltipAttribute("环境信息(x:高度Min,y:高度Max,z:近平面,w:远平面)")] private Vector4 _heightFogInfo = new Vector4(0f, 50f, 10f, 150f); private Vector4 _heightFogInfo_cache = Vector4.zero; [SerializeField, TooltipAttribute("玩家位置")] private Vector3 _playerPos = Vector3.zero; private Vector3 _playerPos_cache = Vector3.zero; [SerializeField, TooltipAttribute("玩家灯光的颜色,rgb表示光线颜色,其中a通道代表光线强度")] private Color _playerLightColor = Color.gray; private Color _playerLightColor_cache = Color.gray; [SerializeField, TooltipAttribute("是否使用玩家灯")] private bool _isUsePlayerLight = false; #endregion #region//其他内部变量 //数据是否被改变 private DirtyFlagCode _dataIsDirty = DirtyFlagCode.None; //存储玩家位置信息的内存块 private float[] _posBlock = null; #endregion #region//MonoBehaviour的方法 private void Awake() { if (_heightFogSunColorPropID <= 0) BuildPropertyID(); CacheShaderValue(); } // Use this for initialization private void Start() { //启动起来先刷新一下 _dataIsDirty = DirtyFlagCode.All; } // Update is called once per frame private void Update() { if (_heightFogSunColorPropID <= 0) { BuildPropertyID(); } RefreshPlayerPos(); RefreshShaderValue(); } private void OnDestroy() { ResetCacheShaderValue(); } //当在编辑器状态下,值改变就会重新刷 private void OnValidate() { if (_posBlock == null || _posBlock.Length < 3) { _posBlock = GonbestGMemory.AllocFloatBlock("PlayerPos", 3); } if (_posBlock != null && _posBlock.Length >= 3) { _posBlock[0] = _playerPos.x; _posBlock[1] = _playerPos.y; _posBlock[2] = _playerPos.z; } _dataIsDirty = DirtyFlagCode.All; } #endregion #region //私有方法 private void RefreshPlayerPos() { if (_isUsePlayerLight) { if (_posBlock == null || _posBlock.Length < 3) { _posBlock = GonbestGMemory.AllocFloatBlock("PlayerPos", 3); } if (_posBlock != null && _posBlock.Length >= 3) { if (Mathf.Abs(_playerPos.x - _posBlock[0]) > 0.001f || Mathf.Abs(_playerPos.y - _posBlock[1]) > 0.001f || Mathf.Abs(_playerPos.z - _posBlock[2]) > 0.001f) { _playerPos.x = _posBlock[0]; _playerPos.y = _posBlock[1]; _playerPos.z = _posBlock[2]; _dataIsDirty |= DirtyFlagCode.PlayerPos; } } } } //缓存原始的Shader值 private void CacheShaderValue() { _heightFogSunColor_cache = Shader.GetGlobalColor(_heightFogSunColorPropID); _heightFogColor_cache = Shader.GetGlobalColor(_heightFogColorPropID); _heightFogInfo_cache = Shader.GetGlobalVector(_heightFogInfoPropID); _playerPos_cache = Shader.GetGlobalVector(_playerPosPropID); _playerLightColor_cache = Shader.GetGlobalColor(_playerLightColorPropID); //_normalScale_cache = Shader.GetGlobalFloat(_normalScalePropID); } //恢复缓存的Shader值 private void ResetCacheShaderValue() { Shader.SetGlobalColor(_heightFogSunColorPropID, _heightFogSunColor_cache); Shader.SetGlobalColor(_heightFogColorPropID, _heightFogColor_cache); Shader.SetGlobalVector(_heightFogInfoPropID, _heightFogInfo_cache); Shader.SetGlobalVector(_playerPosPropID, _playerPos_cache); Shader.SetGlobalColor(_playerLightColorPropID, _playerLightColor_cache); } // 角度转换为方向的函数 private Vector4 AngleToForword(Vector3 angle) { return new Vector4(-Mathf.Cos(angle.x) * Mathf.Sin(angle.y), Mathf.Sin(angle.x), -Mathf.Cos(angle.x) * Mathf.Cos(angle.y), angle.z); } //刷新新的Shader值 private void RefreshShaderValue() { if (_dataIsDirty != DirtyFlagCode.None) { //高度雾向光的颜色 if (DirtyFlagCode.HeightFogSunColor == (_dataIsDirty & DirtyFlagCode.HeightFogSunColor)) { Shader.SetGlobalColor(_heightFogSunColorPropID, _heightFogSunColor); } //高度雾背光的颜色 if (DirtyFlagCode.HeightFogColor == (_dataIsDirty & DirtyFlagCode.HeightFogColor)) { Shader.SetGlobalColor(_heightFogColorPropID, _heightFogColor); } //环境信息 if (DirtyFlagCode.HeightFogInfo == (_dataIsDirty & DirtyFlagCode.HeightFogInfo)) { Shader.SetGlobalVector(_heightFogInfoPropID, _heightFogInfo); } //玩家信息 if (DirtyFlagCode.PlayerPos == (_dataIsDirty & DirtyFlagCode.PlayerPos)) { Shader.SetGlobalVector(_playerPosPropID, _playerPos); } //设置玩家颜色 if (DirtyFlagCode.PlayerLitColor == (_dataIsDirty & DirtyFlagCode.PlayerLitColor)) { Shader.SetGlobalColor(_playerLightColorPropID, _playerLightColor); } //是否使用角色光 if (DirtyFlagCode.UsePlayerLit == (_dataIsDirty & DirtyFlagCode.UsePlayerLit)) { if (_isUsePlayerLight) { Shader.DisableKeyword("_USE_PLAYER_SPOTLIGHT_OFF"); Shader.EnableKeyword("_USE_PLAYER_SPOTLIGHT_ON"); } else { Shader.DisableKeyword("_USE_PLAYER_SPOTLIGHT_ON"); Shader.EnableKeyword("_USE_PLAYER_SPOTLIGHT_OFF"); } } /* //法线设置 if (DirtyFlagCode.NormalScale == (_dataIsDirty & DirtyFlagCode.NormalScale)) { Shader.SetGlobalFloat(_normalScalePropID, _normalScale); }*/ _dataIsDirty = DirtyFlagCode.None; } } #endregion #region//静态方法以及变量 //Shader属性ID private static int _heightFogSunColorPropID = -1; private static int _heightFogColorPropID = -1; private static int _heightFogInfoPropID = -1; private static int _playerPosPropID = -1; private static int _normalScalePropID = -1; private static int _playerLightColorPropID; private static void BuildPropertyID() { _heightFogSunColorPropID = Shader.PropertyToID("_HeightFogSunColor"); _heightFogColorPropID = Shader.PropertyToID("_HeightFogColor"); _heightFogInfoPropID = Shader.PropertyToID("_HeightFogInfo"); _playerPosPropID = Shader.PropertyToID("_PlayerPos"); _playerLightColorPropID = Shader.PropertyToID("_PlayerLitColorAtten"); _normalScalePropID = Shader.PropertyToID("_NormalScale"); Debug.Log("BuildPropertyID Finished!!::"+ _heightFogSunColorPropID); } #endregion #region//子类 [System.Flags] private enum DirtyFlagCode { None = 0, HeightFogSunColor = 1, HeightFogColor = 2, HeightFogInfo = 4, PlayerPos = 8, PlayerLitColor = 16, UsePlayerLit = 32, All = 63, } #endregion } }