Daniele Bartolini 10 месяцев назад
Родитель
Сommit
6b60b40cb9
2 измененных файлов с 40 добавлено и 0 удалено
  1. 33 0
      src/core/math/frustum.cpp
  2. 7 0
      src/core/math/frustum.inl

+ 33 - 0
src/core/math/frustum.cpp

@@ -3,6 +3,7 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include "core/error/error.inl"
 #include "core/math/frustum.inl"
 
 namespace crown
@@ -63,6 +64,38 @@ namespace frustum
 		plane3::normalize(f.planes[5]);
 	}
 
+	void split(Frustum *splits, u32 num, const Frustum &f, f32 weight, f32 overlap)
+	{
+		CE_ENSURE(num > 1);
+
+		// See: https://developer.download.nvidia.com/SDK/10.5/opengl/src/cascaded_shadow_maps/doc/cascaded_shadow_maps.pdf
+		const f32 ratio = fabs(f.planes[5].d / f.planes[4].d);
+		const f32 diff  = fabs(f.planes[5].d - f.planes[4].d);
+
+		splits[0].planes[0] = f.planes[0];
+		splits[0].planes[1] = f.planes[1];
+		splits[0].planes[2] = f.planes[2];
+		splits[0].planes[3] = f.planes[3];
+		splits[0].planes[4] = f.planes[4];
+
+		for (u32 i = 1; i < num; ++i) {
+			const f32 si = i / f32(num);
+
+			splits[i].planes[0]   = f.planes[0];
+			splits[i].planes[1]   = f.planes[1];
+			splits[i].planes[2]   = f.planes[2];
+			splits[i].planes[3]   = f.planes[3];
+			splits[i].planes[4].n = f.planes[4].n;
+			splits[i].planes[4].d = weight * (f.planes[4].d * fpow(ratio, si)) + (1 - weight) * (f.planes[4].d + diff * si);
+			splits[i].planes[5].n = f.planes[5].n;
+
+			splits[i - 1].planes[5].n = f.planes[5].n;
+			splits[i - 1].planes[5].d = -splits[i].planes[4].d * overlap;
+		}
+
+		splits[num - 1].planes[5] = f.planes[5];
+	}
+
 } // namespace frustum
 
 } // namespace crown

+ 7 - 0
src/core/math/frustum.inl

@@ -22,6 +22,13 @@ namespace frustum
 	/// Returns whether the frustum @a f contains the point @a p.
 	bool contains_point(const Frustum &f, const Vector3 &p);
 
+	/// Splits the frustum @a f into @a num sub-frustum @a splits.
+	/// @a weight controls splits distribution: 0 means evenly-spaced
+	/// splits; higher values push splits towards the original near plane.
+	/// @a overlap sets how much a given far plane should overlap the next
+	/// split's near plane.
+	void split(Frustum *splits, u32 num, const Frustum &f, f32 weight = 0.75f, f32 overlap = 1.005f);
+
 	/// Returns the @a vertices of the frustum @a f.
 	/// @note
 	/// 0 = Near bottom left