[Bf-blender-cvs] [15182f09411] temp-image-buffer-rasterizer: Use a constant fragment adder per triangle.

Jeroen Bakker noreply at git.blender.org
Mon Feb 21 09:53:26 CET 2022


Commit: 15182f094115cb0f1942739ebd4451d56874671d
Author: Jeroen Bakker
Date:   Mon Feb 21 09:52:58 2022 +0100
Branches: temp-image-buffer-rasterizer
https://developer.blender.org/rB15182f094115cb0f1942739ebd4451d56874671d

Use a constant fragment adder per triangle.

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

M	source/blender/imbuf/IMB_rasterizer.hh

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

diff --git a/source/blender/imbuf/IMB_rasterizer.hh b/source/blender/imbuf/IMB_rasterizer.hh
index 42e9a3dd18c..bf9b682e060 100644
--- a/source/blender/imbuf/IMB_rasterizer.hh
+++ b/source/blender/imbuf/IMB_rasterizer.hh
@@ -89,7 +89,7 @@ template<
     /**
      * Data type per vertex generated by the vertex shader and transferred to the fragment shader.
      *
-     * The data type should implement the +=, =, -, / and * operator.
+     * The data type should implement the +=, +, =, -, / and * operator.
      */
     typename Inner>
 class VertexOutInterface {
@@ -122,6 +122,14 @@ class VertexOutInterface {
     return result;
   }
 
+  Self operator+(const Self &other) const
+  {
+    Self result;
+    result.coord = coord + other.coord;
+    result.data = data + other.data;
+    return result;
+  }
+
   Self operator/(const float divider) const
   {
     Self result;
@@ -135,7 +143,7 @@ class VertexOutInterface {
     Self result;
     result.coord = coord * multiplier;
     result.data = data * multiplier;
-    return *this;
+    return result;
   }
 };
 
@@ -177,15 +185,15 @@ template<typename FragmentInput> class Rasterline {
   /** Input data for the fragment shader on (start_x, y). */
   FragmentInput start_data;
   /** Delta to add to the start_input to create the data for the next fragment. */
-  FragmentInput delta_step;
+  FragmentInput fragment_add;
 
   Rasterline() = default;
   Rasterline(uint32_t y,
              uint32_t start_x,
              uint32_t end_x,
              FragmentInput start_data,
-             FragmentInput delta_step)
-      : y(y), start_x(start_x), end_x(end_x), start_data(start_data), delta_step(delta_step)
+             FragmentInput fragment_add)
+      : y(y), start_x(start_x), end_x(end_x), start_data(start_data), fragment_add(fragment_add)
   {
   }
 };
