2025-01-25 04:38:09 +08:00

242 lines
8.8 KiB
C#

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
}
}