add very simple frustum culling.
This commit is contained in:
parent
bc0c2c8c73
commit
a30c41dc46
|
@ -15,7 +15,7 @@
|
||||||
#include "minus_renderer.h"
|
#include "minus_renderer.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
spdlog::set_level(spdlog::level::trace);
|
spdlog::set_level(spdlog::level::debug);
|
||||||
|
|
||||||
cxxopts::Options options("Minus Renderer",
|
cxxopts::Options options("Minus Renderer",
|
||||||
"A minus soft rasterize 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,
|
cv::Mat MinusRenderer::render(const int resolution_width,
|
||||||
const int resolution_height) {
|
const int resolution_height) {
|
||||||
spdlog::trace("Tick once.");
|
spdlog::trace("Tick once.");
|
||||||
|
@ -146,8 +183,11 @@ cv::Mat MinusRenderer::render(const int resolution_width,
|
||||||
++mesh_index) {
|
++mesh_index) {
|
||||||
auto primitives = (meshes_[mesh_index]).get_primitives();
|
auto primitives = (meshes_[mesh_index]).get_primitives();
|
||||||
for (auto &t : 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()));
|
t.set_points(apply_transform(ss_transform, t.get_vertex_position()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
rasterizer_->rasterize(mesh_index, primitives);
|
rasterizer_->rasterize(mesh_index, primitives);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,42 +206,13 @@ cv::Mat MinusRenderer::render(const int resolution_width,
|
||||||
if (fragment.triangle.mesh_index >= 0 &&
|
if (fragment.triangle.mesh_index >= 0 &&
|
||||||
fragment.triangle.mesh_index < meshes_.size()) {
|
fragment.triangle.mesh_index < meshes_.size()) {
|
||||||
const auto &mesh = meshes_[fragment.triangle.mesh_index];
|
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 =
|
const Point3d &position =
|
||||||
(inv_ss_transform *
|
(inv_ss_transform *
|
||||||
(Point3d{x + 0.5, y + 0.5, fragment.depth}.homogeneous()))
|
(Point3d{x + 0.5, y + 0.5, fragment.depth}.homogeneous()))
|
||||||
.hnormalized();
|
.hnormalized();
|
||||||
|
|
||||||
const auto &triangle =
|
pixel_color = fragment_shader(fragment, position, mesh);
|
||||||
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_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,10 @@ private:
|
||||||
construct_transform(const int resolution_width,
|
construct_transform(const int resolution_width,
|
||||||
const int resolution_height) const;
|
const int resolution_height) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
cv::Vec3b fragment_shader(const RasterizerResult &fragment,
|
||||||
|
const Point3d &position, const Mesh &mesh);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float near_;
|
float near_;
|
||||||
float far_;
|
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)};
|
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 {
|
Vector3d Triangle::unit_normal_vector() const {
|
||||||
return normal_vector().normalized();
|
return normal_vector().normalized();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BBox axis_align_bbox() const;
|
BBox axis_align_bbox() const;
|
||||||
|
std::pair<double, double> get_depth_range() const;
|
||||||
Vector3d normal_vector() const;
|
Vector3d normal_vector() const;
|
||||||
Vector3d unit_normal_vector() const;
|
Vector3d unit_normal_vector() const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue