[Bf-blender-cvs] [b82f7814c4f] master: Fix: Draw: Incorrect culling in the new Draw Manager

Miguel Pozo noreply at git.blender.org
Mon Jan 16 18:41:22 CET 2023


Commit: b82f7814c4f386c05215d7dc85d526fa10e2b4e1
Author: Miguel Pozo
Date:   Mon Jan 16 18:41:06 2023 +0100
Branches: master
https://developer.blender.org/rBb82f7814c4f386c05215d7dc85d526fa10e2b4e1

Fix: Draw:  Incorrect culling in the new Draw Manager

ViewCullingData::corners (vec4) was casted to a BoundingBox (vec3),  so the frustum corners were uploaded in the wrong format to the GPU.

Now the ViewCullingData::corners are used directly without casting, since the BoundBox API is not really needed.

Reviewed By: fclem

Differential Revision: https://developer.blender.org/D17008

===================================================================

M	source/blender/draw/intern/draw_view.cc
M	source/blender/draw/intern/draw_view.hh

===================================================================

diff --git a/source/blender/draw/intern/draw_view.cc b/source/blender/draw/intern/draw_view.cc
index 2e303aa9295..82f614f20f2 100644
--- a/source/blender/draw/intern/draw_view.cc
+++ b/source/blender/draw/intern/draw_view.cc
@@ -24,16 +24,14 @@ void View::sync(const float4x4 &view_mat, const float4x4 &win_mat, int view_id)
 
   is_inverted_ = (is_negative_m4(view_mat.ptr()) == is_negative_m4(win_mat.ptr()));
 
-  BoundBox &bound_box = *reinterpret_cast<BoundBox *>(&culling_[view_id].corners);
-  BoundSphere &bound_sphere = *reinterpret_cast<BoundSphere *>(&culling_[view_id].bound_sphere);
-  frustum_boundbox_calc(bound_box, view_id);
+  frustum_boundbox_calc(view_id);
   frustum_culling_planes_calc(view_id);
-  frustum_culling_sphere_calc(bound_box, bound_sphere, view_id);
+  frustum_culling_sphere_calc(view_id);
 
   dirty_ = true;
 }
 
-void View::frustum_boundbox_calc(BoundBox &bbox, int view_id)
+void View::frustum_boundbox_calc(int view_id)
 {
   /* Extract the 8 corners from a Projection Matrix. */
 #if 0 /* Equivalent to this but it has accuracy problems. */
@@ -43,16 +41,18 @@ void View::frustum_boundbox_calc(BoundBox &bbox, int view_id)
   }
 #endif
 
+  MutableSpan<float4> corners = {culling_[view_id].corners, ARRAY_SIZE(culling_[view_id].corners)};
+
   float left, right, bottom, top, near, far;
   bool is_persp = data_[view_id].winmat[3][3] == 0.0f;
 
   projmat_dimensions(data_[view_id].winmat.ptr(), &left, &right, &bottom, &top, &near, &far);
 
-  bbox.vec[0][2] = bbox.vec[3][2] = bbox.vec[7][2] = bbox.vec[4][2] = -near;
-  bbox.vec[0][0] = bbox.vec[3][0] = left;
-  bbox.vec[4][0] = bbox.vec[7][0] = right;
-  bbox.vec[0][1] = bbox.vec[4][1] = bottom;
-  bbox.vec[7][1] = bbox.vec[3][1] = top;
+  corners[0][2] = corners[3][2] = corners[7][2] = corners[4][2] = -near;
+  corners[0][0] = corners[3][0] = left;
+  corners[4][0] = corners[7][0] = right;
+  corners[0][1] = corners[4][1] = bottom;
+  corners[7][1] = corners[3][1] = top;
 
   /* Get the coordinates of the far plane. */
   if (is_persp) {
@@ -63,15 +63,16 @@ void View::frustum_boundbox_calc(BoundBox &bbox, int view_id)
     top *= sca_far;
   }
 
-  bbox.vec[1][2] = bbox.vec[2][2] = bbox.vec[6][2] = bbox.vec[5][2] = -far;
-  bbox.vec[1][0] = bbox.vec[2][0] = left;
-  bbox.vec[6][0] = bbox.vec[5][0] = right;
-  bbox.vec[1][1] = bbox.vec[5][1] = bottom;
-  bbox.vec[2][1] = bbox.vec[6][1] = top;
+  corners[1][2] = corners[2][2] = corners[6][2] = corners[5][2] = -far;
+  corners[1][0] = corners[2][0] = left;
+  corners[6][0] = corners[5][0] = right;
+  corners[1][1] = corners[5][1] = bottom;
+  corners[2][1] = corners[6][1] = top;
 
   /* Transform into world space. */
