aboutsummaryrefslogtreecommitdiff
path: root/src/renderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer.cpp')
-rw-r--r--src/renderer.cpp178
1 files changed, 78 insertions, 100 deletions
diff --git a/src/renderer.cpp b/src/renderer.cpp
index 7a32807..1fa8799 100644
--- a/src/renderer.cpp
+++ b/src/renderer.cpp
@@ -6,8 +6,8 @@
#include "math/vector.h"
#include "o3d/vertex.h"
#include "o3d/deriv_vertex.h"
-#include "o3d/tri_vertex.h"
-#include "o3d/tri_deriv_vertex.h"
+#include "o3d/tri.h"
+#include "o3d/tri_deriv.h"
#include "o3d/vertex_data.h"
using namespace engine;
@@ -34,127 +34,105 @@ void Renderer::clear() {
fb->clear();
}
-void Renderer::_draw_cropped_triangle(o3d::TriangleVertex4 root, o3d::TriangleDerivedVertex4 triangle) {
- std::array<o3d::DerivedVertex4*, 3> sorted_vs = { &triangle.derived_vertex1, &triangle.derived_vertex2, &triangle.derived_vertex3 };
+enum TriangleSide { top, bottom };
-#define SWAP_IF_LT(X,Y) ({ \
- if (sorted_vs[X]->point.y < sorted_vs[Y]->point.y) { \
- auto temp = sorted_vs[X]; \
- sorted_vs[X] = sorted_vs[Y]; \
- sorted_vs[Y] = temp; \
- } \
- })
- SWAP_IF_LT(1, 0);
- SWAP_IF_LT(2, 1);
- SWAP_IF_LT(1, 0);
-#undef SWAP_IF_LT
+void Renderer::_draw_cropped_triangle(const o3d::Triangle& root, const o3d::TriangleDerived& triangle) {
+ std::array<const o3d::DerivedVertex*, 3> sorted_vs = { &triangle.derived_vertex1, &triangle.derived_vertex2, &triangle.derived_vertex3 };
+
+ {
+ const auto swap_if_lt = [&](auto x, auto y) {
+ if (sorted_vs[x]->vertex.y < sorted_vs[y]->vertex.y) {
+ auto temp = sorted_vs[x];
+ sorted_vs[x] = sorted_vs[y];
+ sorted_vs[y] = temp;
+ }
+ };
+
+ swap_if_lt(1, 0);
+ swap_if_lt(2, 1);
+ swap_if_lt(1, 0);
+ }
auto middle_vl = *sorted_vs[1];
- const float fac = (sorted_vs[1]->point.y - sorted_vs[0]->point.y) / (sorted_vs[2]->point.y - sorted_vs[0]->point.y);
- const float fac_b0 = (1.f - fac) / sorted_vs[0]->point.w / ((1.f - fac) / sorted_vs[0]->point.w + fac / sorted_vs[2]->point.w);
- o3d::DerivedVertex4 middle_vr{
+ const float fac = (sorted_vs[1]->vertex.y - sorted_vs[0]->vertex.y) / (sorted_vs[2]->vertex.y - sorted_vs[0]->vertex.y);
+ const float fac_b0 = (1.f - fac) / sorted_vs[0]->vertex.w / ((1.f - fac) / sorted_vs[0]->vertex.w + fac / sorted_vs[2]->vertex.w);
+ o3d::DerivedVertex middle_vr{
{
- sorted_vs[0]->point.x + fac * (sorted_vs[2]->point.x - sorted_vs[0]->point.x),
- sorted_vs[1]->point.y,
- fac_b0 * sorted_vs[0]->point.z + (1.f - fac_b0) * sorted_vs[2]->point.z,
- 1.f / (1.f / sorted_vs[0]->point.w + fac * (1.f / sorted_vs[2]->point.w - 1.f / sorted_vs[0]->point.w))
+ sorted_vs[0]->vertex.x + fac * (sorted_vs[2]->vertex.x - sorted_vs[0]->vertex.x),
+ sorted_vs[1]->vertex.y,
+ fac_b0 * sorted_vs[0]->vertex.z + (1.f - fac_b0) * sorted_vs[2]->vertex.z,
+ 1.f / (1.f / sorted_vs[0]->vertex.w + fac * (1.f / sorted_vs[2]->vertex.w - 1.f / sorted_vs[0]->vertex.w))
},
fac_b0 * sorted_vs[0]->b0 + (1.f - fac_b0) * sorted_vs[2]->b0,
fac_b0 * sorted_vs[0]->b1 + (1.f - fac_b0) * sorted_vs[2]->b1
};
- if (middle_vr.point.x < middle_vl.point.x) {
+ if (middle_vr.vertex.x < middle_vl.vertex.x) {
auto temp = middle_vr;
middle_vr = middle_vl;
middle_vl = temp;
}
- // top triangle
- {
- if (sorted_vs[0]->point.y != sorted_vs[1]->point.y) {
- int top_y = static_cast<int>(std::floor(sorted_vs[0]->point.y + 1.f));
- int bottom_y = static_cast<int>(std::ceil(sorted_vs[1]->point.y - 1.f));
- for (int y = top_y; y <= bottom_y; y++) {
- float iy = static_cast<float>(y);
- float s = (iy - sorted_vs[0]->point.y) / (sorted_vs[1]->point.y - sorted_vs[0]->point.y);
- float sub_bb0 = 1.f - s;
- float xl = sorted_vs[0]->point.x + s * (middle_vl.point.x - sorted_vs[0]->point.x);
- float xr = sorted_vs[0]->point.x + s * (middle_vr.point.x - sorted_vs[0]->point.x);
- int left_x = static_cast<int>(std::ceil(xl));
- int right_x = static_cast<int>(std::ceil(xr - 1.f));
- for (int x = left_x; x <= right_x; x++) {
- float ix = static_cast<float>(x);
- float t = (ix - xl) / (xr - xl);
- float sub_bb1 = s * (1.f - t);
- float b_fac = 1.f / (sub_bb0 / sorted_vs[0]->point.w + sub_bb1 / middle_vl.point.w + (1.f - sub_bb0 - sub_bb1) / middle_vr.point.w);
- float sub_b0 = b_fac * sub_bb0 / sorted_vs[0]->point.w;
- float sub_b1 = b_fac * sub_bb1 / middle_vl.point.w;
- float b0 = sub_b0 * sorted_vs[0]->b0 + sub_b1 * middle_vl.b0 + (1.f - sub_b0 - sub_b1) * middle_vr.b0;
- float b1 = sub_b0 * sorted_vs[0]->b1 + sub_b1 * middle_vl.b1 + (1.f - sub_b0 - sub_b1) * middle_vr.b1;
- math::Vector3 loc{
- b0 * root.vertex1.point.x + b1 * root.vertex2.point.x + (1.f - b0 - b1) * root.vertex3.point.x,
- b0 * root.vertex1.point.y + b1 * root.vertex2.point.y + (1.f - b0 - b1) * root.vertex3.point.y,
- b0 * root.vertex1.point.z + b1 * root.vertex2.point.z + (1.f - b0 - b1) * root.vertex3.point.z
- };
- if (loc.z < depth_buf[x + y * fb->width()]) {
- depth_buf[x + y * fb->width()] = loc.z;
- fb->draw_point(x, y, loc, o3d::VertexData::bilerp(root.vertex1.data, root.vertex2.data, root.vertex3.data, b0, b1));
- }
- }
- }
+ const auto _draw_cropped_triangle_side = [&]<TriangleSide side>() {
+ const int vertex_end_index = ([&]() { if constexpr (side == TriangleSide::top) return 0; else return 2; })();
+ const o3d::DerivedVertex& vertex_end = *sorted_vs[vertex_end_index];
+ if (vertex_end.vertex.y == sorted_vs[1]->vertex.y)
+ return;
+ int top_y;
+ int bottom_y;
+ if constexpr (side == TriangleSide::top) {
+ top_y = static_cast<int>(std::floor(vertex_end.vertex.y + 1.f));
+ bottom_y = static_cast<int>(std::ceil(sorted_vs[1]->vertex.y - 1.f));
+ } else {
+ bottom_y = static_cast<int>(std::floor(vertex_end.vertex.y));
+ top_y = static_cast<int>(std::ceil(sorted_vs[1]->vertex.y));
}
- }
-
- // bottom triangle
- {
- if (sorted_vs[1]->point.y != sorted_vs[2]->point.y) {
- int bottom_y = static_cast<int>(std::floor(sorted_vs[2]->point.y));
- int top_y = static_cast<int>(std::ceil(sorted_vs[1]->point.y));
- for (int y = top_y; y <= bottom_y; y++) {
- float iy = static_cast<float>(y);
- float s = (iy - sorted_vs[2]->point.y) / (sorted_vs[1]->point.y - sorted_vs[2]->point.y);
- float sub_bb0 = 1.f - s;
- float xl = sorted_vs[2]->point.x + s * (middle_vl.point.x - sorted_vs[2]->point.x);
- float xr = sorted_vs[2]->point.x + s * (middle_vr.point.x - sorted_vs[2]->point.x);
- int left_x = static_cast<int>(std::ceil(xl));
- int right_x = static_cast<int>(std::ceil(xr - 1.f));
- for (int x = left_x; x <= right_x; x++) {
- float ix = static_cast<float>(x);
- float t = (ix - xl) / (xr - xl);
- float sub_bb1 = s * (1.f - t);
- float b_fac = 1.f / (sub_bb0 / sorted_vs[2]->point.w + sub_bb1 / middle_vl.point.w + (1.f - sub_bb0 - sub_bb1) / middle_vr.point.w);
- float sub_b0 = b_fac * sub_bb0 / sorted_vs[2]->point.w;
- float sub_b1 = b_fac * sub_bb1 / middle_vl.point.w;
- float b0 = sub_b0 * sorted_vs[2]->b0 + sub_b1 * middle_vl.b0 + (1.f - sub_b0 - sub_b1) * middle_vr.b0;
- float b1 = sub_b0 * sorted_vs[2]->b1 + sub_b1 * middle_vl.b1 + (1.f - sub_b0 - sub_b1) * middle_vr.b1;
- math::Vector3 loc{
- b0 * root.vertex1.point.x + b1 * root.vertex2.point.x + (1.f - b0 - b1) * root.vertex3.point.x,
- b0 * root.vertex1.point.y + b1 * root.vertex2.point.y + (1.f - b0 - b1) * root.vertex3.point.y,
- b0 * root.vertex1.point.z + b1 * root.vertex2.point.z + (1.f - b0 - b1) * root.vertex3.point.z
- };
- if (loc.z < depth_buf[x + y * fb->width()]) {
- depth_buf[x + y * fb->width()] = loc.z;
- fb->draw_point(x, y, loc, o3d::VertexData::bilerp(root.vertex1.data, root.vertex2.data, root.vertex3.data, b0, b1));
- }
+ for (int y = top_y; y <= bottom_y; y++) {
+ float iy = static_cast<float>(y);
+ float s = (iy - vertex_end.vertex.y) / (sorted_vs[1]->vertex.y - vertex_end.vertex.y);
+ float sub_bb0 = 1.f - s;
+ float xl = vertex_end.vertex.x + s * (middle_vl.vertex.x - vertex_end.vertex.x);
+ float xr = vertex_end.vertex.x + s * (middle_vr.vertex.x - vertex_end.vertex.x);
+ int left_x = static_cast<int>(std::ceil(xl));
+ int right_x = static_cast<int>(std::ceil(xr - 1.f));
+ for (int x = left_x; x <= right_x; x++) {
+ float ix = static_cast<float>(x);
+ float t = (ix - xl) / (xr - xl);
+ float sub_bb1 = s * (1.f - t);
+ float b_fac = 1.f / (sub_bb0 / vertex_end.vertex.w + sub_bb1 / middle_vl.vertex.w + (1.f - sub_bb0 - sub_bb1) / middle_vr.vertex.w);
+ float sub_b0 = b_fac * sub_bb0 / vertex_end.vertex.w;
+ float sub_b1 = b_fac * sub_bb1 / middle_vl.vertex.w;
+ float b0 = sub_b0 * vertex_end.b0 + sub_b1 * middle_vl.b0 + (1.f - sub_b0 - sub_b1) * middle_vr.b0;
+ float b1 = sub_b0 * vertex_end.b1 + sub_b1 * middle_vl.b1 + (1.f - sub_b0 - sub_b1) * middle_vr.b1;
+ math::Vector3 loc{
+ b0 * root.vertex1.vertex.x + b1 * root.vertex2.vertex.x + (1.f - b0 - b1) * root.vertex3.vertex.x,
+ b0 * root.vertex1.vertex.y + b1 * root.vertex2.vertex.y + (1.f - b0 - b1) * root.vertex3.vertex.y,
+ b0 * root.vertex1.vertex.z + b1 * root.vertex2.vertex.z + (1.f - b0 - b1) * root.vertex3.vertex.z
+ };
+ if (loc.z < depth_buf[x + y * fb->width()]) {
+ depth_buf[x + y * fb->width()] = loc.z;
+ fb->draw_point(x, y, loc, o3d::VertexData::bilerp(root.vertex1.data, root.vertex2.data, root.vertex3.data, b0, b1));
}
}
}
- }
+ };
+ _draw_cropped_triangle_side.operator()<TriangleSide::top>();
+ _draw_cropped_triangle_side.operator()<TriangleSide::bottom>();
}
-void Renderer::draw_triangle(o3d::TriangleVertex4 triangle) {
+void Renderer::draw_triangle(o3d::Triangle triangle) {
for (auto t1 : triangle.to_derived().crop_z_out(-1.f, 1.f)) {
for (auto t2 : t1.div_by_w().perspective_crop_xy_out(-1.f, 1.f, -1.f, 1.f)) {
- auto pp1 = t2.derived_vertex1.point.xy();
- auto pp2 = t2.derived_vertex2.point.xy();
- auto pp3 = t2.derived_vertex3.point.xy();
+ auto pp1 = t2.derived_vertex1.vertex.xy();
+ auto pp2 = t2.derived_vertex2.vertex.xy();
+ auto pp3 = t2.derived_vertex3.vertex.xy();
if ((pp2 - pp1).det(pp3 - pp1) >= 0.f) continue;
float fw_over_2 = static_cast<float>(fb->width()) / 2.f, fh_over_2 = static_cast<float>(fb->height()) / 2.f;
- t2.derived_vertex1.point.x = (t2.derived_vertex1.point.x + 1.f) * fw_over_2 - .5f;
- t2.derived_vertex1.point.y = (t2.derived_vertex1.point.y + 1.f) * fh_over_2 - .5f;
- t2.derived_vertex2.point.x = (t2.derived_vertex2.point.x + 1.f) * fw_over_2 - .5f;
- t2.derived_vertex2.point.y = (t2.derived_vertex2.point.y + 1.f) * fh_over_2 - .5f;
- t2.derived_vertex3.point.x = (t2.derived_vertex3.point.x + 1.f) * fw_over_2 - .5f;
- t2.derived_vertex3.point.y = (t2.derived_vertex3.point.y + 1.f) * fh_over_2 - .5f;
+ t2.derived_vertex1.vertex.x = (t2.derived_vertex1.vertex.x + 1.f) * fw_over_2 - .5f;
+ t2.derived_vertex1.vertex.y = (t2.derived_vertex1.vertex.y + 1.f) * fh_over_2 - .5f;
+ t2.derived_vertex2.vertex.x = (t2.derived_vertex2.vertex.x + 1.f) * fw_over_2 - .5f;
+ t2.derived_vertex2.vertex.y = (t2.derived_vertex2.vertex.y + 1.f) * fh_over_2 - .5f;
+ t2.derived_vertex3.vertex.x = (t2.derived_vertex3.vertex.x + 1.f) * fw_over_2 - .5f;
+ t2.derived_vertex3.vertex.y = (t2.derived_vertex3.vertex.y + 1.f) * fh_over_2 - .5f;
_draw_cropped_triangle(triangle, t2);
}
}