2D-Platformer/Assets/Plugins/Light2D/Scripts/LightingSystem.cs
2022-02-12 12:53:50 +02:00

773 lines
No EOL
32 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Light2D
{
/// <summary>
/// Main script for lights. Should be attached to camera.
/// Handles lighting operation like camera setup, shader setup, merging cameras output together, blurring and some others.
/// </summary>
[ExecuteInEditMode]
[RequireComponent(typeof (Camera))]
public class LightingSystem : MonoBehaviour
{
/// <summary>
/// Size of lighting pixel in Unity meters. Controls resoultion of lighting textures.
/// Smaller value - better quality, but lower performance.
/// </summary>
public float LightPixelSize = 0.05f;
/// <summary>
/// Needed for off screen lights to work correctly. Set that value to radius of largest light.
/// Used only when camera is in orthographic mode. Big values could cause a performance drop.
/// </summary>
public float LightCameraSizeAdd = 3;
/// <summary>
/// Needed for off screen lights to work correctly.
/// Used only when camera is in perspective mode.
/// </summary>
public float LightCameraFovAdd = 30;
/// <summary>
/// Enable/disable ambient lights. Disable it to improve performance if you not using ambient light.
/// </summary>
public bool EnableAmbientLight = true;
/// <summary>
/// LightSourcesBlurMaterial is applied to light sources texture if enabled. Disable to improve performance.
/// </summary>
public bool BlurLightSources = true;
/// <summary>
/// AmbientLightBlurMaterial is applied to ambient light texture if enabled. Disable to improve performance.
/// </summary>
public bool BlurAmbientLight = true;
/// <summary>
/// If true RGBHalf RenderTexture type will be used for light processing.
/// That could improve smoothness of lights. Will be turned off if device is not supports it.
/// </summary>
public bool HDR = true;
/// <summary>
/// If true light obstacles will be rendered in 2x resolution and then downsampled to 1x.
/// </summary>
public bool LightObstaclesAntialiasing = true;
/// <summary>
/// Set it to distance from camera to plane with light obstacles. Used only when camera in perspective mode.
/// </summary>
public float LightObstaclesDistance = 10;
/// <summary>
/// Billinear for blurred lights, Point for pixelated lights.
/// </summary>
public FilterMode LightTexturesFilterMode = FilterMode.Bilinear;
/// <summary>
/// Normal mapping. Not supported on mobiles.
/// </summary>
public bool EnableNormalMapping = false;
/// <summary>
/// If true lighting won't be seen on contents of previous cameras.
/// </summary>
public bool AffectOnlyThisCamera;
public Material AmbientLightComputeMaterial;
public Material LightOverlayMaterial;
public Material LightSourcesBlurMaterial;
public Material AmbientLightBlurMaterial;
public Camera LightCamera;
public int LightSourcesLayer;
public int AmbientLightLayer;
public int LightObstaclesLayer;
public LayerMask LightObstaclesReplacementShaderLayer;
private RenderTexture _ambientEmissionTexture;
private RenderTexture _ambientTexture;
private RenderTexture _prevAmbientTexture;
private RenderTexture _bluredLightTexture;
private RenderTexture _obstaclesUpsampledTexture;
private RenderTexture _lightSourcesTexture;
private RenderTexture _obstaclesTexture;
private RenderTexture _screenBlitTempTex;
private RenderTexture _normalMapBuffer;
private RenderTexture _singleLightSourceTexture;
private RenderTexture _renderTargetTexture;
private RenderTexture _oldActiveRenderTexture;
private Camera _camera;
private ObstacleCameraPostPorcessor _obstaclesPostProcessor;
private Point2 _extendedLightTextureSize;
private Point2 _smallLightTextureSize;
private Vector3 _oldPos;
private Vector3 _currPos;
private RenderTextureFormat _texFormat;
private int _aditionalAmbientLightCycles = 0;
private static LightingSystem _instance;
private Shader _normalMapRenderShader;
private Camera _normalMapCamera;
private List<LightSprite> _lightSpritesCache = new List<LightSprite>();
private Material _normalMappedLightMaterial;
private Material _lightCombiningMaterial;
private Material _alphaBlendedMaterial;
private bool _halfTexelOffest;
private Shader _lightBlockerReplacementShader;
#if LIGHT2D_2DTK
private tk2dCamera _tk2dCamera;
#endif
private float LightPixelsPerUnityMeter
{
get { return 1/LightPixelSize; }
}
public static LightingSystem Instance
{
get { return _instance != null ? _instance : (_instance = FindObjectOfType<LightingSystem>()); }
}
[ContextMenu("Create Camera")]
private void CreateCamera()
{
if (LightCamera == null)
{
var go = new GameObject("Ligt Camera",typeof(Camera));
go.transform.SetParent(transform,false);
LightCamera = go.GetComponent<Camera>();
}
}
private void OnEnable()
{
_instance = this;
_camera = GetComponent<Camera>();
}
private void Start()
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
Shader.SetGlobalTexture("_ObstacleTex", Texture2D.whiteTexture);
return;
}
#endif
if (LightCamera == null)
{
Debug.LogError(
"Lighting Camera in LightingSystem is null. Please, select Lighting Camera camera for lighting to work.");
enabled = false;
return;
}
if (LightOverlayMaterial == null)
{
Debug.LogError(
"LightOverlayMaterial in LightingSystem is null. Please, select LightOverlayMaterial camera for lighting to work.");
enabled = false;
return;
}
if (AffectOnlyThisCamera && _camera.targetTexture != null)
{
Debug.LogError("\"Affect Only This Camera\" will not work if camera.targetTexture is set.");
AffectOnlyThisCamera = false;
}
_camera = GetComponent<Camera>();
if (EnableNormalMapping && !_camera.orthographic)
{
Debug.LogError("Normal mapping is not supported with perspective camera.");
EnableNormalMapping = false;
}
if (!SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf))
HDR = false;
_texFormat = HDR ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32;
var lightPixelsPerUnityMeter = LightPixelsPerUnityMeter;
_halfTexelOffest = SystemInfo.graphicsDeviceVersion.StartsWith("Direct3D 9");
InitTK2D();
if (_camera.orthographic)
{
var rawCamHeight = (_camera.orthographicSize + LightCameraSizeAdd)*2f;
var rawCamWidth = (_camera.orthographicSize*_camera.aspect + LightCameraSizeAdd)*2f;
_extendedLightTextureSize = new Point2(
Mathf.RoundToInt(rawCamWidth*lightPixelsPerUnityMeter),
Mathf.RoundToInt(rawCamHeight*lightPixelsPerUnityMeter));
var rawSmallCamHeight = _camera.orthographicSize*2f*lightPixelsPerUnityMeter;
_smallLightTextureSize = new Point2(
Mathf.RoundToInt(rawSmallCamHeight*_camera.aspect),
Mathf.RoundToInt(rawSmallCamHeight));
}
else
{
{
var lightCamHalfFov = (_camera.fieldOfView + LightCameraFovAdd)*Mathf.Deg2Rad/2f;
var lightCamSize = Mathf.Tan(lightCamHalfFov)*LightObstaclesDistance*2;
//var gameCamHalfFov = _camera.fieldOfView*Mathf.Deg2Rad/2f;
var texHeight = Mathf.RoundToInt(lightCamSize/LightPixelSize);
var texWidth = texHeight*_camera.aspect;
_extendedLightTextureSize = Point2.Round(new Vector2(texWidth, texHeight));
}
{
var lightCamHalfFov = _camera.fieldOfView*Mathf.Deg2Rad/2f;
var lightCamSize = Mathf.Tan(lightCamHalfFov)*LightObstaclesDistance*2;
//LightCamera.orthographicSize = lightCamSize/2f;
var gameCamHalfFov = _camera.fieldOfView*Mathf.Deg2Rad/2f;
var gameCamSize = Mathf.Tan(gameCamHalfFov)*LightObstaclesDistance*2;
_camera.orthographicSize = gameCamSize/2f;
var texHeight = Mathf.RoundToInt(lightCamSize/LightPixelSize);
var texWidth = texHeight*_camera.aspect;
_smallLightTextureSize = Point2.Round(new Vector2(texWidth, texHeight));
}
}
if (_extendedLightTextureSize.x%2 != 0)
_extendedLightTextureSize.x++;
if (_extendedLightTextureSize.y%2 != 0)
_extendedLightTextureSize.y++;
if (_extendedLightTextureSize.x > 1024 || _extendedLightTextureSize.y > 1024 ||
_smallLightTextureSize.x > 1024 || _smallLightTextureSize.y > 1024)
{
Debug.LogError("LightPixelSize is too small. Turning off lighting system.");
enabled = false;
return;
}
if (_extendedLightTextureSize.x < 4 || _extendedLightTextureSize.y < 4 ||
_smallLightTextureSize.x < 4 || _smallLightTextureSize.y < 4)
{
Debug.LogError("LightPixelSize is too big. Turning off lighting system.");
enabled = false;
return;
}
_screenBlitTempTex = new RenderTexture((int)_camera.pixelWidth, (int)_camera.pixelHeight, 0, _texFormat);
_screenBlitTempTex.filterMode = FilterMode.Point;
LightCamera.orthographic = _camera.orthographic;
if (EnableNormalMapping)
{
_lightSourcesTexture = new RenderTexture((int)_camera.pixelWidth, (int)_camera.pixelHeight,
0, _texFormat);
_lightSourcesTexture.filterMode = FilterMode.Point;
}
else
{
_lightSourcesTexture = new RenderTexture(_smallLightTextureSize.x, _smallLightTextureSize.y,
0, _texFormat);
_lightSourcesTexture.filterMode = LightTexturesFilterMode;
}
_obstaclesTexture = new RenderTexture(_extendedLightTextureSize.x, _extendedLightTextureSize.y,
0, _texFormat);
_ambientTexture = new RenderTexture(_extendedLightTextureSize.x, _extendedLightTextureSize.y,
0, _texFormat);
_ambientTexture.filterMode = LightTexturesFilterMode;
var upsampledObstacleSize = _extendedLightTextureSize * (LightObstaclesAntialiasing ? 2 : 1);
_obstaclesUpsampledTexture = new RenderTexture(
upsampledObstacleSize.x, upsampledObstacleSize.y, 0, _texFormat);
if (AffectOnlyThisCamera)
{
_renderTargetTexture = new RenderTexture((int)_camera.pixelWidth, (int)_camera.pixelHeight, 0, RenderTextureFormat.ARGB32);
_renderTargetTexture.filterMode = FilterMode.Point;
}
_obstaclesPostProcessor = new ObstacleCameraPostPorcessor();
_lightBlockerReplacementShader = Shader.Find(@"Light2D/Internal/LightBlockerReplacementShader");
LoopAmbientLight(100);
}
private void OnRenderImage(RenderTexture src, RenderTexture dest)
{
#if UNITY_EDITOR
if (!Application.isPlaying || Util.IsSceneViewFocused)
{
Shader.SetGlobalTexture("_ObstacleTex", Texture2D.whiteTexture);
if (dest != null)
dest.DiscardContents();
Graphics.Blit(src, dest);
return;
}
#endif
Update2DTK();
UpdateCamera();
RenderObstacles();
SetupShaders();
RenderNormalBuffer();
RenderLightSources();
RenderLightSourcesBlur();
RenderAmbientLight();
RenderLightOverlay(src, dest);
}
void OnPreRender()
{
if (Application.isPlaying && AffectOnlyThisCamera)
{
_oldActiveRenderTexture = RenderTexture.active;
RenderTexture.active = _renderTargetTexture;
GL.Clear(true, true, new Color(0, 0, 0, 0));
}
}
void OnPostRender()
{
if (Application.isPlaying && AffectOnlyThisCamera)
{
RenderTexture.active = _oldActiveRenderTexture;
//if (_alphaBlendedMaterial == null)
// _alphaBlendedMaterial = new Material(Shader.Find("Unlit/Transparent"));
//_alphaBlendedMaterial.SetTexture("_MainTex", _screenBlitTempTex);
//Graphics.Blit(_screenBlitTempTex, _renderTargetTexture, _alphaBlendedMaterial);
}
}
void InitTK2D()
{
#if LIGHT2D_2DTK
_tk2dCamera = GetComponent<tk2dCamera>();
if (_tk2dCamera != null && _tk2dCamera.CameraSettings.projection == tk2dCameraSettings.ProjectionType.Orthographic)
{
_camera.orthographic = true;
_camera.orthographicSize = _tk2dCamera.ScreenExtents.yMax;
}
#endif
}
void Update2DTK()
{
#if LIGHT2D_2DTK
if (_tk2dCamera != null && _tk2dCamera.CameraSettings.projection == tk2dCameraSettings.ProjectionType.Orthographic)
{
_camera.orthographic = true;
_camera.orthographicSize = _tk2dCamera.ScreenExtents.yMax;
}
#endif
}
private void LateUpdate()
{
#if UNITY_EDITOR
if (!Application.isPlaying && LightCamera != null)
{
_camera = GetComponent<Camera>();
if (_camera != null)
{
InitTK2D();
LightCamera.orthographic = _camera.orthographic;
if (_camera.orthographic)
{
LightCamera.orthographicSize = _camera.orthographicSize + LightCameraSizeAdd;
}
else
{
LightCamera.fieldOfView = _camera.fieldOfView + LightCameraFovAdd;
}
}
}
if (!Application.isPlaying || Util.IsSceneViewFocused)
{
Shader.SetGlobalTexture("_ObstacleTex", Texture2D.whiteTexture);
return;
}
#endif
}
private void RenderObstacles()
{
ConfigLightCamera(true);
var oldColor = LightCamera.backgroundColor;
var oldClearFlags = LightCamera.clearFlags;
LightCamera.enabled = false;
LightCamera.targetTexture = _obstaclesUpsampledTexture;
//main
LightCamera.clearFlags = CameraClearFlags.SolidColor;
LightCamera.cullingMask = 1 << LightObstaclesLayer;
LightCamera.backgroundColor = new Color(1, 1, 1, 0);
_obstaclesPostProcessor.DrawMesh(LightCamera, LightObstaclesAntialiasing ? 2 : 1);
LightCamera.Render();
//replacement
LightCamera.clearFlags = CameraClearFlags.Nothing;
LightCamera.cullingMask = LightObstaclesReplacementShaderLayer;
LightCamera.RenderWithShader(_lightBlockerReplacementShader, "RenderType");
//LightCamera.Render();
//LightCamera.ResetReplacementShader();
LightCamera.targetTexture = null;
LightCamera.cullingMask = 0;
LightCamera.backgroundColor = oldColor;
LightCamera.clearFlags = oldClearFlags;
_obstaclesTexture.DiscardContents();
Graphics.Blit(_obstaclesUpsampledTexture, _obstaclesTexture);
}
private void SetupShaders()
{
var lightPixelsPerUnityMeter = LightPixelsPerUnityMeter;
if (HDR) Shader.EnableKeyword("HDR");
else Shader.DisableKeyword("HDR");
if (_camera.orthographic) Shader.DisableKeyword("PERSPECTIVE_CAMERA");
else Shader.EnableKeyword("PERSPECTIVE_CAMERA");
Shader.SetGlobalTexture("_ObstacleTex", _obstaclesTexture);
Shader.SetGlobalFloat("_PixelsPerBlock", lightPixelsPerUnityMeter);
Shader.SetGlobalVector("_ExtendedToSmallTextureScale", new Vector2(
_smallLightTextureSize.x / (float)_extendedLightTextureSize.x,
_smallLightTextureSize.y / (float)_extendedLightTextureSize.y));
Shader.SetGlobalVector("_PosOffset", LightObstaclesAntialiasing
? (EnableNormalMapping ? _obstaclesUpsampledTexture.texelSize * 0.75f : _obstaclesUpsampledTexture.texelSize * 0.25f)
: (EnableNormalMapping ? _obstaclesTexture.texelSize : _obstaclesTexture.texelSize * 0.5f));
}
private void RenderNormalBuffer()
{
if (!EnableNormalMapping)
return;
if (_normalMapBuffer == null)
{
_normalMapBuffer = new RenderTexture(
(int) _camera.pixelWidth, (int) _camera.pixelHeight, 0, RenderTextureFormat.ARGB32);
_normalMapBuffer.filterMode = FilterMode.Point;
}
if (_normalMapRenderShader == null)
_normalMapRenderShader = Shader.Find("Light2D/Internal/Normal Map Drawer");
if (_normalMapCamera == null)
{
var camObj = new GameObject();
camObj.name = "Normals Camera";
camObj.transform.parent = _camera.transform;
camObj.transform.localScale = Vector3.one;
camObj.transform.localPosition = Vector3.zero;
camObj.transform.localRotation = Quaternion.identity;
_normalMapCamera = camObj.AddComponent<Camera>();
_normalMapCamera.enabled = false;
}
_normalMapBuffer.DiscardContents();
_normalMapCamera.CopyFrom(_camera);
_normalMapCamera.transform.position = LightCamera.transform.position;
_normalMapCamera.clearFlags = CameraClearFlags.SolidColor;
_normalMapCamera.targetTexture = _normalMapBuffer;
_normalMapCamera.cullingMask = int.MaxValue;
_normalMapCamera.backgroundColor = new Color(0.5f, 0.5f, 0, 1);
_normalMapCamera.RenderWithShader(_normalMapRenderShader, "LightObstacle");
Shader.SetGlobalTexture("_NormalsBuffer", _normalMapBuffer);
Shader.EnableKeyword("NORMAL_MAPPED_LIGHTS");
}
private void RenderLightSources()
{
ConfigLightCamera(false);
if (EnableNormalMapping)
{
if(_singleLightSourceTexture == null)
{
_singleLightSourceTexture = new RenderTexture(
_smallLightTextureSize.x, _smallLightTextureSize.y, 0, _texFormat);
_singleLightSourceTexture.filterMode = LightTexturesFilterMode;
}
if (_normalMappedLightMaterial == null)
{
_normalMappedLightMaterial = new Material(Shader.Find("Light2D/Internal/Normal Mapped Light"));
_normalMappedLightMaterial.SetTexture("_MainTex", _singleLightSourceTexture);
}
if (_lightCombiningMaterial == null)
{
_lightCombiningMaterial = new Material(Shader.Find("Light2D/Internal/Light Blender"));
_lightCombiningMaterial.SetTexture("_MainTex", _singleLightSourceTexture);
}
var cameraPlanes = GeometryUtility.CalculateFrustumPlanes(_camera);
_lightSourcesTexture.DiscardContents();
var oldBackgroundColor = LightCamera.backgroundColor;
var oldRt = RenderTexture.active;
Graphics.SetRenderTarget(_lightSourcesTexture);
GL.Clear(false, true, oldBackgroundColor);
Graphics.SetRenderTarget(oldRt);
_lightSpritesCache.Clear();
foreach (var lightSprite in LightSprite.AllLightSprites)
{
if (lightSprite.RendererEnabled &&
GeometryUtility.TestPlanesAABB(cameraPlanes, lightSprite.Renderer.bounds))
{
_lightSpritesCache.Add(lightSprite);
}
}
var lightCamLocPos = LightCamera.transform.localPosition;
LightCamera.targetTexture = _singleLightSourceTexture;
LightCamera.cullingMask = 0;
LightCamera.backgroundColor = new Color(0, 0, 0, 0);
foreach (var lightSprite in _lightSpritesCache)
{
// HACK: won't work for unknown reason without that line
LightCamera.RenderWithShader(_normalMapRenderShader, "f84j");
Graphics.SetRenderTarget(_singleLightSourceTexture);
lightSprite.DrawLightingNow(lightCamLocPos);
Graphics.SetRenderTarget(_lightSourcesTexture);
lightSprite.DrawLightNormalsNow(_normalMappedLightMaterial);
}
Graphics.SetRenderTarget(oldRt);
LightCamera.cullingMask = 1 << LightSourcesLayer;
LightCamera.Render();
Graphics.Blit(_singleLightSourceTexture, _lightSourcesTexture, _lightCombiningMaterial);
LightCamera.targetTexture = null;
LightCamera.cullingMask = 0;
LightCamera.backgroundColor = oldBackgroundColor;
}
else
{
LightCamera.targetTexture = _lightSourcesTexture;
LightCamera.cullingMask = 1 << LightSourcesLayer;
//LightCamera.backgroundColor = new Color(0, 0, 0, 0);
LightCamera.Render();
LightCamera.targetTexture = null;
LightCamera.cullingMask = 0;
}
}
private void RenderLightSourcesBlur()
{
if (BlurLightSources && LightSourcesBlurMaterial != null)
{
UnityEngine.Profiling.Profiler.BeginSample("LightingSystem.OnRenderImage Bluring Light Sources");
if (_bluredLightTexture == null)
{
var w = _lightSourcesTexture.width == _smallLightTextureSize.x
? _lightSourcesTexture.width*2
: _lightSourcesTexture.width;
var h = _lightSourcesTexture.height == _smallLightTextureSize.y
? _lightSourcesTexture.height*2
: _lightSourcesTexture.height;
_bluredLightTexture = new RenderTexture(w, h, 0, _texFormat);
}
_bluredLightTexture.DiscardContents();
_lightSourcesTexture.filterMode = FilterMode.Bilinear;
LightSourcesBlurMaterial.mainTexture = _lightSourcesTexture;
Graphics.Blit(null, _bluredLightTexture, LightSourcesBlurMaterial);
if (LightTexturesFilterMode == FilterMode.Point)
{
_lightSourcesTexture.filterMode = FilterMode.Point;
_lightSourcesTexture.DiscardContents();
Graphics.Blit(_bluredLightTexture, _lightSourcesTexture);
}
UnityEngine.Profiling.Profiler.EndSample();
}
}
private void RenderAmbientLight()
{
if (!EnableAmbientLight || AmbientLightComputeMaterial == null)
return;
UnityEngine.Profiling.Profiler.BeginSample("LightingSystem.OnRenderImage Ambient Light");
ConfigLightCamera(true);
if (_ambientTexture == null)
{
_ambientTexture =
new RenderTexture(_extendedLightTextureSize.x, _extendedLightTextureSize.y, 0, _texFormat);
}
if (_prevAmbientTexture == null)
{
_prevAmbientTexture =
new RenderTexture(_extendedLightTextureSize.x, _extendedLightTextureSize.y, 0, _texFormat);
}
if (_ambientEmissionTexture == null)
{
_ambientEmissionTexture =
new RenderTexture(_extendedLightTextureSize.x, _extendedLightTextureSize.y, 0, _texFormat);
}
if (EnableAmbientLight)
{
var oldBackgroundColor = LightCamera.backgroundColor;
LightCamera.targetTexture = _ambientEmissionTexture;
LightCamera.cullingMask = 1 << AmbientLightLayer;
LightCamera.backgroundColor = new Color(0, 0, 0, 0);
LightCamera.Render();
LightCamera.targetTexture = null;
LightCamera.cullingMask = 0;
LightCamera.backgroundColor = oldBackgroundColor;
}
for (int i = 0; i < _aditionalAmbientLightCycles + 1; i++)
{
var tmp = _prevAmbientTexture;
_prevAmbientTexture = _ambientTexture;
_ambientTexture = tmp;
var texSize = new Vector2(_ambientTexture.width, _ambientTexture.height);
var posShift = ((Vector2) (_currPos - _oldPos)/LightPixelSize).Div(texSize);
_oldPos = _currPos;
AmbientLightComputeMaterial.SetTexture("_LightSourcesTex", _ambientEmissionTexture);
AmbientLightComputeMaterial.SetTexture("_MainTex", _prevAmbientTexture);
AmbientLightComputeMaterial.SetVector("_Shift", posShift);
_ambientTexture.DiscardContents();
Graphics.Blit(null, _ambientTexture, AmbientLightComputeMaterial);
if (BlurAmbientLight && AmbientLightBlurMaterial != null)
{
UnityEngine.Profiling.Profiler.BeginSample("LightingSystem.OnRenderImage Bluring Ambient Light");
_prevAmbientTexture.DiscardContents();
AmbientLightBlurMaterial.mainTexture = _ambientTexture;
Graphics.Blit(null, _prevAmbientTexture, AmbientLightBlurMaterial);
var tmpblur = _prevAmbientTexture;
_prevAmbientTexture = _ambientTexture;
_ambientTexture = tmpblur;
UnityEngine.Profiling.Profiler.EndSample();
}
}
_aditionalAmbientLightCycles = 0;
UnityEngine.Profiling.Profiler.EndSample();
}
private void RenderLightOverlay(RenderTexture src, RenderTexture dest)
{
UnityEngine.Profiling.Profiler.BeginSample("LightingSystem.OnRenderImage Light Overlay");
ConfigLightCamera(false);
Vector2 lightTexelSize = new Vector2(1f / _smallLightTextureSize.x, 1f / _smallLightTextureSize.y);
float lightPixelsPerUnityMeter = LightPixelsPerUnityMeter;
Vector2 worldOffset = Quaternion.Inverse(_camera.transform.rotation)*(LightCamera.transform.position - _camera.transform.position);
Vector2 offset = Vector2.Scale(lightTexelSize, -worldOffset*lightPixelsPerUnityMeter);
var lightSourcesTex = BlurLightSources && LightSourcesBlurMaterial != null && LightTexturesFilterMode != FilterMode.Point
? _bluredLightTexture
: _lightSourcesTexture;
float xDiff = _camera.aspect/LightCamera.aspect;
if (!_camera.orthographic)
{
var gameCamHalfFov = _camera.fieldOfView * Mathf.Deg2Rad / 2f;
var gameCamSize = Mathf.Tan(gameCamHalfFov) * LightObstaclesDistance * 2;
_camera.orthographicSize = gameCamSize / 2f;
}
float scaleY = _camera.orthographicSize/LightCamera.orthographicSize;
var scale = new Vector2(scaleY*xDiff, scaleY);
var oldAmbientFilterMode = _ambientTexture == null ? FilterMode.Point : _ambientTexture.filterMode;
LightOverlayMaterial.SetTexture("_AmbientLightTex", EnableAmbientLight ? _ambientTexture : null);
LightOverlayMaterial.SetTexture("_LightSourcesTex", lightSourcesTex);
LightOverlayMaterial.SetTexture("_GameTex", src);
LightOverlayMaterial.SetVector("_Offset", offset);
LightOverlayMaterial.SetVector("_Scale", scale);
if (_screenBlitTempTex == null || _screenBlitTempTex.width != src.width ||
_screenBlitTempTex.height != src.height)
{
if (_screenBlitTempTex != null)
_screenBlitTempTex.Release();
_screenBlitTempTex = new RenderTexture(src.width, src.height, 0, RenderTextureFormat.ARGB32);
_screenBlitTempTex.filterMode = FilterMode.Point;
}
_screenBlitTempTex.DiscardContents();
Graphics.Blit(null, _screenBlitTempTex, LightOverlayMaterial);
if (_ambientTexture != null)
_ambientTexture.filterMode = oldAmbientFilterMode;
if (!AffectOnlyThisCamera)
Graphics.Blit(_screenBlitTempTex, dest);
UnityEngine.Profiling.Profiler.EndSample();
}
private void UpdateCamera()
{
LightPixelSize = _camera.orthographicSize*2f/_smallLightTextureSize.y;
var lightPixelsPerUnityMeter = LightPixelsPerUnityMeter;
var mainPos = _camera.transform.position;
var camRot = _camera.transform.rotation;
var unrotMainPos = Quaternion.Inverse(camRot) * mainPos;
var gridPos = new Vector2(
Mathf.Round(unrotMainPos.x * lightPixelsPerUnityMeter) / lightPixelsPerUnityMeter,
Mathf.Round(unrotMainPos.y * lightPixelsPerUnityMeter) / lightPixelsPerUnityMeter);
Vector2 posDiff = gridPos - (Vector2)unrotMainPos;
var pos = camRot*posDiff + mainPos;
LightCamera.transform.position = pos;
_currPos = pos;
}
public void LoopAmbientLight(int cycles)
{
_aditionalAmbientLightCycles += cycles;
}
void ConfigLightCamera(bool extended)
{
if (extended)
{
LightCamera.orthographicSize =
_camera.orthographicSize*(_extendedLightTextureSize.y/(float)_smallLightTextureSize.y);// _extendedLightTextureSize.y/(2f*LightPixelsPerUnityMeter);
LightCamera.fieldOfView = _camera.fieldOfView + LightCameraFovAdd;
LightCamera.aspect = _extendedLightTextureSize.x/(float) _extendedLightTextureSize.y;
}
else
{
LightCamera.orthographicSize = _camera.orthographicSize;// _smallLightTextureSize.y / (2f * LightPixelsPerUnityMeter);
LightCamera.fieldOfView = _camera.fieldOfView;
LightCamera.aspect = _smallLightTextureSize.x / (float)_smallLightTextureSize.y;
}
}
}
}