14 Eigen::Matrix<double, 3, 4> p;
19 p.col(0) = ((p.col(0).array() + 1.0) / 2.0) * frameBuffer.rows();
20 p.col(1) = ((p.col(1).array() + 1.0) / 2.0) * frameBuffer.cols();
22 int lx = std::floor(p.col(0).minCoeff());
23 int ly = std::floor(p.col(1).minCoeff());
24 int ux = std::ceil(p.col(0).maxCoeff());
25 int uy = std::ceil(p.col(1).maxCoeff());
27 lx = std::min(std::max(lx,
int(0)),
int(frameBuffer.rows() - 1));
28 ly = std::min(std::max(ly,
int(0)),
int(frameBuffer.cols() - 1));
29 ux = std::max(std::min(ux,
int(frameBuffer.rows() - 1)),
int(0));
30 uy = std::max(std::min(uy,
int(frameBuffer.cols() - 1)),
int(0));
33 A.col(0) = p.row(0).segment(0, 3);
34 A.col(1) = p.row(1).segment(0, 3);
35 A.col(2) = p.row(2).segment(0, 3);
36 A.row(2) << 1.0, 1.0, 1.0;
38 Eigen::Matrix3d Ai = A.inverse();
40 for (
unsigned i = lx; i <= ux; i++)
42 for (
unsigned j = ly; j <= uy; j++)
45 Eigen::Vector3d pixel(i + 0.5, j + 0.5, 1);
46 Eigen::Vector3d b = Ai * pixel;
47 if (b.minCoeff() >= 0)
54 frameBuffer(i, j) = program.
BlendingShader(frag, frameBuffer(i, j));
61 void rasterize_triangles(
const Program &program,
const UniformAttributes &uniform,
const std::vector<VertexAttributes> &vertices, Eigen::Matrix<FrameBufferAttributes, Eigen::Dynamic, Eigen::Dynamic> &frameBuffer)
63 std::vector<VertexAttributes> v(vertices.size());
64 for (
unsigned i = 0; i < vertices.size(); i++)
67 for (
unsigned i = 0; i < vertices.size() / 3; i++)
68 rasterize_triangle(program, uniform, v[i * 3 + 0], v[i * 3 + 1], v[i * 3 + 2], frameBuffer);
73 Eigen::Matrix<double, 2, 4> p;
77 p.col(0) = ((p.col(0).array() + 1.0) / 2.0) * frameBuffer.rows();
78 p.col(1) = ((p.col(1).array() + 1.0) / 2.0) * frameBuffer.cols();
80 int lx = std::floor(p.col(0).minCoeff() - line_thickness);
81 int ly = std::floor(p.col(1).minCoeff() - line_thickness);
82 int ux = std::ceil(p.col(0).maxCoeff() + line_thickness);
83 int uy = std::ceil(p.col(1).maxCoeff() + line_thickness);
85 lx = std::min(std::max(lx,
int(0)),
int(frameBuffer.rows() - 1));
86 ly = std::min(std::max(ly,
int(0)),
int(frameBuffer.cols() - 1));
87 ux = std::max(std::min(ux,
int(frameBuffer.rows() - 1)),
int(0));
88 uy = std::max(std::min(uy,
int(frameBuffer.cols() - 1)),
int(0));
90 Eigen::Vector2f l1(p(0, 0), p(0, 1));
91 Eigen::Vector2f l2(p(1, 0), p(1, 1));
94 double ll = (l1 - l2).squaredNorm();
96 for (
unsigned i = lx; i <= ux; i++)
98 for (
unsigned j = ly; j <= uy; j++)
101 Eigen::Vector2f pixel(i + 0.5, j + 0.5);
107 t = (pixel - l1).dot(l2 - l1) / ll;
108 t = std::fmax(0, std::fmin(1, t));
111 Eigen::Vector2f pixel_p = l1 + t * (l2 - l1);
113 if ((pixel - pixel_p).squaredNorm() < (line_thickness * line_thickness))
117 frameBuffer(i, j) = program.
BlendingShader(frag, frameBuffer(i, j));
123 void rasterize_lines(
const Program &program,
const UniformAttributes &uniform,
const std::vector<VertexAttributes> &vertices,
double line_thickness, Eigen::Matrix<FrameBufferAttributes, Eigen::Dynamic, Eigen::Dynamic> &frameBuffer)
125 std::vector<VertexAttributes> v(vertices.size());
126 for (
unsigned i = 0; i < vertices.size(); i++)
129 for (
unsigned i = 0; i < vertices.size() / 2; i++)
130 rasterize_line(program, uniform, v[i * 2 + 0], v[i * 2 + 1], line_thickness, frameBuffer);
133 void framebuffer_to_uint8(
const Eigen::Matrix<FrameBufferAttributes, Eigen::Dynamic, Eigen::Dynamic> &frameBuffer, std::vector<uint8_t> &image)
135 const int w = frameBuffer.rows();
136 const int h = frameBuffer.cols();
138 const int stride_in_bytes = w * comp;
139 image.resize(w * h * comp, 0);
141 for (
unsigned wi = 0; wi < w; ++wi)
143 for (
unsigned hi = 0; hi < h; ++hi)
145 unsigned hif = h - 1 - hi;
146 image[(hi * w * 4) + (wi * 4) + 0] = frameBuffer(wi, hif).color[0];
147 image[(hi * w * 4) + (wi * 4) + 1] = frameBuffer(wi, hif).color[1];
148 image[(hi * w * 4) + (wi * 4) + 2] = frameBuffer(wi, hif).color[2];
149 image[(hi * w * 4) + (wi * 4) + 3] = frameBuffer(wi, hif).color[3];
155 std::vector<uint8_t>
render(
const Eigen::MatrixXd &vertices,
const Eigen::MatrixXi &
faces,
const Eigen::MatrixXi &faces_id,
156 int width,
int height,
157 const Eigen::Vector3d &camera_position,
const double camera_fov,
const double camera_near,
const double camera_far,
const bool is_perspective,
const Eigen::Vector3d &lookat,
const Eigen::Vector3d &up,
158 const Eigen::Vector3d &ambient_light,
const std::vector<std::pair<Eigen::MatrixXd, Eigen::MatrixXd>> &lights,
159 std::vector<Material> &materials)
161 using namespace renderer;
162 using namespace Eigen;
164 Eigen::Matrix<FrameBufferAttributes, Eigen::Dynamic, Eigen::Dynamic> frameBuffer(width, height);
167 const Vector3d gaze = lookat - camera_position;
168 const Vector3d w = -gaze.normalized();
169 const Vector3d u = up.cross(w).normalized();
170 const Vector3d v = w.cross(u);
173 M_cam_inv << u(0), v(0), w(0), camera_position(0),
174 u(1), v(1), w(1), camera_position(1),
175 u(2), v(2), w(2), camera_position(2),
178 uniform.
M_cam = M_cam_inv.inverse();
181 const double camera_ar = double(width) / height;
182 const double tan_angle = tan(camera_fov / 2);
183 const double n = -camera_near;
184 const double f = -camera_far;
185 const double t = tan_angle * n;
187 const double r = t * camera_ar;
190 uniform.
M_orth << 2 / (r - l), 0, 0, -(r + l) / (r - l),
191 0, 2 / (t - b), 0, -(t + b) / (t - b),
192 0, 0, 2 / (n - f), -(n + f) / (n - f),
204 P << 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1;
214 Vector3d color = ambient_light;
217 for (
const auto &l : lights)
219 Vector3d Li = (l.first - hit).normalized();
225 H = (Li + (camera_position - hit).normalized()).normalized();
229 H = (Li - gaze.normalized()).normalized();
232 const Vector3d D = l.first - hit;
233 color += (diffuse + specular).cwiseProduct(l.second) / D.squaredNorm();
246 if (fa.
depth < previous.depth)
258 Eigen::MatrixXd vnormals;
259 igl::per_vertex_normals(vertices,
faces, vnormals);
260 const Material material = materials.front();
262 std::vector<VertexAttributes> vertex_attributes;
263 for (
int i = 0; i <
faces.rows(); ++i)
265 const auto &mat = faces_id.size() <= 0 ? material : materials[faces_id(i)];
266 for (
int j = 0; j < 3; j++)
268 int vid =
faces(i, j);
271 va.
normal = vnormals.row(vid).normalized();
272 vertex_attributes.push_back(va);
276 rasterize_triangles(program, uniform, vertex_attributes, frameBuffer);
278 std::vector<uint8_t> image;
279 framebuffer_to_uint8(frameBuffer, image);