Job description

static bool insideTriangle(double x, double y, const Vector3f* _v)

Test whether the point is inside the triangle. You can modify the definition of this function, which means that you can update the return type or function parameters in your own way.

void rst::rasterizer::rasterize_triangle(const Triangle &t)

Perform the triangle rasterization algorithm

  1. Create 2-dimensional bounding box for triangles.
  2. Walk through all pixels within this bounding Box (using its integer index). Then, use the screen space coordinates of the pixel center to check whether the center point is inside the triangle.
  3. If internally, the interpolated depth value at its position is compared with the corresponding value in the depth buffer.
  4. If the current point is closer to the camera, set the pixel color and update the depth buffer.

To solve the code

static bool insideTriangle(double x, double y, const Vector3f* _v)

Notice that the vector dot product is rotating counterclockwise.

static bool insideTriangle(double x, double y, const Vector3f* _v)
{   
    Eigen::Vector2f p;
    p << x, y;

    Eigen::Vector2f AB, BC, CA;
    AB = _v[1].head(2) - _v[0].head(2);
    BC = _v[2].head(2) - _v[1].head(2);
    CA = _v[0].head(2) - _v[2].head(2); 

    Eigen::Vector2f AP, BP, CP;
    AP = p - _v[0].head(2);
    BP = p - _v[1].head(2);
    CP = p - _v[2].head(2);
    
    return AB[0] * AP[1] - AB[1] * AP[0] > 0 
        && BC[0] * BP[1] - BC[1] * BP[0] > 0 
        && CA[0] * CP[1] - CA[1] * CP[0] > 0;
}
Copy the code

void rst::rasterizer::rasterize_triangle(const Triangle &t)

Different from the inversion of assignment 1, Assignment 2 hard core the values of the near and far planes in the framework, so it is not enough to just take the inverse of the projection transformation matrix. If the z value of the viewport transformation matrix is changed to negative in draw() function on the basis of inverse, the correction effect can be achieved. vert.z() = -vert.z() * f1 + f2;

Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
                                      float zNear, float zFar)
{
    Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();
    Eigen::Matrix4f persp2ortho(4, 4);
    Eigen::Matrix4f ortho_translate(4, 4);
    Eigen::Matrix4f ortho_scale(4, 4);

    float radian = (eye_fov / 2) * MY_PI / 180.0;

    float n= -zNear;
    float f = -zFar;

    float t = abs(tan(radian) * (n));
    float b = -t;

    float r = t * aspect_ratio;
    float l = -r;

    persp2ortho << n, 0, 0, 0,
        0, n, 0, 0,
        0, 0, n + f, -(n * f),
        0, 0, 1, 0;
    ortho_translate << 1, 0, 0, -(r + l) / 2,
        0, 1, 0, -(t + b) / 2,
        0, 0, 1, -(n + f) / 2,
        0, 0, 0, 1;
    ortho_scale << 2 / (r - l), 0, 0, 0,
        0, 2 / (t - b), 0, 0,
        0, 0, 2 / (n - f), 0,
        0, 0, 0, 1;

    projection = ortho_scale * ortho_translate * persp2ortho;
    return projection;
}
Copy the code

The output

./Rasterizer
Copy the code