Skip to content

Commit 1c706d6

Browse files
author
SR
committed
first commit
1 parent 0a63e9d commit 1c706d6

File tree

240 files changed

+25337
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

240 files changed

+25337
-1
lines changed

Diff for: .idea/.idea.Unity-ReflectionCamera.dir/.idea/encodings.xml

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: .idea/.idea.Unity-ReflectionCamera.dir/.idea/indexLayout.xml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: .idea/.idea.Unity-ReflectionCamera.dir/.idea/projectSettingsUpdater.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: .idea/.idea.Unity-ReflectionCamera.dir/.idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: .idea/.idea.Unity-ReflectionCamera.dir/.idea/workspace.xml

+48
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: .idea/.idea.Unity-ReflectionCamera/.idea/encodings.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: .idea/.idea.Unity-ReflectionCamera/.idea/indexLayout.xml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: .idea/.idea.Unity-ReflectionCamera/.idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Assets/Core.meta

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Assets/Core/PlanarReflectionCamera.cs

+278
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
using System;
2+
using UnityEngine;
3+
using UnityEngine.PlayerLoop;
4+
using UnityEngine.Rendering;
5+
using UnityEngine.SceneManagement;
6+
7+
[ExecuteAlways]
8+
[RequireComponent(typeof(Renderer))]
9+
public class PlanarReflectionCamera : MonoBehaviour
10+
{
11+
private static readonly int ReflectionTex = Shader.PropertyToID("_ReflectionTex");
12+
private static readonly Matrix4x4 ScaleXMinusOne = Matrix4x4.Scale(new Vector3(-1, 1, 1));
13+
14+
private enum ReflectionNormal
15+
{
16+
Up,
17+
Down,
18+
Left,
19+
Right,
20+
Forward,
21+
Back
22+
}
23+
24+
[SerializeField]
25+
private Material _material;
26+
27+
[SerializeField]
28+
private ReflectionNormal _reflectionNormal = ReflectionNormal.Up;
29+
30+
[SerializeField]
31+
private LayerMask _reflectionMask = -1;
32+
33+
[SerializeField]
34+
private float _clipPlaneOffset = 0;
35+
36+
[SerializeField]
37+
[Range(0.01f, 1f)]
38+
private float _farScale = 1;
39+
40+
[SerializeField]
41+
[Range(0.01f, 1f)]
42+
private float _renderTextureScale = 1f;
43+
44+
[SerializeField]
45+
private bool _showHiddenCamera = false;
46+
47+
private Camera _reflectionCamera;
48+
private Renderer _renderer;
49+
50+
private int ScaledWidth => Mathf.Max(1, (int)(Screen.width * _renderTextureScale));
51+
52+
private int ScaledHeight => Mathf.Max(1, (int)(Screen.height * _renderTextureScale));
53+
54+
private bool HasReflectionCameraChanged => _reflectionCamera == null || _reflectionCamera.targetTexture == null;
55+
56+
private bool IsScreenSizeChanged => _reflectionCamera.targetTexture.width != ScaledWidth || _reflectionCamera.targetTexture.height != ScaledHeight;
57+
58+
private Vector3 ReflectionNormalVector
59+
{
60+
get
61+
{
62+
switch (_reflectionNormal)
63+
{
64+
case ReflectionNormal.Up:
65+
return -transform.up;//reversed
66+
67+
case ReflectionNormal.Down:
68+
return transform.up;//reversed
69+
70+
case ReflectionNormal.Left:
71+
return -transform.right;
72+
73+
case ReflectionNormal.Right:
74+
return transform.right;
75+
76+
case ReflectionNormal.Forward:
77+
return transform.forward;
78+
79+
case ReflectionNormal.Back:
80+
return -transform.forward;
81+
82+
default:
83+
throw new ArgumentOutOfRangeException();
84+
}
85+
}
86+
}
87+
88+
private void Reset()
89+
{
90+
if (_reflectionCamera != null)
91+
{
92+
DestroyImmediate(_reflectionCamera.gameObject);
93+
}
94+
95+
_renderer = GetComponent<Renderer>();
96+
_material = _renderer.sharedMaterial;
97+
}
98+
99+
private void Awake()
100+
{
101+
Init();
102+
}
103+
104+
private void OnValidate()
105+
{
106+
//reinitialize
107+
if (Application.isPlaying == false)
108+
{
109+
Init();
110+
}
111+
}
112+
113+
private void Init()
114+
{
115+
if (_reflectionCamera == null)
116+
{
117+
var cameraObject = new GameObject(nameof(PlanarReflectionCamera));
118+
cameraObject.transform.SetParent(transform);
119+
120+
_reflectionCamera = cameraObject.AddComponent<Camera>();
121+
_renderer = GetComponent<Renderer>();
122+
}
123+
124+
var oldRenderTexture = _reflectionCamera.targetTexture;
125+
var renderTexture = new RenderTexture(ScaledWidth, ScaledHeight, 16)
126+
{
127+
name = $"{nameof(PlanarReflectionCamera)}-{name}",
128+
useMipMap = false,
129+
autoGenerateMips = false,
130+
anisoLevel = 0,
131+
filterMode = FilterMode.Bilinear,
132+
wrapMode = TextureWrapMode.Repeat,
133+
};
134+
135+
_reflectionCamera.targetTexture = renderTexture;
136+
_reflectionCamera.gameObject.hideFlags = _showHiddenCamera ? HideFlags.NotEditable | HideFlags.DontSave : HideFlags.HideAndDontSave;
137+
138+
if (oldRenderTexture != null)
139+
{
140+
DestroyImmediate(oldRenderTexture);
141+
}
142+
143+
if (_material != null)
144+
{
145+
if (_material.HasProperty(ReflectionTex))
146+
{
147+
_material.SetTexture(ReflectionTex, _reflectionCamera.targetTexture);
148+
}
149+
else
150+
{
151+
Debug.LogError("Material does not have _ReflectionTex property. Please add it to the shader.");
152+
}
153+
}
154+
}
155+
156+
private void OnEnable()
157+
{
158+
RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
159+
RenderPipelineManager.endCameraRendering += OnEndCameraRendering;
160+
161+
#if UNITY_EDITOR
162+
UnityEditor.PrefabUtility.prefabInstanceUpdated += OnPrefabInstanceUpdated;
163+
UnityEditor.SceneManagement.EditorSceneManager.sceneSaved += OnEditorSceneManagerOnSceneSaved;
164+
#endif
165+
}
166+
167+
168+
private void OnDisable()
169+
{
170+
RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
171+
RenderPipelineManager.endCameraRendering -= OnEndCameraRendering;
172+
173+
#if UNITY_EDITOR
174+
UnityEditor.PrefabUtility.prefabInstanceUpdated -= OnPrefabInstanceUpdated;
175+
UnityEditor.SceneManagement.EditorSceneManager.sceneSaved -= OnEditorSceneManagerOnSceneSaved;
176+
#endif
177+
}
178+
179+
private void OnBeginCameraRendering(ScriptableRenderContext arg1, Camera cam)
180+
{
181+
if (_reflectionCamera == cam)
182+
GL.invertCulling = true;
183+
}
184+
185+
private void OnEndCameraRendering(ScriptableRenderContext arg1, Camera cam)
186+
{
187+
if (_reflectionCamera == cam)
188+
GL.invertCulling = false;
189+
}
190+
191+
private void OnEditorSceneManagerOnSceneSaved(Scene _)
192+
{
193+
Init();
194+
}
195+
196+
private void OnPrefabInstanceUpdated(GameObject _)
197+
{
198+
Init();
199+
}
200+
201+
private void LateUpdate()
202+
{
203+
//reinitialize if needed
204+
if (HasReflectionCameraChanged || IsScreenSizeChanged)
205+
{
206+
Init();
207+
}
208+
209+
UpdateReflection(Camera.main, _reflectionCamera);
210+
}
211+
212+
private void UpdateReflection(Camera main, Camera reflectionCamera)
213+
{
214+
if (main == null || reflectionCamera == null)
215+
{
216+
return;
217+
}
218+
219+
//copy camera settings
220+
reflectionCamera.clearFlags = main.clearFlags;
221+
reflectionCamera.backgroundColor = main.backgroundColor;
222+
reflectionCamera.cullingMask = main.cullingMask & _reflectionMask;
223+
reflectionCamera.orthographic = main.orthographic;
224+
reflectionCamera.fieldOfView = main.fieldOfView;
225+
reflectionCamera.aspect = main.aspect;
226+
reflectionCamera.orthographicSize = main.orthographicSize;
227+
reflectionCamera.nearClipPlane = main.nearClipPlane;
228+
reflectionCamera.farClipPlane = main.farClipPlane * _farScale;
229+
reflectionCamera.renderingPath = main.renderingPath;
230+
reflectionCamera.allowHDR = main.allowHDR;
231+
reflectionCamera.allowMSAA = main.allowMSAA;
232+
reflectionCamera.allowDynamicResolution = main.allowDynamicResolution;
233+
234+
Vector3 normal = ReflectionNormalVector;
235+
Vector3 pos = transform.position;
236+
float d = -Vector3.Dot(normal, pos);
237+
Vector4 reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);
238+
239+
Matrix4x4 reflection = Matrix4x4.zero;
240+
CalculateReflectionMatrix(ref reflection, reflectionPlane);
241+
242+
reflectionCamera.worldToCameraMatrix = ScaleXMinusOne * main.worldToCameraMatrix * reflection;
243+
Vector4 clipPlane = CameraSpacePlane(reflectionCamera, pos, normal, 1.0f);
244+
reflectionCamera.projectionMatrix = ScaleXMinusOne * main.CalculateObliqueMatrix(clipPlane);
245+
}
246+
247+
private Vector4 CameraSpacePlane(Camera cam, Vector3 pos, Vector3 normal, float sideSign)
248+
{
249+
Vector3 offsetPos = pos + normal * _clipPlaneOffset;
250+
Matrix4x4 m = cam.worldToCameraMatrix;
251+
Vector3 cpos = m.MultiplyPoint(offsetPos);
252+
Vector3 cnormal = -m.MultiplyVector(normal).normalized * sideSign;
253+
return new Vector4(cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos, cnormal));
254+
}
255+
256+
private static void CalculateReflectionMatrix(ref Matrix4x4 reflectionMat, Vector4 plane)
257+
{
258+
reflectionMat.m00 = (1F - 2F * plane[0] * plane[0]);
259+
reflectionMat.m01 = (-2F * plane[0] * plane[1]);
260+
reflectionMat.m02 = (-2F * plane[0] * plane[2]);
261+
reflectionMat.m03 = (-2F * plane[3] * plane[0]);
262+
263+
reflectionMat.m10 = (-2F * plane[1] * plane[0]);
264+
reflectionMat.m11 = (1F - 2F * plane[1] * plane[1]);
265+
reflectionMat.m12 = (-2F * plane[1] * plane[2]);
266+
reflectionMat.m13 = (-2F * plane[3] * plane[1]);
267+
268+
reflectionMat.m20 = (-2F * plane[2] * plane[0]);
269+
reflectionMat.m21 = (-2F * plane[2] * plane[1]);
270+
reflectionMat.m22 = (1F - 2F * plane[2] * plane[2]);
271+
reflectionMat.m23 = (-2F * plane[3] * plane[2]);
272+
273+
reflectionMat.m30 = 0F;
274+
reflectionMat.m31 = 0F;
275+
reflectionMat.m32 = 0F;
276+
reflectionMat.m33 = 1F;
277+
}
278+
}

0 commit comments

Comments
 (0)