aboutsummaryrefslogtreecommitdiff
path: root/src/renderer.cpp
diff options
context:
space:
mode:
authorvimene <vincent.menegaux@gmail.com>2025-01-02 13:25:14 +0100
committervimene <vincent.menegaux@gmail.com>2025-01-02 13:25:14 +0100
commit26b4b82a7be2c029491f3009b66b3cbf8db5d93c (patch)
treeddc247a0600b5933185677212f158ebea5a87530 /src/renderer.cpp
parent9fdb5881d46f5d80626f961f9c9f133cc25dab70 (diff)
downloadengine-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.cpp73
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());
}
}
};