using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using UnityEditor; using UnityEngine; namespace Light2D { /// /// 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. /// [ExecuteInEditMode] [RequireComponent(typeof (Camera))] public class LightingSystem : MonoBehaviour { /// /// Size of lighting pixel in Unity meters. Controls resoultion of lighting textures. /// Smaller value - better quality, but lower performance. /// public float LightPixelSize = 0.05f; /// /// 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. /// public float LightCameraSizeAdd = 3; /// /// Needed for off screen lights to work correctly. /// Used only when camera is in perspective mode. /// public float LightCameraFovAdd = 30; /// /// Enable/disable ambient lights. Disable it to improve performance if you not using ambient light. /// public bool EnableAmbientLight = true; /// /// LightSourcesBlurMaterial is applied to light sources texture if enabled. Disable to improve performance. /// public bool BlurLightSources = true; /// /// AmbientLightBlurMaterial is applied to ambient light texture if enabled. Disable to improve performance. /// public bool BlurAmbientLight = true; /// /// 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. /// public bool HDR = true; /// /// If true light obstacles will be rendered in 2x resolution and then downsampled to 1x. /// public bool LightObstaclesAntialiasing = true; /// /// Set it to distance from camera to plane with light obstacles. Used only when camera in perspective mode. /// public float LightObstaclesDistance = 10; /// /// Billinear for blurred lights, Point for pixelated lights. /// public FilterMode LightTexturesFilterMode = FilterMode.Bilinear; /// /// Normal mapping. Not supported on mobiles. /// public bool EnableNormalMapping = false; /// /// If true lighting won't be seen on contents of previous cameras. /// 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 _lightSpritesCache = new List(); 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()); } } [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(); } } private void OnEnable() { _instance = this; _camera = GetComponent(); } 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(); 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(); 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(); 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(); _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; } } } }