diff --git a/Tenebrissilva/Assets/_Project/Shader/Water/PlanarReflections.cs b/Tenebrissilva/Assets/_Project/Shader/Water/PlanarReflections.cs
new file mode 100644
index 0000000000000000000000000000000000000000..07391d61d2f2d84b9cede27596119af2f95f87bf
--- /dev/null
+++ b/Tenebrissilva/Assets/_Project/Shader/Water/PlanarReflections.cs
@@ -0,0 +1,288 @@
+using System;
+using UnityEngine.Experimental.Rendering;
+using UnityEngine.Serialization;
+using Unity.Mathematics;
+
+namespace UnityEngine.Rendering.Universal
+{
+    [ExecuteAlways]
+    public class PlanarReflections : MonoBehaviour
+    {
+        [Serializable]
+        public enum ResolutionMulltiplier
+        {
+            Full,
+            Half,
+            Third,
+            Quarter
+        }
+
+        [Serializable]
+        public class PlanarReflectionSettings
+        {
+            public ResolutionMulltiplier m_ResolutionMultiplier = ResolutionMulltiplier.Third;
+            public float m_ClipPlaneOffset = 0.07f;
+            public LayerMask m_ReflectLayers = -1;
+            public bool m_Shadows;
+        }
+
+        [SerializeField]
+        public PlanarReflectionSettings m_settings = new PlanarReflectionSettings();
+
+        public GameObject target;
+        [FormerlySerializedAs("camOffset")] public float m_planeOffset;
+
+        private static Camera _reflectionCamera;
+        private RenderTexture _reflectionTexture;
+        private readonly int _planarReflectionTextureId = Shader.PropertyToID("_PlanarReflectionTexture");
+
+        private int2 _oldReflectionTextureSize;
+
+        public static event Action<ScriptableRenderContext, Camera> BeginPlanarReflections;
+
+        private void OnEnable()
+        {
+            RenderPipelineManager.beginCameraRendering += ExecutePlanarReflections;
+        }
+
+        // Cleanup all the objects we possibly have created
+        private void OnDisable()
+        {
+            Cleanup();
+        }
+
+        private void OnDestroy()
+        {
+            Cleanup();
+        }
+
+        private void Cleanup()
+        {
+            RenderPipelineManager.beginCameraRendering -= ExecutePlanarReflections;
+
+            if(_reflectionCamera)
+            {
+                _reflectionCamera.targetTexture = null;
+                SafeDestroy(_reflectionCamera.gameObject);
+            }
+            if (_reflectionTexture)
+            {
+                RenderTexture.ReleaseTemporary(_reflectionTexture);
+            }
+        }
+
+        private static void SafeDestroy(Object obj)
+        {
+            if (Application.isEditor)
+            {
+                DestroyImmediate(obj);
+            }
+            else
+            {
+                Destroy(obj);
+            }
+        }
+
+        private void UpdateCamera(Camera src, Camera dest)
+        {
+            if (dest == null) return;
+
+            dest.CopyFrom(src);
+            dest.useOcclusionCulling = false;
+            if (dest.gameObject.TryGetComponent(out UniversalAdditionalCameraData camData))
+            {
+                camData.renderShadows = m_settings.m_Shadows; // turn off shadows for the reflection camera
+            }
+        }
+
+        private void UpdateReflectionCamera(Camera realCamera)
+        {
+            if (_reflectionCamera == null)
+                _reflectionCamera = CreateMirrorObjects();
+
+            // find out the reflection plane: position and normal in world space
+            Vector3 pos = Vector3.zero;
+            Vector3 normal = Vector3.up;
+            if (target != null)
+            {
+                pos = target.transform.position + Vector3.up * m_planeOffset;
+                normal = target.transform.up;
+            }
+
+            UpdateCamera(realCamera, _reflectionCamera);
+
+            // Render reflection
+            // Reflect camera around reflection plane
+            var d = -Vector3.Dot(normal, pos) - m_settings.m_ClipPlaneOffset;
+            var reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);
+
+            var reflection = Matrix4x4.identity;
+            reflection *= Matrix4x4.Scale(new Vector3(1, -1, 1));
+
+            CalculateReflectionMatrix(ref reflection, reflectionPlane);
+            var oldPosition = realCamera.transform.position - new Vector3(0, pos.y * 2, 0);
+            var newPosition = ReflectPosition(oldPosition);
+            _reflectionCamera.transform.forward = Vector3.Scale(realCamera.transform.forward, new Vector3(1, -1, 1));
+            _reflectionCamera.worldToCameraMatrix = realCamera.worldToCameraMatrix * reflection;
+
+            // Setup oblique projection matrix so that near plane is our reflection
+            // plane. This way we clip everything below/above it for free.
+            var clipPlane = CameraSpacePlane(_reflectionCamera, pos - Vector3.up * 0.1f, normal, 1.0f);
+            var projection = realCamera.CalculateObliqueMatrix(clipPlane);
+            _reflectionCamera.projectionMatrix = projection;
+            _reflectionCamera.cullingMask = m_settings.m_ReflectLayers; // never render water layer
+            _reflectionCamera.transform.position = newPosition;
+        }
+
+        // Calculates reflection matrix around the given plane
+        private static void CalculateReflectionMatrix(ref Matrix4x4 reflectionMat, Vector4 plane)
+        {
+            reflectionMat.m00 = (1F - 2F * plane[0] * plane[0]);
+            reflectionMat.m01 = (-2F * plane[0] * plane[1]);
+            reflectionMat.m02 = (-2F * plane[0] * plane[2]);
+            reflectionMat.m03 = (-2F * plane[3] * plane[0]);
+
+            reflectionMat.m10 = (-2F * plane[1] * plane[0]);
+            reflectionMat.m11 = (1F - 2F * plane[1] * plane[1]);
+            reflectionMat.m12 = (-2F * plane[1] * plane[2]);
+            reflectionMat.m13 = (-2F * plane[3] * plane[1]);
+
+            reflectionMat.m20 = (-2F * plane[2] * plane[0]);
+            reflectionMat.m21 = (-2F * plane[2] * plane[1]);
+            reflectionMat.m22 = (1F - 2F * plane[2] * plane[2]);
+            reflectionMat.m23 = (-2F * plane[3] * plane[2]);
+
+            reflectionMat.m30 = 0F;
+            reflectionMat.m31 = 0F;
+            reflectionMat.m32 = 0F;
+            reflectionMat.m33 = 1F;
+        }
+
+        private static Vector3 ReflectPosition(Vector3 pos)
+        {
+            var newPos = new Vector3(pos.x, -pos.y, pos.z);
+            return newPos;
+        }
+
+        private float GetScaleValue()
+        {
+            switch(m_settings.m_ResolutionMultiplier)
+            {
+                case ResolutionMulltiplier.Full:
+                    return 1f;
+                case ResolutionMulltiplier.Half:
+                    return 0.5f;
+                case ResolutionMulltiplier.Third:
+                    return 0.33f;
+                case ResolutionMulltiplier.Quarter:
+                    return 0.25f;
+                default:
+                    return 0.5f; // default to half res
+            }
+        }
+
+        // Compare two int2
+        private static bool Int2Compare(int2 a, int2 b)
+        {
+            return a.x == b.x && a.y == b.y;
+        }
+
+        // Given position/normal of the plane, calculates plane in camera space.
+        private Vector4 CameraSpacePlane(Camera cam, Vector3 pos, Vector3 normal, float sideSign)
+        {
+            var offsetPos = pos + normal * m_settings.m_ClipPlaneOffset;
+            var m = cam.worldToCameraMatrix;
+            var cameraPosition = m.MultiplyPoint(offsetPos);
+            var cameraNormal = m.MultiplyVector(normal).normalized * sideSign;
+            return new Vector4(cameraNormal.x, cameraNormal.y, cameraNormal.z, -Vector3.Dot(cameraPosition, cameraNormal));
+        }
+
+        private Camera CreateMirrorObjects()
+        {
+            var go = new GameObject("Planar Reflections",typeof(Camera));
+            var cameraData = go.AddComponent(typeof(UniversalAdditionalCameraData)) as UniversalAdditionalCameraData;
+
+            cameraData.requiresColorOption = CameraOverrideOption.Off;
+            cameraData.requiresDepthOption = CameraOverrideOption.Off;
+            cameraData.SetRenderer(1);
+
+            var t = transform;
+            var reflectionCamera = go.GetComponent<Camera>();
+            reflectionCamera.transform.SetPositionAndRotation(t.position, t.rotation);
+            reflectionCamera.depth = -10;
+            reflectionCamera.enabled = false;
+            go.hideFlags = HideFlags.HideAndDontSave;
+
+            return reflectionCamera;
+        }
+
+        private void PlanarReflectionTexture(Camera cam)
+        {
+            if (_reflectionTexture == null)
+            {
+                var res = ReflectionResolution(cam, UniversalRenderPipeline.asset.renderScale);
+                const bool useHdr10 = true;
+                const RenderTextureFormat hdrFormat = useHdr10 ? RenderTextureFormat.RGB111110Float : RenderTextureFormat.DefaultHDR;
+                _reflectionTexture = RenderTexture.GetTemporary(res.x, res.y, 16,
+                    GraphicsFormatUtility.GetGraphicsFormat(hdrFormat, true));
+            }
+            _reflectionCamera.targetTexture =  _reflectionTexture;
+        }
+
+        private int2 ReflectionResolution(Camera cam, float scale)
+        {
+            var x = (int)(cam.pixelWidth * scale * GetScaleValue());
+            var y = (int)(cam.pixelHeight * scale * GetScaleValue());
+            return new int2(x, y);
+        }
+
+        private void ExecutePlanarReflections(ScriptableRenderContext context, Camera camera)
+        {
+            // we dont want to render planar reflections in reflections or previews
+            if (camera.cameraType == CameraType.Reflection || camera.cameraType == CameraType.Preview)
+                return;
+
+            UpdateReflectionCamera(camera); // create reflected camera
+            PlanarReflectionTexture(camera); // create and assign RenderTexture
+
+            var data = new PlanarReflectionSettingData(); // save quality settings and lower them for the planar reflections
+            data.Set(); // set quality settings
+
+            BeginPlanarReflections?.Invoke(context, _reflectionCamera); // callback Action for PlanarReflection
+            UniversalRenderPipeline.RenderSingleCamera(context, _reflectionCamera); // render planar reflections
+
+            data.Restore(); // restore the quality settings
+            Shader.SetGlobalTexture(_planarReflectionTextureId, _reflectionTexture); // Assign texture to water shader
+        }
+
+        class PlanarReflectionSettingData
+        {
+            private readonly bool _fog;
+            private readonly int _maxLod;
+            private readonly float _lodBias;
+
+            public PlanarReflectionSettingData()
+            {
+                _fog = RenderSettings.fog;
+                _maxLod = QualitySettings.maximumLODLevel;
+                _lodBias = QualitySettings.lodBias;
+            }
+
+            public void Set()
+            {
+                GL.invertCulling = true;
+                RenderSettings.fog = false; // disable fog for now as it's incorrect with projection
+                QualitySettings.maximumLODLevel = 1;
+                QualitySettings.lodBias = _lodBias * 0.5f;
+            }
+
+            public void Restore()
+            {
+                GL.invertCulling = false;
+                RenderSettings.fog = _fog;
+                QualitySettings.maximumLODLevel = _maxLod;
+                QualitySettings.lodBias = _lodBias;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tenebrissilva/Assets/_Project/Shader/Water/PlanarReflections.cs.meta b/Tenebrissilva/Assets/_Project/Shader/Water/PlanarReflections.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..36665fe29ef5485d1bd38d2b1362d546e2feaf77
--- /dev/null
+++ b/Tenebrissilva/Assets/_Project/Shader/Water/PlanarReflections.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6c5c28dabe9cb3f46992afd36066224e
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: