diff options
author | vimene <vincent.menegaux@gmail.com> | 2025-01-02 13:25:14 +0100 |
---|---|---|
committer | vimene <vincent.menegaux@gmail.com> | 2025-01-02 13:25:14 +0100 |
commit | 26b4b82a7be2c029491f3009b66b3cbf8db5d93c (patch) | |
tree | ddc247a0600b5933185677212f158ebea5a87530 /src/renderer.cpp | |
parent | 9fdb5881d46f5d80626f961f9c9f133cc25dab70 (diff) | |
download | engine-26b4b82a7be2c029491f3009b66b3cbf8db5d93c.tar.gz |
various improvements
- cleaned up the computation of the camera's matrix
- changed VertexData to being a struct which transmit data between the "vertex shader" and the "fragment shader"
- started working on keyboard and mouse controls
- added fov (field of view)
- changed quaternion to euler angles conversion, from zyx to zxy
- fixed computations of z coordinates in triangle rendering
- improved naming in the triangle rasterizer
Diffstat (limited to 'src/renderer.cpp')
-rw-r--r-- | src/renderer.cpp | 73 |
1 files changed, 41 insertions, 32 deletions
diff --git a/src/renderer.cpp b/src/renderer.cpp index ad67ecc..7e868b4 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -14,6 +14,7 @@ using engine::o3d::Triangle, engine::o3d::TriangleDerived, engine::o3d::VertexData, + engine::o3d::DerivedVertex, engine::fb::CharacterFrameBuffer, engine::fb::PixelFrameBuffer; @@ -59,31 +60,31 @@ void Renderer<FrameBuffer>::draw_triangle(const Triangle& triangle) { template<typename FrameBuffer> void Renderer<FrameBuffer>::_draw_cropped_triangle(const Triangle& root, const TriangleDerived& triangle) { - std::array<const o3d::DerivedVertex*, 3> sorted_vs = { &triangle.derived_vertex1, &triangle.derived_vertex2, &triangle.derived_vertex3 }; + std::array<const 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) { + const auto swap_if_gt = [&](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); + swap_if_gt(0, 1); + swap_if_gt(1, 2); + swap_if_gt(0, 1); } auto middle_vl = *sorted_vs[1]; 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 middle_vr_vertex_w = 1.f / (1.f / sorted_vs[0]->vertex.w + fac * (1.f / sorted_vs[2]->vertex.w - 1.f / sorted_vs[0]->vertex.w)); const float fac_b0 = middle_vr_vertex_w * (1.f - fac) / sorted_vs[0]->vertex.w; - o3d::DerivedVertex middle_vr{ + DerivedVertex middle_vr{ { 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, + (fac_b0 * sorted_vs[0]->vertex.w * sorted_vs[0]->vertex.z + (1.f - fac_b0) * sorted_vs[2]->vertex.w * sorted_vs[2]->vertex.z) / middle_vr_vertex_w, middle_vr_vertex_w }, fac_b0 * sorted_vs[0]->b0 + (1.f - fac_b0) * sorted_vs[2]->b0, @@ -97,7 +98,7 @@ void Renderer<FrameBuffer>::_draw_cropped_triangle(const Triangle& root, const T 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]; + const DerivedVertex& vertex_end = *sorted_vs[vertex_end_index]; if (vertex_end.vertex.y == sorted_vs[1]->vertex.y) return; int top_y; @@ -110,34 +111,42 @@ void Renderer<FrameBuffer>::_draw_cropped_triangle(const Triangle& root, const T top_y = static_cast<int>(std::ceil(sorted_vs[1]->vertex.y)); } 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 s = (static_cast<float>(y) - vertex_end.vertex.y) + / (sorted_vs[1]->vertex.y - vertex_end.vertex.y); + float projected_relative_b0 = 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 loc_z = sub_b0 * vertex_end.vertex.z + sub_b1 * middle_vl.vertex.z + (1.f - sub_b0 - sub_b1) * middle_vr.vertex.z; - if (loc_z < depth_buf[x + y * fb.width()]) { - depth_buf[x + y * fb.width()] = loc_z; - 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; - 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, - loc_z - }; - fb.draw_point(x, y, loc, - VertexData::bilerp(root.vertex1.data, root.vertex2.data, root.vertex3.data, b0, b1), - Vector3::bilerp(root.vertex1.normal, root.vertex2.normal, root.vertex3.normal, b0, b1).normalize()); - } + float t = (static_cast<float>(x) - xl) + / (xr - xl); + float projected_relative_b1 = s * (1.f - t); + float point_w = 1.f / + ( + projected_relative_b0 / vertex_end.vertex.w + + projected_relative_b1 / middle_vl.vertex.w + + (1.f - projected_relative_b0 - projected_relative_b1) / middle_vr.vertex.w + ); + float relative_b0 = point_w * projected_relative_b0 / vertex_end.vertex.w; + float relative_b1 = point_w * projected_relative_b1 / middle_vl.vertex.w; + float loc_z = relative_b0 * vertex_end.vertex.w * vertex_end.vertex.z + + relative_b1 * middle_vl.vertex.w * middle_vl.vertex.z + + (1.f - relative_b0 - relative_b1) * middle_vr.vertex.w * middle_vr.vertex.z; + + if (loc_z >= depth_buf[x + y * fb.width()]) continue; + + depth_buf[x + y * fb.width()] = loc_z; + float b0 = relative_b0 * vertex_end.b0 + relative_b1 * middle_vl.b0 + (1.f - relative_b0 - relative_b1) * middle_vr.b0; + float b1 = relative_b0 * vertex_end.b1 + relative_b1 * middle_vl.b1 + (1.f - relative_b0 - relative_b1) * middle_vr.b1; + 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, + loc_z + }; + fb.draw_point(x, y, loc, + VertexData::bilerp(root.vertex1.data, root.vertex2.data, root.vertex3.data, b0, b1), + Vector3::bilerp(root.vertex1.normal, root.vertex2.normal, root.vertex3.normal, b0, b1).normalize()); } } }; |