add very simple frustum culling.

This commit is contained in:
tianlei.richard 2024-04-03 17:50:32 +08:00
parent bc0c2c8c73
commit a30c41dc46
5 changed files with 54 additions and 33 deletions

View File

@ -15,7 +15,7 @@
#include "minus_renderer.h"
int main(int argc, char *argv[]) {
spdlog::set_level(spdlog::level::trace);
spdlog::set_level(spdlog::level::debug);
cxxopts::Options options("Minus Renderer",
"A minus soft rasterize renderer.");

View File

@ -132,6 +132,43 @@ void MinusRenderer::view_transform(const TransformMatrix &mtx) {
}
}
cv::Vec3b MinusRenderer::fragment_shader(const RasterizerResult &fragment,
const Point3d &position,
const Mesh &mesh) {
const auto &triangle = mesh.get_primitive(fragment.triangle.triangle_index);
const auto &[alpha, beta, gamma] =
calculate_barycentric_coordinate(triangle, position);
cv::Vec3b res{0, 0, 0};
if (alpha >= 0. && alpha <= 1. && beta >= 0. && beta <= 1. && gamma >= 0. &&
gamma <= 1.) {
std::vector<Point2d> triangle_uv;
std::vector<Point3d> triangle_normal;
for (const auto vertex_index : triangle.get_vertex_index()) {
triangle_uv.push_back(mesh.get_texture_coordinate(vertex_index));
triangle_normal.push_back(mesh.get_normal_vector(vertex_index));
}
Point2d uv{alpha * triangle_uv[0].x() + beta * triangle_uv[1].x() +
gamma * triangle_uv[2].x(),
alpha * triangle_uv[0].y() + beta * triangle_uv[1].y() +
gamma * triangle_uv[2].y()};
const auto &normal =
-1. *
Point3d(alpha * triangle_normal[0].x() + beta * triangle_normal[1].x() +
gamma * triangle_normal[2].x(),
alpha * triangle_normal[0].y() + beta * triangle_normal[1].y() +
gamma * triangle_normal[2].y(),
alpha * triangle_normal[0].z() + beta * triangle_normal[1].z() +
gamma * triangle_normal[2].z())
.normalized();
const auto &material = mesh.get_material();
res = material->shade(Vertex{position, normal, uv}, Point3d{}, lamps_);
}
return res;
}
cv::Mat MinusRenderer::render(const int resolution_width,
const int resolution_height) {
spdlog::trace("Tick once.");
@ -146,8 +183,11 @@ cv::Mat MinusRenderer::render(const int resolution_width,
++mesh_index) {
auto primitives = (meshes_[mesh_index]).get_primitives();
for (auto &t : primitives) {
const auto [z_min, z_max] = t.get_depth_range();
if (z_max >= far_ && z_min <= near_) {
t.set_points(apply_transform(ss_transform, t.get_vertex_position()));
}
}
rasterizer_->rasterize(mesh_index, primitives);
}
@ -166,42 +206,13 @@ cv::Mat MinusRenderer::render(const int resolution_width,
if (fragment.triangle.mesh_index >= 0 &&
fragment.triangle.mesh_index < meshes_.size()) {
const auto &mesh = meshes_[fragment.triangle.mesh_index];
if (fragment.depth > -std::numeric_limits<double>::infinity()) {
if (fragment.depth <= 1. && fragment.depth >= -1.) {
const Point3d &position =
(inv_ss_transform *
(Point3d{x + 0.5, y + 0.5, fragment.depth}.homogeneous()))
.hnormalized();
const auto &triangle =
mesh.get_primitive(fragment.triangle.triangle_index);
const auto &[alpha, beta, gamma] =
calculate_barycentric_coordinate(triangle, position);
std::vector<Point2d> triangle_uv;
std::vector<Point3d> triangle_normal;
for (const auto vertex_index : triangle.get_vertex_index()) {
triangle_uv.push_back(mesh.get_texture_coordinate(vertex_index));
triangle_normal.push_back(mesh.get_normal_vector(vertex_index));
}
Point2d uv{alpha * triangle_uv[0].x() + beta * triangle_uv[1].x() +
gamma * triangle_uv[2].x(),
alpha * triangle_uv[0].y() + beta * triangle_uv[1].y() +
gamma * triangle_uv[2].y()};
const auto &normal = -1. * Point3d(alpha * triangle_normal[0].x() +
beta * triangle_normal[1].x() +
gamma * triangle_normal[2].x(),
alpha * triangle_normal[0].y() +
beta * triangle_normal[1].y() +
gamma * triangle_normal[2].y(),
alpha * triangle_normal[0].z() +
beta * triangle_normal[1].z() +
gamma * triangle_normal[2].z())
.normalized();
const auto &material = mesh.get_material();
pixel_color =
material->shade(Vertex{position, normal, uv}, Point3d{}, lamps_);
pixel_color = fragment_shader(fragment, position, mesh);
}
}
}

View File

@ -34,6 +34,10 @@ private:
construct_transform(const int resolution_width,
const int resolution_height) const;
private:
cv::Vec3b fragment_shader(const RasterizerResult &fragment,
const Point3d &position, const Mesh &mesh);
private:
float near_;
float far_;

View File

@ -45,6 +45,11 @@ BBox Triangle::axis_align_bbox() const {
return BBox{x_min, y_min, (x_max - x_min + 1), (y_max - y_min + 1)};
}
std::pair<double, double> Triangle::get_depth_range() const {
return {std::min({vertices_[0].z(), vertices_[1].z(), vertices_[2].z()}),
std::max({vertices_[0].z(), vertices_[1].z(), vertices_[2].z()})};
}
Vector3d Triangle::unit_normal_vector() const {
return normal_vector().normalized();
}

View File

@ -21,6 +21,7 @@ public:
public:
BBox axis_align_bbox() const;
std::pair<double, double> get_depth_range() const;
Vector3d normal_vector() const;
Vector3d unit_normal_vector() const;