MinusculeRender/src/rasterizer.cc

97 lines
3.2 KiB
C++
Raw Normal View History

2024-03-01 21:31:47 +08:00
// Copyright 2024 Bytedance Inc. All Rights Reserved.
// Author: tianlei.richard@qq.com (tianlei.richard)
#include <limits>
#include <thread>
#include "spdlog/spdlog.h"
2024-03-01 21:31:47 +08:00
#include "rasterizer.h"
2024-03-01 21:31:47 +08:00
Rasterizer::Rasterizer(const int width, const int height)
: width_(width), height_(height),
shading_points_(std::vector<std::vector<RasterizerResult>>(
height, std::vector<RasterizerResult>(width, RasterizerResult{}))) {}
std::vector<std::vector<RasterizerResult>>
Rasterizer::rasterize(const std::vector<Triangle> &primitives) {
auto partial_rasterize = [&primitives, this](const int begin, const int end) {
for (int idx = begin; idx < end; ++idx) {
const auto &t = primitives[idx];
const auto &triangle_points = t.get_vertex_position();
const auto &aabb = t.axis_align_bbox();
const int x_min = std::min(std::max(0, aabb.x), width_);
const int x_max = std::min(std::max(0, aabb.x + aabb.width), width_);
const int y_min = std::min(std::max(0, aabb.y), height_);
const int y_max = std::min(std::max(0, aabb.y + aabb.height), height_);
for (int i = y_min; i < y_max; ++i) {
for (int j = x_min; j <= x_max; ++j) {
auto &property = (this->shading_points_)[i][j];
const auto &[is_inside, z_screen] =
inside(Point2d{j + 0.5, i + 0.5}, t);
if (is_inside && z_screen > property.depth) {
property.depth = z_screen;
property.triangle_index = idx;
}
}
2024-03-05 21:43:08 +08:00
}
}
};
const int thread_num = 6;
std::vector<std::thread> rasterize_threads;
for (int begin = 0, offset = primitives.size() / thread_num,
remainer = (primitives.size() % thread_num);
begin < primitives.size();) {
int end = begin + offset;
if (remainer > 0) {
end += 1;
remainer -= 1;
2024-03-01 21:31:47 +08:00
}
rasterize_threads.push_back(std::thread(partial_rasterize, begin, end));
begin = end;
}
for (auto &t : rasterize_threads) {
t.join();
2024-03-01 21:31:47 +08:00
}
return shading_points_;
2024-03-01 21:31:47 +08:00
}
2024-03-05 21:43:08 +08:00
std::vector<std::vector<RasterizerResult>> Rasterizer::get_picture() const {
return shading_points_;
}
void Rasterizer::reset() {
shading_points_ = std::vector<std::vector<RasterizerResult>>(
height_, std::vector<RasterizerResult>(width_, RasterizerResult{}));
}
2024-03-05 21:43:08 +08:00
std::pair<bool, double> Rasterizer::inside(const Point2d &p_screen,
const Triangle &t) {
const auto points = t.get_vertex_position();
2024-03-05 21:43:08 +08:00
const auto plane_normal = t.normal_vector();
const auto plane_point = points[0];
const auto z_screen =
plane_point.z() - (plane_normal.x() * (p_screen.x() - plane_point.x()) +
plane_normal.y() * (p_screen.y() - plane_point.y())) /
plane_normal.z();
const Point3d p{p_screen.x(), p_screen.y(), z_screen};
const auto v1 = points[1] - points[0];
const auto v2 = points[2] - points[1];
const auto v3 = points[0] - points[2];
const auto c1 = v1.cross(p - points[0]).normalized();
const auto c2 = v2.cross(p - points[1]).normalized();
const auto c3 = v3.cross(p - points[2]).normalized();
const auto r1 = c1.dot(c2);
const auto r2 = c1.dot(c3);
const auto r3 = c2.dot(c3);
return {r1 > 0 && r2 > 0 && r3 > 0, z_screen};
}