242 lines
8.8 KiB
C#
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
|
|||
|
}
|
|||
|
}
|