[Bf-blender-cvs] [6d1eaf2d87e] temp-image-buffer-rasterizer: Check for quality.
Jeroen Bakker
noreply at git.blender.org
Mon Feb 21 13:42:36 CET 2022
Commit: 6d1eaf2d87e166af67a42207ecc0515c3321ccf3
Author: Jeroen Bakker
Date: Mon Feb 21 13:42:21 2022 +0100
Branches: temp-image-buffer-rasterizer
https://developer.blender.org/rB6d1eaf2d87e166af67a42207ecc0515c3321ccf3
Check for quality.
===================================================================
M source/blender/imbuf/IMB_rasterizer.hh
M source/blender/imbuf/intern/rasterizer_stats.hh
M source/blender/imbuf/intern/rasterizer_test.cc
===================================================================
diff --git a/source/blender/imbuf/IMB_rasterizer.hh b/source/blender/imbuf/IMB_rasterizer.hh
index bf9b682e060..aa51dab68df 100644
--- a/source/blender/imbuf/IMB_rasterizer.hh
+++ b/source/blender/imbuf/IMB_rasterizer.hh
@@ -349,11 +349,15 @@ class Rasterizer {
#endif
std::array<VertexOutputType *, 3> sorted_vertices = order_triangle_vertices(vertex_out);
- const int min_v = clamping_method.scanline_for(sorted_vertices[0]->coord[1]);
- const int mid_v =
- clamping_method.scanline_for(sorted_vertices[1]->coord[1]) -
- (clamping_method.distance_to_scanline_anchor(sorted_vertices[1]->coord[1]) == 0.5 ? 0 : 1);
- const int max_v = clamping_method.scanline_for(sorted_vertices[2]->coord[1]) - 1;
+ const int min_rasterline_y = clamping_method.scanline_for(sorted_vertices[0]->coord[1]);
+ const int mid_rasterline_y_correction = clamping_method.distance_to_scanline_anchor(
+ sorted_vertices[1]->coord[1]) == 0.0 ?
+ 0 :
+ 1;
+ const int mid_rasterline_y = max_ii(
+ clamping_method.scanline_for(sorted_vertices[1]->coord[1]) - mid_rasterline_y_correction,
+ min_rasterline_y);
+ const int max_rasterline_y = clamping_method.scanline_for(sorted_vertices[2]->coord[1]) - 1;
/* left and right branch. */
VertexOutputType left = *sorted_vertices[0];
@@ -370,8 +374,8 @@ class Rasterizer {
right_target = sorted_vertices[1];
}
- VertexOutputType left_add = calc_vertex_output_data(left, *left_target);
- VertexOutputType right_add = calc_vertex_output_data(right, *right_target);
+ VertexOutputType left_add = calc_branch_delta(left, *left_target);
+ VertexOutputType right_add = calc_branch_delta(right, *right_target);
/* Change winding order to match the steepness of the edges. */
if (right_add.coord[0] < left_add.coord[0]) {
@@ -381,22 +385,51 @@ class Rasterizer {
/* 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(
+ const InterfaceInnerType fragment_add = calc_fragment_delta(
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(
- sorted_vertices[0]->coord[1]);
- left += left_add * distance_to_minline_anchor_point;
- right += right_add * distance_to_minline_anchor_point;
-
- /* Add rasterlines from min_v to mid_v. */
- int v;
- for (v = min_v; v < mid_v; v++) {
- if (v >= 0 && v < image_buffer_->y) {
+ update_branches_to_min_anchor_line(*sorted_vertices[0], left, right, left_add, right_add);
+
+ /* Add rasterlines from min_rasterline_y to mid_rasterline_y. */
+ rasterize_loop(
+ min_rasterline_y, mid_rasterline_y, left, right, left_add, right_add, fragment_add);
+
+ /* Special case when mid vertex is on the same rasterline as the min vertex.
+ * In this case we need to split the right/left branches. Comparing the x coordinate to find
+ * the branch that should hold the mid vertex.
+ */
+ if (min_rasterline_y == mid_rasterline_y) {
+ update_branch_for_flat_bottom(*sorted_vertices[0], *sorted_vertices[1], left, right);
+ }
+
+ update_branches_at_mid_anchor_line(
+ *sorted_vertices[1], *sorted_vertices[2], left, right, left_add, right_add);
+
+ /* Add rasterlines from mid_rasterline_y to max_rasterline_y. */
+ rasterize_loop(
+ mid_rasterline_y, max_rasterline_y, left, right, left_add, right_add, fragment_add);
+ }
+
+ /**
+ * Rasterize multiple sequential lines.
+ *
+ * Create and buffer rasterlines between #from_y and #to_y.
+ * The #left and #right branches are incremented for each rasterline.
+ */
+ void rasterize_loop(int32_t from_y,
+ int32_t to_y,
+ VertexOutputType &left,
+ VertexOutputType &right,
+ const VertexOutputType &left_add,
+ const VertexOutputType &right_add,
+ const InterfaceInnerType &fragment_add)
+ {
+ for (int y = from_y; y < to_y; y++) {
+ if (y >= 0 && y < image_buffer_->y) {
std::optional<RasterlineType> rasterline = clamped_rasterline(
- v, left.coord[0], right.coord[0], left.data, fragment_add);
+ y, left.coord[0], right.coord[0], left.data, fragment_add);
if (rasterline) {
append(*rasterline);
}
@@ -404,60 +437,73 @@ class Rasterizer {
left += left_add;
right += right_add;
}
+ }
- if (min_v >= mid_v) {
- if (sorted_vertices[0]->coord[0] > sorted_vertices[1]->coord[0]) {
- left = *sorted_vertices[1];
- }
- else {
- right = *sorted_vertices[1];
- }
+ /**
+ * Update the left or right branch for when the mid vertex is on the same rasterline as the min
+ * vertex.
+ */
+ void update_branch_for_flat_bottom(const VertexOutputType &min_vertex,
+ const VertexOutputType &mid_vertex,
+ VertexOutputType &r_left,
+ VertexOutputType &r_right) const
+ {
+ if (min_vertex.coord[0] > mid_vertex.coord[0]) {
+ r_left = mid_vertex;
}
+ else {
+ r_right = mid_vertex;
+ }
+ }
+ void update_branches_to_min_anchor_line(const VertexOutputType &min_vertex,
+ VertexOutputType &r_left,
+ VertexOutputType &r_right,
+ const VertexOutputType &left_add,
+ const VertexOutputType &right_add)
+ {
+ const float distance_to_minline_anchor_point = clamping_method.distance_to_scanline_anchor(
+ min_vertex.coord[1]);
+ r_left += left_add * distance_to_minline_anchor_point;
+ r_right += right_add * distance_to_minline_anchor_point;
+ }
+
+ void update_branches_at_mid_anchor_line(const VertexOutputType &mid_vertex,
+ const VertexOutputType &max_vertex,
+ VertexOutputType &r_left,
+ VertexOutputType &r_right,
+ VertexOutputType &r_left_add,
+ VertexOutputType &r_right_add)
+ {
/* When both are the same we should the left/right branches are the same. */
const float distance_to_midline_anchor_point = clamping_method.distance_to_scanline_anchor(
- sorted_vertices[1]->coord[1]);
+ mid_vertex.coord[1]);
/* Use the x coordinate to identify which branch should be modified. */
- 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]);
+ const float distance_to_left = abs(r_left.coord[0] - mid_vertex.coord[0]);
+ const float distance_to_right = abs(r_right.coord[0] - mid_vertex.coord[0]);
if (distance_to_left < distance_to_right) {
- left = *sorted_vertices[1];
- left_target = sorted_vertices[2];
- left_add = calc_vertex_output_data(left, *left_target);
- left += left_add * distance_to_midline_anchor_point;
+ r_left = mid_vertex;
+ r_left_add = calc_branch_delta(r_left, max_vertex);
+ r_left += r_left_add * distance_to_midline_anchor_point;
}
else {
- right = *sorted_vertices[1];
- right_target = sorted_vertices[2];
- right_add = calc_vertex_output_data(right, *right_target);
- right += right_add * distance_to_midline_anchor_point;
- }
-
- /* Add rasterlines from mid_v to max_v. */
- 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, fragment_add);
- if (rasterline) {
- append(*rasterline);
- }
- }
- left += left_add;
- right += right_add;
+ r_right = mid_vertex;
+ r_right_add = calc_branch_delta(r_right, max_vertex);
+ r_right += r_right_add * distance_to_midline_anchor_point;
}
}
/**
- * Calculate the delta adder between two fragments.
+ * Calculate the delta adder between two sequential fragments in the x-direction.
*
* 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.
+ * 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,
+ InterfaceInnerType calc_fragment_delta(const std::array<VertexOutputType *, 3> &sorted_vertices,
const VertexOutputType &left,
const VertexOutputType &right,
const VertexOutputType &left_add,
@@ -486,14 +532,14 @@ class Rasterizer {
(sorted_vertices[1]->coord[0] - mid_left.coord[0]);
}
- VertexOutputType calc_vertex_output_data(const VertexOutputType &from,
- const VertexOutputType &to)
+ /**
+ * Calculate the delta adder between two rasterlines for the given edge.
+ */
+ VertexOutputType calc_branc
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list