aboutsummaryrefslogtreecommitdiff
path: root/src/renderer.cpp
diff options
context:
space:
mode:
authorvimene <vincent.menegaux@gmail.com>2023-12-11 12:42:46 +0100
committervimene <vincent.menegaux@gmail.com>2023-12-11 12:42:46 +0100
commit6b765a85cf81bf4b7162e4c9280dd4054581c611 (patch)
tree4156dff7c632e6511fe18daebeea506744ad1ff7 /src/renderer.cpp
parentff2c784d4c4100f0301628e8a52a6910d776d067 (diff)
downloadengine-6b765a85cf81bf4b7162e4c9280dd4054581c611.tar.gz
improved mesh definition
- In the context of mesh definition, splited indices into vertex index, normal index and vertex data index to be able to specify different normals and vertex data for different faces using the same vertex
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);
}
}