add very simple frustum culling.
This commit is contained in:
parent
bc0c2c8c73
commit
a30c41dc46
|
@ -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.");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue