You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

261 lines
8.2 KiB

using UnityEngine;
using UnityEngine.Profiling;
[ExecuteInEditMode]
public class ShadowCamera : MonoBehaviour
{
Camera ThisCamera = null;
GameObject Dad = null;
FogVolume Fog = null;
public RenderTexture RT_Opacity, RT_OpacityBlur, RT_PostProcess;
public RenderTexture GetOpacityRT()
{
return RT_Opacity;
}
public RenderTexture GetOpacityBlurRT()
{
return RT_OpacityBlur;
}
[System.Serializable]
public enum TextureSize
{
_64 = 64,
_128 = 128,
_256 = 256,
_512 = 512,
_1024 = 1024
};
public TextureSize SetTextureSize
{
set
{
if (value != textureSize)
SetQuality(value);
}
get
{
return textureSize;
}
}
public TextureSize textureSize = TextureSize._128;
/// Blur iterations - larger number means more blur.
[Range(0, 10)]
public int iterations = 3;
/// Blur spread for each iteration. Lower values
/// give better looking blur, but require more iterations to
/// get large blurs. Value is usually between 0.5 and 1.0.
[Range(0.0f, 1)]
public float blurSpread = 0.6f;
public int Downsampling = 2;
void SetQuality(TextureSize value)
{
textureSize = value;
// print((int)textureSize);
}
Shader blurShader = null;
Shader PostProcessShader = null;
Material blurMaterial = null;
Material postProcessMaterial = null;
protected Material BlurMaterial
{
get
{
if (blurMaterial == null)
{
blurMaterial = new Material(blurShader);
blurMaterial.hideFlags = HideFlags.DontSave;
}
return blurMaterial;
}
}
protected Material PostProcessMaterial
{
get
{
if (postProcessMaterial == null)
{
postProcessMaterial = new Material(PostProcessShader);
postProcessMaterial.hideFlags = HideFlags.DontSave;
}
return postProcessMaterial;
}
}
protected void GetRT(ref RenderTexture rt, int size, string name)
{
// Release existing one
ReleaseRT(rt);
rt = RenderTexture.GetTemporary(size, size, 0, RenderTextureFormat.R8, RenderTextureReadWrite.Linear);
rt.filterMode = FilterMode.Bilinear;
rt.name = name;
rt.wrapMode = TextureWrapMode.Repeat;
}
public void ReleaseRT(RenderTexture rt)
{
if (rt != null)
{
RenderTexture.ReleaseTemporary(rt);
rt = null;
}
}
// Performs one blur iteration.
public void FourTapCone(RenderTexture source, RenderTexture dest, int iteration)
{
float off = 0.5f + iteration * blurSpread;
Graphics.BlitMultiTap(source, dest, BlurMaterial,
new Vector2(-off, -off),
new Vector2(-off, off),
new Vector2(off, off),
new Vector2(off, -off)
);
}
// Downsamples the texture to a quarter resolution.
private void DownSample(RenderTexture source, RenderTexture dest)
{
float off = 1.0f;
Graphics.BlitMultiTap(source, dest, BlurMaterial,
new Vector2(-off, -off),
new Vector2(-off, off),
new Vector2(off, off),
new Vector2(off, -off)
);
}
void Blur(RenderTexture Input, int BlurRTSize)
{
RenderTexture RT_OpacityBlur2 = null;
GetRT(ref RT_OpacityBlur, BlurRTSize, "Shadow blurred");
GetRT(ref RT_OpacityBlur2, BlurRTSize, "Shadow blurred");
// Copy source to the smaller texture.
DownSample(Input, RT_OpacityBlur);
//Graphics.Blit(Input, RT_OpacityBlur);
// Blur the small texture
for (int i = 0; i < iterations; i++)
{
FourTapCone(RT_OpacityBlur, RT_OpacityBlur2, i);
FogVolumeUtilities.ExtensionMethods.Swap(ref RT_OpacityBlur, ref RT_OpacityBlur2);
}
Shader.SetGlobalTexture("RT_OpacityBlur", RT_OpacityBlur);
Fog.RT_OpacityBlur = RT_OpacityBlur;
}
void RenderShadowMap()
{
//ideally, a cheaper version should be rendered here.
//So lets render a version with no lighting stuff
Profiler.BeginSample(Fog.name + " shadows");
Fog.FogVolumeShader.maximumLOD = 100;
SetQuality(textureSize);
GetRT(ref RT_Opacity, (int)textureSize, "Opacity");
ThisCamera.targetTexture = RT_Opacity;
// print(Fog.ShadowCameraSkippedFrames);
ThisCamera.Render();
Fog.RT_Opacity = RT_Opacity;
// Shader.SetGlobalTexture("RT_Opacity", RT_Opacity);
if (RT_Opacity != null)
{
GetRT(ref RT_PostProcess, (int)textureSize, "Shadow PostProcess");
PostProcessMaterial.SetFloat("ShadowColor", Fog.ShadowColor.a);
// PostProcessMaterial.SetFloat("_jitter", Fog._jitter);
Graphics.Blit(RT_Opacity, RT_PostProcess, PostProcessMaterial);
// ThisCamera.targetTexture = null;
Graphics.Blit(RT_PostProcess, RT_Opacity);
//RenderTexture.ReleaseTemporary(RT_Opacity);
if (iterations > 0)
{
Blur(RT_Opacity, (int)textureSize >> Downsampling);
}
else
{
Shader.SetGlobalTexture("RT_OpacityBlur", RT_Opacity);
Fog.RT_OpacityBlur = RT_Opacity;
}
Fog.RT_Opacity = RT_Opacity;
}
//Shader.SetGlobalTexture("RT_Opacity", RT_Opacity);
BlurMaterial.SetFloat("ShadowColor", Fog.ShadowColor.a);
// back to normal
Fog.FogVolumeShader.maximumLOD = 600;
Profiler.EndSample();
}
void ShaderLoad()
{
blurShader = Shader.Find("Hidden/Fog Volume/BlurEffectConeTap");
if (blurShader == null) print("Hidden / Fog Volume / BlurEffectConeTap #SHADER ERROR#");
PostProcessShader = Shader.Find("Hidden/Fog Volume/Shadow Postprocess");
if (PostProcessShader == null) print("Hidden/Fog Volume/Shadow Postprocess #SHADER ERROR#");
}
void OnEnable()
{
ShaderLoad();
Dad = transform.parent.gameObject;
Fog = Dad.GetComponent<FogVolume>();
ThisCamera = gameObject.GetComponent<Camera>();
ThisCamera.depthTextureMode = DepthTextureMode.Depth;
CameraTransform();
}
public void CameraTransform()
{
if (ThisCamera != null)
{
ThisCamera.orthographicSize = Dad.GetComponent<FogVolume>().fogVolumeScale.x / 2;
ThisCamera.transform.position = Dad.transform.position;
ThisCamera.farClipPlane = Fog.fogVolumeScale.y + Fog.shadowCameraPosition;
// print(ThisCamera.farClipPlane);
Vector3 VerticalTranslate = new Vector3(0, 0, Fog.fogVolumeScale.y / 2 - Fog.shadowCameraPosition);
// print(Fog.ShadowCameraPosition);
ThisCamera.transform.Translate(VerticalTranslate, Space.Self);
Quaternion target = Quaternion.Euler(90, 0, 0);
ThisCamera.transform.rotation = Dad.transform.rotation * target;
ThisCamera.enabled = false;
if (Fog.SunAttached)
{
Fog.Sun.transform.rotation = Dad.transform.rotation * target;
}
}
}
// Update is called once per frame
void Update()
{
// print(Fog.name + " visibility: " + Fog.IsVisible);
if (Fog.IsVisible && Fog.CastShadows)//3.1.7
{
if (FogVolumeUtilities.ExtensionMethods.TimeSnap(Fog.ShadowCameraSkippedFrames))
RenderShadowMap();
#if UNITY_EDITOR
CameraTransform();
#endif
}
}
void OnDisable()
{
RenderTexture.active = null;
ThisCamera.targetTexture = null;
if (RT_Opacity) DestroyImmediate(RT_Opacity);
if (RT_OpacityBlur) DestroyImmediate(RT_OpacityBlur);
if (RT_PostProcess) DestroyImmediate(RT_PostProcess);
if (blurMaterial) DestroyImmediate(blurMaterial);
if (postProcessMaterial) DestroyImmediate(postProcessMaterial);
}
}