aboutsummaryrefslogtreecommitdiff
path: root/src/fb
diff options
context:
space:
mode:
Diffstat (limited to 'src/fb')
-rw-r--r--src/fb/chfb.cpp119
-rw-r--r--src/fb/chfb.h12
-rw-r--r--src/fb/fb.h20
-rw-r--r--src/fb/pixfb.cpp116
-rw-r--r--src/fb/pixfb.h11
5 files changed, 37 insertions, 241 deletions
diff --git a/src/fb/chfb.cpp b/src/fb/chfb.cpp
index c0e5cc7..b5c0ae0 100644
--- a/src/fb/chfb.cpp
+++ b/src/fb/chfb.cpp
@@ -17,7 +17,6 @@ void CharacterFrameBuffer::resize(unsigned int w, unsigned int h) {
this->w = w;
this->h = h;
chars_vector.resize(w * h);
- depth_buf.resize(w * h);
clear();
}
@@ -35,124 +34,14 @@ const char* CharacterFrameBuffer::chars() const {
void CharacterFrameBuffer::clear() {
std::fill(chars_vector.begin(), chars_vector.end(), ' ');
- std::fill(depth_buf.begin(), depth_buf.end(), 1.f);
- face_ind = -1;
}
-void CharacterFrameBuffer::_draw_cropped_triangle(engine::o3d::TriangleVertex3 triangle) {
- std::array<engine::o3d::Vertex3*, 3> sorted_vs = { &triangle.vertex1, &triangle.vertex2, &triangle.vertex3 };
-
-#define SWAP_IF_LT(X,Y) ({\
- if (sorted_vs[X]->point.y < sorted_vs[Y]->point.y) {\
- engine::o3d::Vertex3* 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
-
- engine::o3d::Vertex3 middle_vl = *sorted_vs[1];
- float fac = (sorted_vs[1]->point.y - sorted_vs[0]->point.y) / (sorted_vs[2]->point.y - sorted_vs[0]->point.y);
- engine::o3d::Vertex3 middle_vr{
- {
- sorted_vs[0]->point.x + fac * (sorted_vs[2]->point.x - sorted_vs[0]->point.x),
- sorted_vs[1]->point.y,
- sorted_vs[0]->point.z + fac * (sorted_vs[2]->point.z - sorted_vs[0]->point.z)
- },
- engine::o3d::VertexData::lerp(sorted_vs[0]->data, sorted_vs[2]->data, fac)
- };
- if (middle_vr.point.x < middle_vl.point.x) {
- engine::o3d::Vertex3 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 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);
- // depth and vd don't take into account perspective
- float depth = sorted_vs[0]->point.z + s * (middle_vl.point.z - sorted_vs[0]->point.z + t * (middle_vr.point.z - middle_vl.point.z));
- // VertexData vd = VertexData::bilerp(sorted_vs[0]->data, middle_vl.data, middle_vr.data, s, t);
- if (depth < depth_buf[x + y * w]) {
- depth_buf[x + y * w] = depth;
- chars_vector[x + y * w] = face_char();
- }
- }
- }
- }
- }
-
- // 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 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);
- // depth and vd don't take into account perspective
- float depth = sorted_vs[2]->point.z + s * (middle_vl.point.z - sorted_vs[2]->point.z + t * (middle_vr.point.z - middle_vl.point.z));
- // VertexData vd = VertexData::bilerp(sorted_vs[2]->data, middle_vl.data, middle_vr.data, s, t);
- if (depth < depth_buf[x + y * w]) {
- depth_buf[x + y * w] = depth;
- chars_vector[x + y * w] = face_char();
- }
- }
- }
- }
- }
-}
-
-void CharacterFrameBuffer::draw_triangle(engine::o3d::TriangleVertex4 triangle) {
- face_ind++;
- for (auto t1 : triangle.crop_z_out(-1.f, 1.f)) {
- auto t1_2 = t1.div_by_w();
- t1_2.vertex1.point.x *= 2.f;
- t1_2.vertex2.point.x *= 2.f;
- t1_2.vertex3.point.x *= 2.f;
- for (auto t2 : t1_2.crop_xy_out(-1.f, 1.f, -1.f, 1.f)) {
- engine::math::Vector2 pp1 = t2.vertex1.point.xy(),
- pp2 = t2.vertex2.point.xy(),
- pp3 = t2.vertex3.point.xy();
- if ((pp2 - pp1).det(pp3 - pp1) >= 0.f) continue;
- t2.vertex1.point = (t2.vertex1.point + engine::math::Vector3{1.f, 1.f, 0.f}) / 2.f;
- t2.vertex2.point = (t2.vertex2.point + engine::math::Vector3{1.f, 1.f, 0.f}) / 2.f;
- t2.vertex3.point = (t2.vertex3.point + engine::math::Vector3{1.f, 1.f, 0.f}) / 2.f;
- float fw = static_cast<float>(w), fh = static_cast<float>(h);
- t2.vertex1.point.x = t2.vertex1.point.x * fw - .5f;
- t2.vertex1.point.y = t2.vertex1.point.y * fh - .5f;
- t2.vertex2.point.x = t2.vertex2.point.x * fw - .5f;
- t2.vertex2.point.y = t2.vertex2.point.y * fh - .5f;
- t2.vertex3.point.x = t2.vertex3.point.x * fw - .5f;
- t2.vertex3.point.y = t2.vertex3.point.y * fh - .5f;
- _draw_cropped_triangle(t2);
- }
- }
+void CharacterFrameBuffer::draw_point(int x, int y, engine::math::Vector3 loc, const engine::o3d::VertexData& vd) {
+ (void) vd;
+ chars_vector[x + y * w] = face_char(static_cast<int>(loc.x));
}
-char CharacterFrameBuffer::face_char() const {
+char CharacterFrameBuffer::face_char(int face_ind) const {
int n = 1 + face_ind / 2;
return (n < 10 ? '0' : 'A' - 10) + n;
}
diff --git a/src/fb/chfb.h b/src/fb/chfb.h
index 9e10a0d..280f6d8 100644
--- a/src/fb/chfb.h
+++ b/src/fb/chfb.h
@@ -2,12 +2,11 @@
#define FB_CHFB_H
#include <vector>
-#include "math/vector.h"
-#include "o3d/tri_vertex.h"
+#include "fb/fb.h"
namespace engine::fb {
-class CharacterFrameBuffer {
+class CharacterFrameBuffer : public FrameBuffer {
public:
CharacterFrameBuffer(unsigned int w, unsigned int h);
void resize(unsigned int w, unsigned int h);
@@ -15,16 +14,13 @@ class CharacterFrameBuffer {
unsigned int height() const;
const char* chars() const;
void clear();
- void draw_triangle(engine::o3d::TriangleVertex4 triangle);
+ void draw_point(int x, int y, engine::math::Vector3 loc, const engine::o3d::VertexData& vd);
private:
unsigned int w, h;
std::vector<char> chars_vector;
- std::vector<float> depth_buf;
- int face_ind;
- void _draw_cropped_triangle(engine::o3d::TriangleVertex3 triangle);
- char face_char() const;
+ char face_char(int face_inf) const;
};
}
diff --git a/src/fb/fb.h b/src/fb/fb.h
new file mode 100644
index 0000000..04b13ee
--- /dev/null
+++ b/src/fb/fb.h
@@ -0,0 +1,20 @@
+#ifndef FB_FB_H
+#define FB_FB_H
+
+#include "math/vector.h"
+#include "o3d/vertex_data.h"
+
+namespace engine::fb {
+
+class FrameBuffer {
+ public:
+ virtual void resize(unsigned int w, unsigned int h) = 0;
+ virtual unsigned int width() const = 0;
+ virtual unsigned int height() const = 0;
+ virtual void clear() = 0;
+ virtual void draw_point(int x, int y, engine::math::Vector3 loc, const engine::o3d::VertexData& vd) = 0;
+};
+
+}
+
+#endif // FB_FB_H
diff --git a/src/fb/pixfb.cpp b/src/fb/pixfb.cpp
index af220c6..26bc8f2 100644
--- a/src/fb/pixfb.cpp
+++ b/src/fb/pixfb.cpp
@@ -3,6 +3,7 @@
#include <cmath>
#include <vector>
#include <cstdint>
+#include <algorithm>
#include "math/vector.h"
#include "o3d/vertex.h"
#include "o3d/tri_vertex.h"
@@ -18,7 +19,6 @@ void PixelFrameBuffer::resize(unsigned int w, unsigned int h) {
this->w = w;
this->h = h;
pixels_vector.resize(w * h);
- depth_buf.resize(w * h);
clear();
}
@@ -36,120 +36,14 @@ const uint32_t* PixelFrameBuffer::pixels() const {
void PixelFrameBuffer::clear() {
std::fill(pixels_vector.begin(), pixels_vector.end(), 0x000000FF);
- std::fill(depth_buf.begin(), depth_buf.end(), 1.f);
- face_ind = -1;
}
-void PixelFrameBuffer::_draw_cropped_triangle(engine::o3d::TriangleVertex3 triangle) {
- std::array<engine::o3d::Vertex3*, 3> sorted_vs = { &triangle.vertex1, &triangle.vertex2, &triangle.vertex3 };
-
-#define SWAP_IF_LT(X,Y) ({\
- if (sorted_vs[X]->point.y < sorted_vs[Y]->point.y) {\
- engine::o3d::Vertex3* 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
-
- engine::o3d::Vertex3 middle_vl = *sorted_vs[1];
- float fac = (sorted_vs[1]->point.y - sorted_vs[0]->point.y) / (sorted_vs[2]->point.y - sorted_vs[0]->point.y);
- engine::o3d::Vertex3 middle_vr{
- {
- sorted_vs[0]->point.x + fac * (sorted_vs[2]->point.x - sorted_vs[0]->point.x),
- sorted_vs[1]->point.y,
- sorted_vs[0]->point.z + fac * (sorted_vs[2]->point.z - sorted_vs[0]->point.z)
- },
- engine::o3d::VertexData::lerp(sorted_vs[0]->data, sorted_vs[2]->data, fac)
- };
- if (middle_vr.point.x < middle_vl.point.x) {
- engine::o3d::Vertex3 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 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);
- // depth and vd don't take into account perspective
- float depth = sorted_vs[0]->point.z + s * (middle_vl.point.z - sorted_vs[0]->point.z + t * (middle_vr.point.z - middle_vl.point.z));
- // VertexData vd = VertexData::bilerp(sorted_vs[0]->data, middle_vl.data, middle_vr.data, s, t);
- if (depth < depth_buf[x + y * w]) {
- depth_buf[x + y * w] = depth;
- pixels_vector[x + y * w] = face_color();
- }
- }
- }
- }
- }
-
- // 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 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);
- // depth and vd don't take into account perspective
- float depth = sorted_vs[2]->point.z + s * (middle_vl.point.z - sorted_vs[2]->point.z + t * (middle_vr.point.z - middle_vl.point.z));
- // VertexData vd = VertexData::bilerp(sorted_vs[2]->data, middle_vl.data, middle_vr.data, s, t);
- if (depth < depth_buf[x + y * w]) {
- depth_buf[x + y * w] = depth;
- pixels_vector[x + y * w] = face_color();
- }
- }
- }
- }
- }
-}
-
-void PixelFrameBuffer::draw_triangle(engine::o3d::TriangleVertex4 triangle) {
- face_ind++;
- for (auto t1 : triangle.crop_z_out(-1.f, 1.f)) {
- for (auto t2 : t1.div_by_w().crop_xy_out(-1.f, 1.f, -1.f, 1.f)) {
- engine::math::Vector2 pp1 = t2.vertex1.point.xy(),
- pp2 = t2.vertex2.point.xy(),
- pp3 = t2.vertex3.point.xy();
- if ((pp2 - pp1).det(pp3 - pp1) >= 0.f) continue;
- t2.vertex1.point = (t2.vertex1.point + engine::math::Vector3{1.f, 1.f, 0.f}) / 2.f;
- t2.vertex2.point = (t2.vertex2.point + engine::math::Vector3{1.f, 1.f, 0.f}) / 2.f;
- t2.vertex3.point = (t2.vertex3.point + engine::math::Vector3{1.f, 1.f, 0.f}) / 2.f;
- float fw = static_cast<float>(w), fh = static_cast<float>(h);
- t2.vertex1.point.x = t2.vertex1.point.x * fw - .5f;
- t2.vertex1.point.y = t2.vertex1.point.y * fh - .5f;
- t2.vertex2.point.x = t2.vertex2.point.x * fw - .5f;
- t2.vertex2.point.y = t2.vertex2.point.y * fh - .5f;
- t2.vertex3.point.x = t2.vertex3.point.x * fw - .5f;
- t2.vertex3.point.y = t2.vertex3.point.y * fh - .5f;
- _draw_cropped_triangle(t2);
- }
- }
+void PixelFrameBuffer::draw_point(int x, int y, engine::math::Vector3 loc, const engine::o3d::VertexData& vd) {
+ (void) vd;
+ pixels_vector[x + y * w] = face_color(static_cast<int>(loc.x));
}
-uint32_t PixelFrameBuffer::face_color() const {
+uint32_t PixelFrameBuffer::face_color(int face_ind) const {
int n = face_ind / 2;
return ((n % 2 ? 0xFF000000 : 0x55000000) >> ((n % 6) / 2 * 8)) | 0xFF;
}
diff --git a/src/fb/pixfb.h b/src/fb/pixfb.h
index cdfac18..84bce2c 100644
--- a/src/fb/pixfb.h
+++ b/src/fb/pixfb.h
@@ -3,12 +3,11 @@
#include <vector>
#include <cstdint>
-#include "math/vector.h"
-#include "o3d/tri_vertex.h"
+#include "fb/fb.h"
namespace engine::fb {
-class PixelFrameBuffer {
+class PixelFrameBuffer : public FrameBuffer {
public:
PixelFrameBuffer(unsigned int w, unsigned int h);
void resize(unsigned int w, unsigned int h);
@@ -16,16 +15,14 @@ class PixelFrameBuffer {
unsigned int height() const;
const uint32_t* pixels() const;
void clear();
- void draw_triangle(engine::o3d::TriangleVertex4 triangle);
+ void draw_point(int x, int y, engine::math::Vector3 loc, const engine::o3d::VertexData& vd);
private:
unsigned int w, h;
std::vector<uint32_t> pixels_vector;
- std::vector<float> depth_buf;
int face_ind;
- void _draw_cropped_triangle(engine::o3d::TriangleVertex3 triangle);
- uint32_t face_color() const;
+ uint32_t face_color(int face_ind) const;
};
}