aboutsummaryrefslogtreecommitdiff
path: root/src/renderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer.cpp')
-rw-r--r--src/renderer.cpp122
1 files changed, 68 insertions, 54 deletions
diff --git a/src/renderer.cpp b/src/renderer.cpp
index 1fa8799..ad67ecc 100644
--- a/src/renderer.cpp
+++ b/src/renderer.cpp
@@ -1,42 +1,64 @@
#include "renderer.h"
-#include <array>
-#include <cmath>
-#include <algorithm>
#include <memory>
+#include <array>
#include "math/vector.h"
-#include "o3d/vertex.h"
-#include "o3d/deriv_vertex.h"
#include "o3d/tri.h"
#include "o3d/tri_deriv.h"
-#include "o3d/vertex_data.h"
+#include "fb/chfb.h"
+#include "fb/pixfb.h"
using namespace engine;
+using
+ engine::math::Vector2,
+ engine::math::Vector4,
+ engine::o3d::Triangle,
+ engine::o3d::TriangleDerived,
+ engine::o3d::VertexData,
+ engine::fb::CharacterFrameBuffer,
+ engine::fb::PixelFrameBuffer;
-Renderer::Renderer(std::unique_ptr<fb::FrameBuffer> fb) : fb{std::move(fb)} {
- depth_buf.resize(this->fb->width() * this->fb->height());
-}
-
-void Renderer::resize(unsigned int w, unsigned int h) {
- fb->resize(w, h);
- depth_buf.resize(fb->width() * fb->height());
-}
-
-unsigned int Renderer::width() const {
- return fb->width();
+template<typename FrameBuffer>
+template<typename FBArg>
+Renderer<FrameBuffer>::Renderer(FBArg&& fb) : fb{std::forward<FBArg>(fb)} {
+ depth_buf.resize(this->fb.width() * this->fb.height());
}
-unsigned int Renderer::height() const {
- return fb->height();
+template<typename FrameBuffer>
+void Renderer<FrameBuffer>::resize(unsigned int w, unsigned int h) {
+ fb.resize(w, h);
+ depth_buf.resize(fb.width() * fb.height());
}
-void Renderer::clear() {
+template<typename FrameBuffer>
+void Renderer<FrameBuffer>::clear() {
std::fill(depth_buf.begin(), depth_buf.end(), 1.f);
- fb->clear();
+ fb.clear();
}
enum TriangleSide { top, bottom };
-void Renderer::_draw_cropped_triangle(const o3d::Triangle& root, const o3d::TriangleDerived& triangle) {
+template<typename FrameBuffer>
+void Renderer<FrameBuffer>::draw_triangle(const Triangle& triangle) {
+ Vector2 fdim_over_2 = Vector2{static_cast<float>(fb.width()), static_cast<float>(fb.height())} / 2.f;
+ for (const 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& v1 = t2.derived_vertex1.vertex;
+ auto& v2 = t2.derived_vertex2.vertex;
+ auto& v3 = t2.derived_vertex3.vertex;
+ auto pp1 = v1.xy();
+ auto pp2 = v2.xy();
+ auto pp3 = v3.xy();
+ if ((pp2 - pp1).det(pp3 - pp1) >= 0.f) continue;
+ v1 = Vector4{(pp1 + 1.f).mul_term(fdim_over_2) - .5f, v1.z, v1.w};
+ v2 = Vector4{(pp2 + 1.f).mul_term(fdim_over_2) - .5f, v2.z, v2.w};
+ v3 = Vector4{(pp3 + 1.f).mul_term(fdim_over_2) - .5f, v3.z, v3.w};
+ _draw_cropped_triangle(triangle, t2);
+ }
+ }
+}
+
+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 };
{
@@ -55,13 +77,14 @@ void Renderer::_draw_cropped_triangle(const o3d::Triangle& root, const o3d::Tria
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 fac_b0 = (1.f - fac) / sorted_vs[0]->vertex.w / ((1.f - fac) / sorted_vs[0]->vertex.w + fac / sorted_vs[2]->vertex.w);
+ 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{
{
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))
+ middle_vr_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
@@ -101,39 +124,30 @@ void Renderer::_draw_cropped_triangle(const o3d::Triangle& root, const o3d::Tria
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));
+ 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());
}
}
}
};
- _draw_cropped_triangle_side.operator()<TriangleSide::top>();
- _draw_cropped_triangle_side.operator()<TriangleSide::bottom>();
+ _draw_cropped_triangle_side.template operator()<TriangleSide::top>();
+ _draw_cropped_triangle_side.template operator()<TriangleSide::bottom>();
}
-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.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.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);
- }
- }
-}
+template class Renderer<CharacterFrameBuffer>;
+template Renderer<CharacterFrameBuffer>::Renderer(CharacterFrameBuffer&&);
+template Renderer<CharacterFrameBuffer>::Renderer(const CharacterFrameBuffer&);
+template class Renderer<PixelFrameBuffer>;
+template Renderer<PixelFrameBuffer>::Renderer(PixelFrameBuffer&&);
+template Renderer<PixelFrameBuffer>::Renderer(const PixelFrameBuffer&);