373 lines
11 KiB
C#
373 lines
11 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Thousandto.Launcher.ExternalLibs;
|
|
|
|
/// <summary>
|
|
/// 创建一个产生实时阴影贴图的脚本
|
|
/// </summary>
|
|
public class ShadowMapScript : MonoBehaviour
|
|
{
|
|
|
|
#region 常量定义
|
|
private const int CN_RESIZE_WIDTH = 1024;
|
|
private const int CN_RTSIZE_HEIGHT = 1024;
|
|
private const string DefaultShadowKeyWords = "_GONBEST_SHADOW_ON";
|
|
#endregion
|
|
|
|
#region 私有变量
|
|
//是否支持阴影
|
|
private bool _supportShadow = false;
|
|
//支持的阴影贴图模式
|
|
private RenderTextureFormat _texFormat = RenderTextureFormat.ARGB32;
|
|
//阴影贴图深度值
|
|
private int _texDepth = 0;
|
|
//阴影开关
|
|
private bool _isEnable = false;
|
|
|
|
//阴影摄像机
|
|
private Camera _shadowMapCamera = null;
|
|
//矩阵
|
|
private Matrix4x4 _shadowViewProj = Matrix4x4.zero;
|
|
|
|
//阴影贴图
|
|
private RenderTexture _shadownMap = null;
|
|
//阴影shader
|
|
private Shader _depthShader = null;
|
|
|
|
//摄像机裁剪层
|
|
[SerializeField]
|
|
private LayerMask _Cameralayer = 1 << 28;
|
|
|
|
//可接受阴影的render
|
|
[SerializeField]
|
|
private Renderer[] _shadowRenderers = null;
|
|
|
|
//阴影强度
|
|
[SerializeField]
|
|
private float _shadowStrength = 0.7f;
|
|
|
|
//阴影视口大小
|
|
[SerializeField]
|
|
private float _viewPortSize = 3;
|
|
|
|
//是否使用深度处理
|
|
[SerializeField]
|
|
private bool _useDepth = false;
|
|
//是否需要刷新
|
|
[SerializeField]
|
|
private bool _refresh = false;
|
|
#endregion
|
|
|
|
#region //重载MonoBehaviour的系统函数
|
|
// Use this for initialization
|
|
void Awake()
|
|
{
|
|
//1.初始化
|
|
ResetShadowShaderParam();
|
|
|
|
//2.判断是否支持阴影
|
|
CheckSupportShadow();
|
|
|
|
//3.刷新摄像机
|
|
RefreshCamera();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
EnableEx();
|
|
RefreshCamera();
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
DisableEx();
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
if (_refresh)
|
|
{
|
|
_refresh = false;
|
|
if (_shadowMapCamera != null)
|
|
{
|
|
if (_useDepth)
|
|
{
|
|
_depthShader = ShaderFactory.Find("Ares/SpecialEffect/MakeShadow_Depth");
|
|
if (_depthShader == null)
|
|
{
|
|
Debug.LogError("阴影不生效,因为没有找到Shader:Ares/SpecialEffect/MakeShadow_Depth");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_depthShader = ShaderFactory.Find("Ares/SpecialEffect/MakeShadow");
|
|
if (_depthShader == null)
|
|
{
|
|
Debug.LogError("阴影不生效,因为没有找到Shader:Ares/SpecialEffect/MakeShadow");
|
|
}
|
|
}
|
|
|
|
_shadowMapCamera.SetReplacementShader(_depthShader, "RenderType");
|
|
}
|
|
}
|
|
this.Render();
|
|
}
|
|
|
|
private void OnValidate()
|
|
{
|
|
RefreshCamera();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
ResetMaterial();
|
|
ReleaseRenderTexture();
|
|
if (_shadowMapCamera != null)
|
|
{
|
|
_shadowMapCamera.enabled = false;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
|
|
|
|
//刷新摄像机的值
|
|
private void RefreshCamera()
|
|
{
|
|
if (!_supportShadow)
|
|
return;
|
|
if (_shadowMapCamera == null)
|
|
{
|
|
_shadowMapCamera = gameObject.GetComponent<Camera>();
|
|
_shadowMapCamera.clearFlags = CameraClearFlags.Color;
|
|
_shadowMapCamera.backgroundColor = Color.black;
|
|
_shadowMapCamera.depth = -10f;
|
|
_shadowMapCamera.useOcclusionCulling = false;
|
|
_shadowMapCamera.orthographic = true;
|
|
_shadowMapCamera.enabled = true;
|
|
if (_useDepth)
|
|
{
|
|
_depthShader = ShaderFactory.Find("Ares/SpecialEffect/MakeShadow_Depth");
|
|
}
|
|
else
|
|
{
|
|
_depthShader = ShaderFactory.Find("Ares/SpecialEffect/MakeShadow");
|
|
}
|
|
|
|
if (_depthShader == null)
|
|
{
|
|
Debug.LogError("阴影不生效,因为没有找到Shader:Ares/SpecialEffect/MakeShadow");
|
|
}
|
|
_shadowMapCamera.SetReplacementShader(_depthShader, "RenderType");
|
|
;
|
|
}
|
|
if (_shadowMapCamera != null)
|
|
{
|
|
_shadowMapCamera.cullingMask = _Cameralayer;
|
|
_shadowMapCamera.orthographicSize = _viewPortSize;
|
|
}
|
|
}
|
|
|
|
//创建RenderTexture
|
|
private void CreateRenderTexture()
|
|
{
|
|
if (!_supportShadow)
|
|
return;
|
|
ReleaseRenderTexture();
|
|
if (!_useDepth) _texDepth = 0;
|
|
_shadownMap = RenderTexture.GetTemporary(CN_RESIZE_WIDTH, CN_RTSIZE_HEIGHT, _texDepth, _texFormat);
|
|
_shadownMap.name = "RenderTexture86";
|
|
_shadownMap.wrapMode = TextureWrapMode.Clamp;
|
|
if (_shadownMap.format != _texFormat)
|
|
{
|
|
_shadownMap.format = _texFormat;
|
|
}
|
|
_shadownMap.filterMode = FilterMode.Bilinear;
|
|
_shadownMap.antiAliasing = 1;
|
|
Graphics.Blit(Texture2D.blackTexture, _shadownMap);
|
|
_shadowMapCamera.targetTexture = _shadownMap;
|
|
_shadowMapCamera.RenderWithShader(_depthShader, "RenderType");
|
|
}
|
|
|
|
//释放RenderTexture
|
|
private void ReleaseRenderTexture()
|
|
{
|
|
if (_shadownMap != null)
|
|
{
|
|
RenderTexture.ReleaseTemporary(_shadownMap);
|
|
_shadownMap = null;
|
|
}
|
|
if (_shadowMapCamera != null)
|
|
_shadowMapCamera.targetTexture = null;
|
|
}
|
|
|
|
//判断是否支持阴影
|
|
private bool CheckSupportShadow()
|
|
{
|
|
|
|
_supportShadow = true;
|
|
|
|
if (_useDepth)
|
|
{
|
|
if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB32))
|
|
{
|
|
_texFormat = RenderTextureFormat.ARGB32;
|
|
}
|
|
else
|
|
{
|
|
_supportShadow = false;
|
|
Debug.LogError("阴影不生效,因为当前设备不支持RenderTexture的图片格式!");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RGB565))
|
|
{
|
|
_texFormat = RenderTextureFormat.RGB565;
|
|
}
|
|
else if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB4444))
|
|
{
|
|
_texFormat = RenderTextureFormat.ARGB4444;
|
|
}
|
|
else if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB1555))
|
|
{
|
|
_texFormat = RenderTextureFormat.ARGB1555;
|
|
}
|
|
else if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB32))
|
|
{
|
|
_texFormat = RenderTextureFormat.ARGB32;
|
|
}
|
|
else
|
|
{
|
|
_supportShadow = false;
|
|
Debug.LogError("阴影不生效,因为当前设备不支持RenderTexture的图片格式!");
|
|
}
|
|
}
|
|
return _supportShadow;
|
|
}
|
|
|
|
|
|
//实时获取阴影摄像机的数据,并为Shader所需传递参数
|
|
public void Render()
|
|
{
|
|
if (!_supportShadow)
|
|
return;
|
|
if (!_isEnable)
|
|
return;
|
|
if (_depthShader == null)
|
|
return;
|
|
if (_shadowMapCamera == null)
|
|
return;
|
|
|
|
Matrix4x4 proj = _shadowMapCamera.projectionMatrix;
|
|
Matrix4x4 view = _shadowMapCamera.worldToCameraMatrix;
|
|
|
|
proj = GL.GetGPUProjectionMatrix(_shadowMapCamera.projectionMatrix, true);
|
|
|
|
if (_shadowRenderers != null)
|
|
{
|
|
for (int i = 0; i < _shadowRenderers.Length; ++i)
|
|
{
|
|
var render = _shadowRenderers[i];
|
|
if (render != null && render.sharedMaterial != null)
|
|
{
|
|
render.sharedMaterial.SetMatrix("_MyWorld2ShadowProj", proj * view);
|
|
render.sharedMaterial.SetTexture("_MyShadowMap", _shadownMap);
|
|
render.sharedMaterial.SetFloat("_ShadowIntensity", _shadowStrength);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//开启阴影
|
|
private void EnableEx()
|
|
{
|
|
_isEnable = true;
|
|
if (!_supportShadow) return;
|
|
|
|
ResetShadowShaderParam();
|
|
|
|
if (_shadowMapCamera != null)
|
|
_shadowMapCamera.enabled = true;
|
|
|
|
CreateRenderTexture();
|
|
|
|
if (_shadowRenderers != null)
|
|
{
|
|
for (int i = 0; i < _shadowRenderers.Length; ++i)
|
|
{
|
|
var render = _shadowRenderers[i];
|
|
if (render != null && render.sharedMaterial != null)
|
|
{
|
|
//Debug.LogError("Eanble:"+ render.name);
|
|
render.sharedMaterial.EnableKeyword(DefaultShadowKeyWords);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//关闭阴影
|
|
private void DisableEx()
|
|
{
|
|
_isEnable = false;
|
|
if (!_supportShadow) return;
|
|
|
|
ResetShadowShaderParam();
|
|
|
|
if (_shadowMapCamera != null)
|
|
_shadowMapCamera.enabled = false;
|
|
|
|
ReleaseRenderTexture();
|
|
|
|
if (_shadowRenderers != null)
|
|
{
|
|
for (int i = 0; i < _shadowRenderers.Length; ++i)
|
|
{
|
|
var render = _shadowRenderers[i];
|
|
if (render != null && render.sharedMaterial != null)
|
|
{
|
|
//Debug.LogError("Disable:" + render.name);
|
|
render.sharedMaterial.DisableKeyword(DefaultShadowKeyWords);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//重置一下阴影的shader参数
|
|
private void ResetShadowShaderParam()
|
|
{
|
|
if (_shadowRenderers != null)
|
|
{
|
|
for (int i = 0; i < _shadowRenderers.Length; ++i)
|
|
{
|
|
var render = _shadowRenderers[i];
|
|
if (render != null && render.sharedMaterial != null)
|
|
{
|
|
render.sharedMaterial.SetTexture("_MyShadowMap", Texture2D.blackTexture);
|
|
render.sharedMaterial.SetFloat("_ShadowIntensity", 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//重置一下阴影的shader参数
|
|
private void ResetMaterial()
|
|
{
|
|
if (_shadowRenderers != null)
|
|
{
|
|
for (int i = 0; i < _shadowRenderers.Length; ++i)
|
|
{
|
|
var render = _shadowRenderers[i];
|
|
if (render != null && render.sharedMaterial != null)
|
|
{
|
|
render.sharedMaterial.shader = render.sharedMaterial.shader;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|