@@ -368,8 +376,14 @@ class Rasterizer {
     /* Change winding order to match the steepness of the edges. */
     if (right_add.coord[0] < left_add.coord[0]) {
       std::swap(left_add, right_add);
+      std::swap(left_target, right_target);
     }
 
+    /* Calculate the adder for each x pixel. This is constant for the whole triangle. It is
+     * calculated at the midline to reduce edge cases. */
+    const InterfaceInnerType fragment_add = calc_fragment_adder(
+        sorted_vertices, left, right, left_add, right_add, left_target);
+
     /* Perform a substep to make sure that the data of left and right match the data on the anchor
      * point (center of the pixel). */
     const float distance_to_minline_anchor_point = clamping_method.distance_to_scanline_anchor(
@@ -382,7 +396,7 @@ class Rasterizer {
     for (v = min_v; v < mid_v; v++) {
       if (v >= 0 && v < image_buffer_->y) {
         std::optional<RasterlineType> rasterline = clamped_rasterline(
-            v, left.coord[0], right.coord[0], left.data, right.data);
+            v, left.coord[0], right.coord[0], left.data, fragment_add);
         if (rasterline) {
           append(*rasterline);
         }
@@ -404,7 +418,6 @@ class Rasterizer {
     const float distance_to_midline_anchor_point = clamping_method.distance_to_scanline_anchor(
         sorted_vertices[1]->coord[1]);
     /* Use the x coordinate to identify which branch should be modified. */
-    // TODO when min_v and mid_v are on the same scanline....
     const float distance_to_left = abs(left.coord[0] - sorted_vertices[1]->coord[0]);
     const float distance_to_right = abs(right.coord[0] - sorted_vertices[1]->coord[0]);
     if (distance_to_left < distance_to_right) {
@@ -424,7 +437,7 @@ class Rasterizer {
     for (; v < max_v; v++) {
       if (v >= 0 && v < image_buffer_->y) {
         std::optional<RasterlineType> rasterline = clamped_rasterline(
-            v, left.coord[0], right.coord[0], left.data, right.data);
+            v, left.coord[0], right.coord[0], left.data, fragment_add);
         if (rasterline) {
           append(*rasterline);
         }
@@ -434,6 +447,45 @@ class Rasterizer {
     }
   }
 
+  /**
+   * Calculate the delta adder between two fragments.
+   *
+   * Fragment adder is constant and can be calculated once and reused for each rasterline of
+   * the same triangle. However the calculation requires a distance that might not be known at the
+   * first scanline that is added. Therefore this method uses the mid scanline as there is the max
+   * x_distance.
+   *
+   * \returns the adder that can be added the previous fragment data.
+   */
+  InterfaceInnerType calc_fragment_adder(const std::array<VertexOutputType *, 3> &sorted_vertices,
+                                         const VertexOutputType &left,
+                                         const VertexOutputType &right,
+                                         const VertexOutputType &left_add,
+                                         const VertexOutputType &right_add,
+                                         const VertexOutputType *left_target)
+  {
+    const float distance_min_to_mid = sorted_vertices[1]->coord[1] - sorted_vertices[0]->coord[1];
+    if (distance_min_to_mid == 0.0f) {
+      VertexOutputType *mid_left = (sorted_vertices[1]->coord[0] < sorted_vertices[0]->coord[0]) ?
+                                       sorted_vertices[1] :
+                                       sorted_vertices[0];
+      VertexOutputType *mid_right = (sorted_vertices[1]->coord[0] < sorted_vertices[0]->coord[0]) ?
+                                        sorted_vertices[0] :
+                                        sorted_vertices[1];
+      return (mid_right->data - mid_left->data) / (mid_right->coord[0] - mid_left->coord[0]);
+    }
+
+    if (left_target == sorted_vertices[1]) {
+      VertexOutputType mid_right = right + right_add * distance_min_to_mid;
+      return (mid_right.data - sorted_vertices[1]->data) /
+             (mid_right.coord[0] - sorted_vertices[1]->coord[0]);
+    }
+
+    VertexOutputType mid_left = left + left_add * distance_min_to_mid;
+    return (sorted_vertices[1]->data - mid_left.data) /
+           (sorted_vertices[1]->coord[0] - mid_left.coord[0]);
+  }
+
   VertexOutputType calc_vertex_output_data(const VertexOutputType &from,
                                            const VertexOutputType &to)
   {
@@ -493,7 +545,7 @@ class Rasterizer {
                                                    float start_x,
                                                    float end_x,
                                                    InterfaceInnerType start_data,
-                                                   InterfaceInnerType end_data)
+                                                   const InterfaceInnerType fragment_add)
   {
     BLI_assert(y >= 0 && y < image_buffer_->y);
 
@@ -511,7 +563,7 @@ class Rasterizer {
       return std::nullopt;
     }
 
-    FragmentInputType add_x = (end_data - start_data) / (end_x - start_x);
+    // FragmentInputType add_x = (end_data - start_data) / (end_x - start_x);
     /* Is created rasterline clamped and should be added to the statistics. */
     bool is_clamped = false;
 
@@ -523,7 +575,7 @@ class Rasterizer {
       start_xi = 0;
       is_clamped = true;
     }
-    start_data += add_x * delta_to_anchor;
+    start_data += fragment_add * delta_to_anchor;
 
     uint32_t end_xi = clamping_method.column_for(end_x);
     if (end_xi > image_buffer_->x) {
@@ -539,7 +591,7 @@ class Rasterizer {
     printf("%s y(%d) x(%d-%u)\n", __func__, y, start_xi, end_xi);
 #endif
 
-    return RasterlineType(y, (uint32_t)start_xi, end_xi, start_data, add_x);
+    return RasterlineType(y, (uint32_t)start_xi, end_xi, start_data, fragment_add);
   }
 
   void render_rasterline(const RasterlineType &rasterline)
@@ -553,7 +605,7 @@ class Rasterizer {
       fragment_shader_.fragment(data, &fragment_out);
       copy_v4_v4(pixel_ptr, &fragment_out[0]);
 
-      data += rasterline.delta_step;
+      data += rasterline.fragment_add;
     }
   }



More information about the Bf-blender-cvs mailing list