-  for (int i = 0; i < 8; i++) {
-    mul_m4_v3(data_[view_id].viewinv.ptr(), bbox.vec[i]);
+  for (float4 &corner : corners) {
+    mul_m4_v3(data_[view_id].viewinv.ptr(), corner);
+    corner.w = 1.0;
   }
 }
 
@@ -87,19 +88,22 @@ void View::frustum_culling_planes_calc(int view_id)
                       culling_[view_id].planes[2]);
 
   /* Normalize. */
-  for (int p = 0; p < 6; p++) {
-    culling_[view_id].planes[p].w /= normalize_v3(culling_[view_id].planes[p]);
+  for (float4 &plane : culling_[view_id].planes) {
+    plane.w /= normalize_v3(plane);
   }
 }
 
-void View::frustum_culling_sphere_calc(const BoundBox &bbox, BoundSphere &bsphere, int view_id)
+void View::frustum_culling_sphere_calc(int view_id)
 {
+  BoundSphere &bsphere = *reinterpret_cast<BoundSphere *>(&culling_[view_id].bound_sphere);
+  Span<float4> corners = {culling_[view_id].corners, ARRAY_SIZE(culling_[view_id].corners)};
+
   /* Extract Bounding Sphere */
   if (data_[view_id].winmat[3][3] != 0.0f) {
     /* Orthographic */
     /* The most extreme points on the near and far plane. (normalized device coords). */
-    const float *nearpoint = bbox.vec[0];
-    const float *farpoint = bbox.vec[6];
+    const float *nearpoint = corners[0];
+    const float *farpoint = corners[6];
 
     /* just use median point */
     mid_v3_v3v3(bsphere.center, farpoint, nearpoint);
@@ -113,12 +117,12 @@ void View::frustum_culling_sphere_calc(const BoundBox &bbox, BoundSphere &bspher
 
     /* center of each clipping plane */
     float mid_min[3], mid_max[3];
-    mid_v3_v3v3(mid_min, bbox.vec[3], bbox.vec[4]);
-    mid_v3_v3v3(mid_max, bbox.vec[2], bbox.vec[5]);
+    mid_v3_v3v3(mid_min, corners[3], corners[4]);
+    mid_v3_v3v3(mid_max, corners[2], corners[5]);
 
     /* square length of the diagonals of each clipping plane */
-    float a_sq = len_squared_v3v3(bbox.vec[3], bbox.vec[4]);
-    float b_sq = len_squared_v3v3(bbox.vec[2], bbox.vec[5]);
+    float a_sq = len_squared_v3v3(corners[3], corners[4]);
+    float b_sq = len_squared_v3v3(corners[2], corners[5]);
 
     /* distance squared between clipping planes */
     float h_sq = len_squared_v3v3(mid_min, mid_max);
@@ -132,7 +136,7 @@ void View::frustum_culling_sphere_calc(const BoundBox &bbox, BoundSphere &bspher
     interp_v3_v3v3(bsphere.center, mid_min, mid_max, fac);
 
     /* distance from the center to one of the points of the far plane (1, 2, 5, 6) */
-    bsphere.radius = len_v3v3(bsphere.center, bbox.vec[1]);
+    bsphere.radius = len_v3v3(bsphere.center, corners[1]);
   }
   else {
     /* Perspective with asymmetrical frustum. */
diff --git a/source/blender/draw/intern/draw_view.hh b/source/blender/draw/intern/draw_view.hh
index cded44e5a56..3a3191e2a62 100644
--- a/source/blender/draw/intern/draw_view.hh
+++ b/source/blender/draw/intern/draw_view.hh
@@ -139,9 +139,10 @@ class View {
 
   void update_viewport_size();
 
-  void frustum_boundbox_calc(BoundBox &bbox, int view_id);
+  /* WARNING: These 3 functions must be called in order */
+  void frustum_boundbox_calc(int view_id);
   void frustum_culling_planes_calc(int view_id);
-  void frustum_culling_sphere_calc(const BoundBox &bbox, BoundSphere &bsphere, int view_id);
+  void frustum_culling_sphere_calc(int view_id);
 };
 
 }  // namespace blender::draw



More information about the Bf-blender-cvs mailing list