[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