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.
 
 
 

521 lines
16 KiB

using UnityEngine;
using UnityEngine.UI;
/*not working on android*/
[ExecuteInEditMode]
public class FogVolumeDirectionalLight : MonoBehaviour
{
public FogVolume[] _TargetFogVolumes;
public Vector2 MiniaturePosition = new Vector2(110, 320);
public FogVolume _ProminentFogVolume = null;
// [HideInInspector]
public Material FogVolumeMaterial;
public float _CameraVerticalPosition = 500;
RenderTexture depthRT;
public enum Resolution
{
_256 = 256,
_512 = 512,
_1024 = 1024,
_2048 = 2048,
_4096 = 4096
};
public enum Antialiasing
{
_1 = 1,
_2 = 2,
_4 = 4,
_8 = 8
};
public Antialiasing _Antialiasing = Antialiasing._1;
public Resolution Size = Resolution._512;
// [Range(10, 300)]
// float CameraSize = 100;
//public bool ToggleKeyword = true;
// [HideInInspector]
public Camera ShadowCamera;
public enum ScaleMode
{
VolumeMaxAxis,
Manual
};
public float _FogVolumeShadowMapEdgeSoftness = 0.001f;
public ScaleMode _ScaleMode = ScaleMode.VolumeMaxAxis;
public LayerMask LayersToRender;
[HideInInspector]
public Shader outputDepth;
[HideInInspector]
public GameObject GOShadowCamera;
public bool CameraVisible;
public enum UpdateMode
{
OnStart,
Interleaved
};
Image _CanvasImage;
public UpdateMode _UpdateMode = UpdateMode.Interleaved;
public float Scale = 50;
[Range(0, 100)]
public int SkipFrames = 2;
// CanvasRenderer DebugCanvas;
public bool ShowMiniature = false;
GameObject _GO_Canvas, _GO_Image;
Canvas _Canvas;
public Material DebugViewMaterial;
GameObject Quad;
Vector3 FocusPosition;
FogVolumeData _FogVolumeData;
Camera _GameCamera;
public enum FocusMode
{
VolumeCenter,
GameCameraPosition,
GameObject
};
public Transform _GameObjectFocus;
public FocusMode _FocusMode = FocusMode.VolumeCenter;
Material quadMaterial = null;
public Material QuadMaterial
{
get
{
if (quadMaterial == null) { CreateMaterial(); }
return quadMaterial;
}
}
public Shader quadShader;
void OnEnable()
{
_GO_Canvas = GameObject.Find("FogVolume Debug Canvas");
if (!_GO_Canvas) _GO_Canvas = new GameObject("FogVolume Debug Canvas");
_GO_Image = GameObject.Find("FogVolume Image");
if (!_GO_Image)
{
_GO_Image = new GameObject("FogVolume Image");
_CanvasImage = _GO_Image.AddComponent<Image>();
_CanvasImage.material = DebugViewMaterial;
_CanvasImage.rectTransform.position = new Vector3(MiniaturePosition.x, MiniaturePosition.y, 0);
_CanvasImage.rectTransform.pivot = new Vector2(.5f, .5f);
_CanvasImage.rectTransform.anchorMax = new Vector2(0, 0);
_CanvasImage.rectTransform.anchorMin = new Vector2(0, 0);
_CanvasImage.rectTransform.localScale = new Vector3(2, 2, 2);
}
if (!_CanvasImage) _CanvasImage = _GO_Image.GetComponent<Image>();
_CanvasImage.material = DebugViewMaterial;
_GO_Image.transform.SetParent(_GO_Canvas.transform);
_GO_Canvas.AddComponent<CanvasScaler>();
_GO_Canvas.GetComponent<CanvasScaler>().scaleFactor = 1;
_GO_Canvas.GetComponent<CanvasScaler>().referencePixelsPerUnit = 100;
_Canvas = _GO_Canvas.GetComponent<Canvas>(); // ("Debug view canvas");
_GO_Canvas.hideFlags = HideFlags.HideInHierarchy;
// DebugCanvas = _GO_Canvas.AddComponent<CanvasRenderer>();
_GO_Canvas.layer = LayerMask.NameToLayer("UI");
_GO_Image.layer = LayerMask.NameToLayer("UI");
_Canvas.renderMode = RenderMode.ScreenSpaceOverlay;
Initialize();
if (_UpdateMode == UpdateMode.OnStart) { Render(); }
}
void CreateMaterial()
{
DestroyImmediate(quadMaterial);
quadShader = Shader.Find("Hidden/DepthMapQuad");
//
quadMaterial = new Material(quadShader);
quadMaterial.name = "Depth camera quad material";
quadMaterial.hideFlags = HideFlags.HideAndDontSave;
}
RenderTextureFormat rt_DepthFormat;
void Initialize()
{
CreateMaterial();
if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RGFloat))
rt_DepthFormat = RenderTextureFormat.RGFloat;
else
rt_DepthFormat = RenderTextureFormat.DefaultHDR;
GameObject FogVolumeDataGO = GameObject.Find("Fog Volume Data");
if (FogVolumeDataGO) _FogVolumeData = FogVolumeDataGO.GetComponent<FogVolumeData>();
else return;
_GameCamera = _FogVolumeData.GameCamera;
GOShadowCamera = GameObject.Find("FogVolumeShadowCamera");
if (!GOShadowCamera)
{
GOShadowCamera = new GameObject();
GOShadowCamera.name = "FogVolumeShadowCamera";
}
if (!GOShadowCamera) print("Shadow camera is lost");
else ShadowCamera = GOShadowCamera.GetComponent<Camera>();
if (!depthRT)
{
depthRT = new RenderTexture((int) Size, (int) Size, 16, rt_DepthFormat);
depthRT.antiAliasing = (int) _Antialiasing;
depthRT.filterMode = FilterMode.Bilinear;
depthRT.name = "FogVolumeShadowMap";
depthRT.wrapMode = TextureWrapMode.Clamp;
}
if (!ShadowCamera) ShadowCamera = GOShadowCamera.AddComponent<Camera>();
else ShadowCamera = GOShadowCamera.GetComponent<Camera>();
ShadowCamera.clearFlags = CameraClearFlags.Color;
ShadowCamera.backgroundColor = Color.black;
ShadowCamera.orthographic = true;
ShadowCamera.farClipPlane = 10000.0f;
ShadowCamera.enabled = false;
ShadowCamera.stereoTargetEye = StereoTargetEyeMask.None;
ShadowCamera.targetTexture = depthRT;
ShadowCamera.cullingMask &= ~(1 << LayerMask.NameToLayer("FogVolume"));
ShadowCamera.cullingMask &= ~(1 << LayerMask.NameToLayer("FogVolumeUniform"));
ShadowCamera.cullingMask &= ~(1 << LayerMask.NameToLayer("FogVolumeSurrogate"));
ShadowCamera.cullingMask &= ~(1 << LayerMask.NameToLayer("FogVolumeShadowCaster"));
//make it child
ShadowCamera.transform.parent = gameObject.transform;
Quad = GameObject.Find("Depth map background");
if (!Quad) Quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
Quad.name = "Depth map background";
Quad.GetComponent<MeshRenderer>().sharedMaterial = QuadMaterial;
Quad.transform.parent = ShadowCamera.transform;
//remnove the collider
DestroyImmediate(Quad.GetComponent<MeshCollider>());
Quad.hideFlags = HideFlags.HideInHierarchy;
}
void EnableVolumetricShadow(bool b)
{
if (_TargetFogVolumes == null) { return; }
if (_TargetFogVolumes.Length > 0)
{
float largestAxis = 0.0f;
int largestIndex = 0;
for (int FVindex = 0; FVindex < _TargetFogVolumes.Length; FVindex++)
{
var fogVolume = _TargetFogVolumes[FVindex];
if ((fogVolume != null) && (fogVolume._FogType == FogVolume.FogType.Textured))
{
if (fogVolume.enabled)
{
FogVolumeMaterial = fogVolume.FogMaterial;
FogVolumeMaterial.SetInt("_VolumetricShadowsEnabled", b ? 1 : 0);
}
float largest = _MaxOf(fogVolume.fogVolumeScale.x,
fogVolume.fogVolumeScale.y,
fogVolume.fogVolumeScale.z);
if (largest > largestAxis)
{
largestAxis = largest;
largestIndex = FVindex;
}
}
}
_ProminentFogVolume = _TargetFogVolumes[largestIndex];
}
}
void Update()
{
if (_CanvasImage.material != null) _CanvasImage.material = DebugViewMaterial;
if (!ShadowCamera) Initialize();
if (_TargetFogVolumes != null && _AtLeastOneFogVolumeInArray())
{
EnableVolumetricShadow(depthRT);
LayersToRender &= ~(1 << LayerMask.NameToLayer("FogVolume"));
LayersToRender &= ~(1 << LayerMask.NameToLayer("FogVolumeUniform"));
LayersToRender &= ~(1 << LayerMask.NameToLayer("FogVolumeSurrogate"));
LayersToRender &= ~(1 << LayerMask.NameToLayer("FogVolumeShadowCaster"));
ShadowCamera.cullingMask = LayersToRender;
Refresh();
//
//now, adjust camera size to make it see the whole volume
if (_ScaleMode == ScaleMode.VolumeMaxAxis)
{
if (_ProminentFogVolume != null)
{
ShadowCamera.orthographicSize =
_MaxOf(_ProminentFogVolume.fogVolumeScale.x,
_ProminentFogVolume.fogVolumeScale.y,
_ProminentFogVolume.fogVolumeScale.z) * .5f;
}
}
else ShadowCamera.orthographicSize = Scale;
// ShadowCamera.orthographicSize = CameraSize;
if (ShadowCamera.cullingMask != 0 &&
_ProminentFogVolume != null &&
_UpdateMode == UpdateMode.Interleaved)
{
if (FogVolumeUtilities.ExtensionMethods.TimeSnap(SkipFrames))
{
Render();
}
}
}
else
{
if (depthRT)
{
DestroyImmediate(depthRT);
DestroyImmediate(GOShadowCamera);
}
}
if (!ShowMiniature &&
_GO_Canvas.activeInHierarchy) _GO_Canvas.SetActive(ShowMiniature);
if (ShowMiniature && !_GO_Canvas.activeInHierarchy) _GO_Canvas.SetActive(ShowMiniature);
#if UNITY_EDITOR
if(ShowMiniature)
_CanvasImage.rectTransform.position = new Vector3(MiniaturePosition.x, MiniaturePosition.y, 0);
#endif
}
public void Refresh()
{
if (_TargetFogVolumes == null)
{
_ProminentFogVolume = null;
return;
}
for (int i = 0; i < _TargetFogVolumes.Length; i++)
{
var fogVolume = _TargetFogVolumes[i];
if ((fogVolume != null) &&
(fogVolume._FogType == FogVolume.FogType.Textured))
{
if (fogVolume.HasUpdatedBoxMesh)
{
float largestOfProminent = (_ProminentFogVolume != null)
? _MaxOf(_ProminentFogVolume.fogVolumeScale.x,
_ProminentFogVolume.fogVolumeScale.y,
_ProminentFogVolume.fogVolumeScale.z)
: 0.0f;
float largest = _MaxOf(fogVolume.fogVolumeScale.x,
fogVolume.fogVolumeScale.y,
fogVolume.fogVolumeScale.z);
if (largest > largestOfProminent) { _ProminentFogVolume = fogVolume; }
}
}
}
}
public void Render()
{
if (!depthRT)
{
Initialize();
}
if (depthRT.height != (int) Size)
{
DestroyImmediate(depthRT);
Initialize();
// Debug.Log("A tomar por culo la textura");
}
if ((int) _Antialiasing != depthRT.antiAliasing)
{
DestroyImmediate(depthRT);
Initialize();
}
if (!ShadowCamera)
{
Initialize();
}
switch (_FocusMode)
{
case FocusMode.GameCameraPosition:
FocusPosition = _GameCamera.transform.position;
break;
case FocusMode.VolumeCenter:
if (_ProminentFogVolume != null)
{
FocusPosition = _ProminentFogVolume.transform.position;
}
else
{
FocusPosition = Vector3.zero;
}
break;
case FocusMode.GameObject:
if (_GameObjectFocus) FocusPosition = _GameObjectFocus.transform.position;
break;
}
//move the camera to the target center
Vector3 VerticalTranslate = new Vector3(0,
0, /* _TargetFogVolume.fogVolumeScale.y / 2*/
FocusPosition.y - _CameraVerticalPosition);
ShadowCamera.transform.position = FocusPosition;
ShadowCamera.transform.Translate(VerticalTranslate, Space.Self);
Vector3 QuadScale = new Vector3(ShadowCamera.orthographicSize * 2,
ShadowCamera.orthographicSize * 2,
ShadowCamera.orthographicSize * 2);
Quad.transform.localScale = QuadScale;
//move it to the farclip
Quad.transform.position = ShadowCamera.transform.position;
Vector3 QuadTranslate = new Vector3(0, 0, ShadowCamera.farClipPlane - 50);
Quad.transform.Translate(QuadTranslate, Space.Self);
ShadowCamera.transform.rotation = Quaternion.LookRotation(transform.forward);
;
Shader.SetGlobalVector("_ShadowCameraPosition", ShadowCamera.transform.position);
Shader.SetGlobalMatrix("_ShadowCameraProjection", ShadowCamera.worldToCameraMatrix);
Shader.SetGlobalFloat("_ShadowCameraSize", ShadowCamera.orthographicSize);
Shader.SetGlobalVector("_ShadowLightDir", ShadowCamera.transform.forward);
//depthRT.DiscardContents();
quadShader.maximumLOD = 1;
Shader.SetGlobalFloat("_FogVolumeShadowMapEdgeSoftness",
20.0f / _FogVolumeShadowMapEdgeSoftness);
ShadowCamera.RenderWithShader(outputDepth, "RenderType");
quadShader.maximumLOD = 100;
Shader.SetGlobalTexture("_ShadowTexture", depthRT);
}
void OnDisable()
{
DestroyImmediate(depthRT);
if (_GO_Canvas) _GO_Canvas.SetActive(false);
// DestroyImmediate(_Canvas);
// DestroyImmediate(GOShadowCamera);
// if (FogVolumeMaterial)
// FogVolumeUtilities.Rendering.EnsureKeyword(FogVolumeMaterial, "VOLUMETRIC_SHADOWS", false);
// FogVolumeMaterial.SetInt("_VolumetricShadowsEnabled", 0);
EnableVolumetricShadow(false);
}
private void OnDestroy()
{
DestroyImmediate(GOShadowCamera);
// print("A la mierda!");
DestroyImmediate(_GO_Canvas);
DestroyImmediate(Quad);
}
private bool _AtLeastOneFogVolumeInArray()
{
if (_TargetFogVolumes != null)
{
for (int i = 0; i < _TargetFogVolumes.Length; i++)
{
if (_TargetFogVolumes[i] != null) { return true; }
}
}
return false;
}
public void AddAllFogVolumesToThisLight()
{
_ProminentFogVolume = null;
var fogVolumes = FindObjectsOfType<FogVolume>();
int validFogVolumeCount = 0;
for (int i = 0; i < fogVolumes.Length; i++)
{
if ((fogVolumes[i] != null) &&
(fogVolumes[i]._FogType == FogVolume.FogType.Textured)) { validFogVolumeCount++; }
}
_TargetFogVolumes = new FogVolume[validFogVolumeCount];
int k = 0;
for (var i = 0; i < fogVolumes.Length; i++)
{
var fogVolume = fogVolumes[i];
if ((fogVolume != null) && (fogVolume._FogType == FogVolume.FogType.Textured))
{
_TargetFogVolumes[k++] = fogVolumes[i];
}
}
}
public void RemoveAllFogVolumesFromThisLight()
{
_ProminentFogVolume = null;
_TargetFogVolumes = null;
}
private float _MaxOf(float _a, float _b) { return _a >= _b ? _a : _b; }
private float _MaxOf(float _a, float _b, float _c) { return _MaxOf(_MaxOf(_a, _b), _c); }
}