// clang-format off // // Created by goksu on 4/6/19. // #include #include #include "rasterizer.hpp" #include #include rst::pos_buf_id rst::rasterizer::load_positions(const std::vector &positions) { auto id = get_next_id(); pos_buf.emplace(id, positions); return {id}; } rst::ind_buf_id rst::rasterizer::load_indices(const std::vector &indices) { auto id = get_next_id(); ind_buf.emplace(id, indices); return {id}; } rst::col_buf_id rst::rasterizer::load_colors(const std::vector &cols) { auto id = get_next_id(); col_buf.emplace(id, cols); return {id}; } auto to_vec4(const Eigen::Vector3f& v3, float w = 1.0f) { return Vector4f(v3.x(), v3.y(), v3.z(), w); } static bool insideTriangle(int x, int y, const Vector3f* _v) { //side vector Eigen::Vector2f side1; side1 << _v[0].x()-_v[1].x(),_v[0].y()-_v[1].y(); Eigen::Vector2f side2; side2 << _v[2].x()-_v[0].x(),_v[2].y()-_v[0].y(); Eigen::Vector2f side3; side3 << _v[1].x()-_v[2].x(),_v[1].y()-_v[2].y(); //vector between testPoint and vertex of triangle Eigen::Vector2f po1; po1 << x-_v[0].x(),y-_v[0].y(); Eigen::Vector2f po2; po2 << x-_v[1].x(),y-_v[1].y(); Eigen::Vector2f po3; po3 << x-_v[2].x(),y-_v[2].y(); //cross product float z1 = side1.x()*po1.y()-side1.y()*po1.x(); float z2 = side2.x()*po2.y()-side2.y()*po2.x(); float z3 = side3.x()*po3.y()-side3.y()*po3.x(); //if they have the same character,the point is inside the triangle if((z1<0 && z2<0 && z3<0 )||(z1>0 && z2>0 && z3>0)) { return true; } else { return false; } // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2] } static std::tuple computeBarycentric2D(float x, float y, const Vector3f* v) { float c1 = (x*(v[1].y() - v[2].y()) + (v[2].x() - v[1].x())*y + v[1].x()*v[2].y() - v[2].x()*v[1].y()) / (v[0].x()*(v[1].y() - v[2].y()) + (v[2].x() - v[1].x())*v[0].y() + v[1].x()*v[2].y() - v[2].x()*v[1].y()); float c2 = (x*(v[2].y() - v[0].y()) + (v[0].x() - v[2].x())*y + v[2].x()*v[0].y() - v[0].x()*v[2].y()) / (v[1].x()*(v[2].y() - v[0].y()) + (v[0].x() - v[2].x())*v[1].y() + v[2].x()*v[0].y() - v[0].x()*v[2].y()); float c3 = (x*(v[0].y() - v[1].y()) + (v[1].x() - v[0].x())*y + v[0].x()*v[1].y() - v[1].x()*v[0].y()) / (v[2].x()*(v[0].y() - v[1].y()) + (v[1].x() - v[0].x())*v[2].y() + v[0].x()*v[1].y() - v[1].x()*v[0].y()); return {c1,c2,c3}; } void rst::rasterizer::draw(pos_buf_id pos_buffer, ind_buf_id ind_buffer, col_buf_id col_buffer, Primitive type) { auto& buf = pos_buf[pos_buffer.pos_id]; auto& ind = ind_buf[ind_buffer.ind_id]; auto& col = col_buf[col_buffer.col_id]; float f1 = (50 - 0.1) / 2.0; float f2 = (50 + 0.1) / 2.0; Eigen::Matrix4f mvp = projection * view * model; for (auto& i : ind) { Triangle t; Eigen::Vector4f v[] = { mvp * to_vec4(buf[i[0]], 1.0f), mvp * to_vec4(buf[i[1]], 1.0f), mvp * to_vec4(buf[i[2]], 1.0f) }; //Homogeneous division for (auto& vec : v) { vec /= vec.w(); } //Viewport transformation for (auto & vert : v) { vert.x() = 0.5*width*(vert.x()+1.0); vert.y() = 0.5*height*(vert.y()+1.0); vert.z() = vert.z() * f1 + f2; } for (int i = 0; i < 3; ++i) { t.setVertex(i, v[i].head<3>()); t.setVertex(i, v[i].head<3>()); t.setVertex(i, v[i].head<3>()); } auto col_x = col[i[0]]; auto col_y = col[i[1]]; auto col_z = col[i[2]]; t.setColor(0, col_x[0], col_x[1], col_x[2]); t.setColor(1, col_y[0], col_y[1], col_y[2]); t.setColor(2, col_z[0], col_z[1], col_z[2]); rasterize_triangle(t); } } //Screen space rasterization void rst::rasterizer::rasterize_triangle(const Triangle& t) { auto v = t.toVector4(); //bounding box float max_x= std::max(v[0].x(),std::max(v[1].x(),v[2].x())); float min_x= std::min(v[0].x(),std::min(v[1].x(),v[2].x())); float max_y= std::max(v[0].y(),std::max(v[1].y(),v[2].y())); float min_y= std::min(v[0].y(),std::min(v[1].y(),v[2].y())); for(int x =min_x;x <= max_x;x++) { for(int y = min_y;y <= max_y;y++) { if(insideTriangle(x,y,t.v)) { //以下是计算插值的内容,暂时看不懂,先抄别人博客补全 //最小深度,默认是无穷远 float min_depth = FLT_MAX; //如果在三角形内部,计算当前深度,得到当前最小深度 auto tup = computeBarycentric2D(x, y, t.v); float alpha , beta, gamma; std::tie(alpha, beta, gamma) = tup; float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w()); float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w(); z_interpolated *= w_reciprocal; //如果x,y所在点的深度小于z-buffer的深度, if (z_interpolated::infinity()); } } rst::rasterizer::rasterizer(int w, int h) : width(w), height(h) { frame_buf.resize(w * h); depth_buf.resize(w * h); } int rst::rasterizer::get_index(int x, int y) { return (height-1-y)*width + x; } void rst::rasterizer::set_pixel(const Eigen::Vector3f& point, const Eigen::Vector3f& color) { //old index: auto ind = point.y() + point.x() * width; auto ind = (height-1-point.y())*width + point.x(); frame_buf[ind] = color; } // clang-format on