experiments with fresnel and shadergraph
[WindSway-HDRP.git] / Library / PackageCache / com.unity.render-pipelines.high-definition@4.10.0-preview / Runtime / Core / Utilities / GeometryUtils.cs
blob4b711619f6de3fcac91abb78dc1b4aac7aff8011
1 using System;
3 namespace UnityEngine.Experimental.Rendering
5 public struct Frustum
7 public Plane[] planes; // Left, right, top, bottom, near, far
8 public Vector3[] corners; // Positions of the 8 corners
10 // The frustum will be camera-relative if given a camera-relative VP matrix.
11 public static void Create(Frustum frustum, Matrix4x4 viewProjMatrix, bool depth_0_1, bool reverseZ)
13 GeometryUtility.CalculateFrustumPlanes(viewProjMatrix, frustum.planes);
15 float nd = -1.0f;
17 if (depth_0_1)
19 nd = 0.0f;
21 // See "Fast Extraction of Viewing Frustum Planes" by Gribb and Hartmann.
22 Vector3 f = new Vector3(viewProjMatrix.m20, viewProjMatrix.m21, viewProjMatrix.m22);
23 float s = (float)(1.0 / Math.Sqrt(f.sqrMagnitude));
24 Plane np = new Plane(s * f, s * viewProjMatrix.m23);
26 frustum.planes[4] = np;
29 if (reverseZ)
31 Plane tmp = frustum.planes[4];
32 frustum.planes[4] = frustum.planes[5];
33 frustum.planes[5] = tmp;
36 Matrix4x4 invViewProjMatrix = viewProjMatrix.inverse;
38 // Unproject 8 frustum points.
39 frustum.corners[0] = invViewProjMatrix.MultiplyPoint(new Vector3(-1, -1, 1));
40 frustum.corners[1] = invViewProjMatrix.MultiplyPoint(new Vector3(1, -1, 1));
41 frustum.corners[2] = invViewProjMatrix.MultiplyPoint(new Vector3(-1, 1, 1));
42 frustum.corners[3] = invViewProjMatrix.MultiplyPoint(new Vector3(1, 1, 1));
43 frustum.corners[4] = invViewProjMatrix.MultiplyPoint(new Vector3(-1, -1, nd));
44 frustum.corners[5] = invViewProjMatrix.MultiplyPoint(new Vector3(1, -1, nd));
45 frustum.corners[6] = invViewProjMatrix.MultiplyPoint(new Vector3(-1, 1, nd));
46 frustum.corners[7] = invViewProjMatrix.MultiplyPoint(new Vector3(1, 1, nd));
48 } // struct Frustum
50 [GenerateHLSL]
51 public struct OrientedBBox
53 // 3 x float4 = 48 bytes.
54 // TODO: pack the axes into 16-bit UNORM per channel, and consider a quaternionic representation.
55 public Vector3 right;
56 public float extentX;
57 public Vector3 up;
58 public float extentY;
59 public Vector3 center;
60 public float extentZ;
62 public Vector3 forward { get { return Vector3.Cross(up, right); } }
64 public OrientedBBox(Matrix4x4 trs)
66 Vector3 vecX = trs.GetColumn(0);
67 Vector3 vecY = trs.GetColumn(1);
68 Vector3 vecZ = trs.GetColumn(2);
70 center = trs.GetColumn(3);
71 right = vecX * (1.0f / vecX.magnitude);
72 up = vecY * (1.0f / vecY.magnitude);
74 extentX = 0.5f * vecX.magnitude;
75 extentY = 0.5f * vecY.magnitude;
76 extentZ = 0.5f * vecZ.magnitude;
78 } // struct OrientedBBox
80 public static class GeometryUtils
82 // Returns 'true' if the OBB intersects (or is inside) the frustum, 'false' otherwise.
83 public static bool Overlap(OrientedBBox obb, Frustum frustum, int numPlanes, int numCorners)
85 bool overlap = true;
87 // Test the OBB against frustum planes. Frustum planes are inward-facing.
88 // The OBB is outside if it's entirely behind one of the frustum planes.
89 // See "Real-Time Rendering", 3rd Edition, 16.10.2.
90 for (int i = 0; overlap && i < numPlanes; i++)
92 Vector3 n = frustum.planes[i].normal;
93 float d = frustum.planes[i].distance;
95 // Max projection of the half-diagonal onto the normal (always positive).
96 float maxHalfDiagProj = obb.extentX * Mathf.Abs(Vector3.Dot(n, obb.right))
97 + obb.extentY * Mathf.Abs(Vector3.Dot(n, obb.up))
98 + obb.extentZ * Mathf.Abs(Vector3.Dot(n, obb.forward));
100 // Positive distance -> center in front of the plane.
101 // Negative distance -> center behind the plane (outside).
102 float centerToPlaneDist = Vector3.Dot(n, obb.center) + d;
104 // outside = maxHalfDiagProj < -centerToPlaneDist
105 // outside = maxHalfDiagProj + centerToPlaneDist < 0
106 // overlap = overlap && !outside
107 overlap = overlap && (maxHalfDiagProj + centerToPlaneDist >= 0);
110 if (numCorners == 0) return overlap;
112 // Test the frustum corners against OBB planes. The OBB planes are outward-facing.
113 // The frustum is outside if all of its corners are entirely in front of one of the OBB planes.
114 // See "Correct Frustum Culling" by Inigo Quilez.
115 // We can exploit the symmetry of the box by only testing against 3 planes rather than 6.
116 Plane[] planes = new Plane[3];
118 planes[0].normal = obb.right;
119 planes[0].distance = obb.extentX;
120 planes[1].normal = obb.up;
121 planes[1].distance = obb.extentY;
122 planes[2].normal = obb.forward;
123 planes[2].distance = obb.extentZ;
125 for (int i = 0; overlap && i < 3; i++)
127 Plane plane = planes[i];
129 // We need a separate counter for the "box fully inside frustum" case.
130 bool outsidePos = true; // Positive normal
131 bool outsideNeg = true; // Reversed normal
133 // Merge 2 loops. Continue as long as all points are outside either plane.
134 for (int j = 0; j < numCorners; j++)
136 float proj = Vector3.Dot(plane.normal, frustum.corners[j] - obb.center);
137 outsidePos = outsidePos && (proj > plane.distance);
138 outsideNeg = outsideNeg && (-proj > plane.distance);
141 overlap = overlap && !(outsidePos || outsideNeg);
144 return overlap;
147 public static readonly Matrix4x4 FlipMatrixLHSRHS = Matrix4x4.Scale(new Vector3(1, 1, -1));
149 public static Vector4 Plane(Vector3 position, Vector3 normal)
151 var n = normal;
152 var d = -Vector3.Dot(n, position);
153 var plane = new Vector4(n.x, n.y, n.z, d);
154 return plane;
157 public static Vector4 CameraSpacePlane(Matrix4x4 worldToCamera, Vector3 pos, Vector3 normal, float sideSign = 1, float clipPlaneOffset = 0)
159 var offsetPos = pos + normal * clipPlaneOffset;
160 var cpos = worldToCamera.MultiplyPoint(offsetPos);
161 var cnormal = worldToCamera.MultiplyVector(normal).normalized * sideSign;
162 return new Vector4(cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos, cnormal));
165 public static Matrix4x4 CalculateWorldToCameraMatrixRHS(Vector3 position, Quaternion rotation)
167 return Matrix4x4.Scale(new Vector3(1, 1, -1)) * Matrix4x4.TRS(position, rotation, Vector3.one).inverse;
170 public static Matrix4x4 CalculateWorldToCameraMatrixRHS(Transform transform)
172 return Matrix4x4.Scale(new Vector3(1, 1, -1)) * transform.localToWorldMatrix.inverse;
175 public static Matrix4x4 CalculateObliqueMatrix(Matrix4x4 sourceProjection, Vector4 clipPlane)
177 var projection = sourceProjection;
178 var inversion = sourceProjection.inverse;
180 var cps = new Vector4(
181 Mathf.Sign(clipPlane.x),
182 Mathf.Sign(clipPlane.y),
183 1.0f,
184 1.0f);
185 var q = inversion * cps;
186 Vector4 M4 = new Vector4(projection[3], projection[7], projection[11], projection[15]);
188 var c = clipPlane * ((2.0f*Vector4.Dot(M4, q)) / Vector4.Dot(clipPlane, q));
190 projection[2] = c.x - M4.x;
191 projection[6] = c.y - M4.y;
192 projection[10] = c.z - M4.z;
193 projection[14] = c.w - M4.w;
195 return projection;
198 public static Matrix4x4 CalculateReflectionMatrix(Vector3 position, Vector3 normal)
200 return CalculateReflectionMatrix(Plane(position, normal.normalized));
203 public static Matrix4x4 CalculateReflectionMatrix(Vector4 plane)
205 var reflectionMat = new Matrix4x4();
207 reflectionMat.m00 = (1F - 2F * plane[0] * plane[0]);
208 reflectionMat.m01 = (-2F * plane[0] * plane[1]);
209 reflectionMat.m02 = (-2F * plane[0] * plane[2]);
210 reflectionMat.m03 = (-2F * plane[3] * plane[0]);
212 reflectionMat.m10 = (-2F * plane[1] * plane[0]);
213 reflectionMat.m11 = (1F - 2F * plane[1] * plane[1]);
214 reflectionMat.m12 = (-2F * plane[1] * plane[2]);
215 reflectionMat.m13 = (-2F * plane[3] * plane[1]);
217 reflectionMat.m20 = (-2F * plane[2] * plane[0]);
218 reflectionMat.m21 = (-2F * plane[2] * plane[1]);
219 reflectionMat.m22 = (1F - 2F * plane[2] * plane[2]);
220 reflectionMat.m23 = (-2F * plane[3] * plane[2]);
222 reflectionMat.m30 = 0F;
223 reflectionMat.m31 = 0F;
224 reflectionMat.m32 = 0F;
225 reflectionMat.m33 = 1F;
227 return reflectionMat;
230 public static Matrix4x4 GetWorldToCameraMatrixLHS(this Camera camera)
232 return FlipMatrixLHSRHS * camera.worldToCameraMatrix;
235 public static Matrix4x4 GetProjectionMatrixLHS(this Camera camera)
237 return camera.projectionMatrix * FlipMatrixLHSRHS;
240 public static bool IsProjectionMatrixOblique(Matrix4x4 projectionMatrix)
242 return projectionMatrix[2] != 0 || projectionMatrix[6] != 0;
245 public static Matrix4x4 CalculateProjectionMatrix(Camera camera)
247 if (camera.orthographic)
249 var h = camera.orthographicSize;
250 var w = camera.orthographicSize * camera.aspect;
251 return Matrix4x4.Ortho(-w, w, -h, h, camera.nearClipPlane, camera.farClipPlane);
253 else
254 #if UNITY_2019_1_OR_NEWER
255 return Matrix4x4.Perspective(camera.GetGateFittedFieldOfView(), camera.aspect, camera.nearClipPlane, camera.farClipPlane);
256 #else
257 return Matrix4x4.Perspective(camera.fieldOfView, camera.aspect, camera.nearClipPlane, camera.farClipPlane);
258 #endif
260 } // class GeometryUtils