在Fundamentals of Computer Graphics, 4th 的第153頁有如下描述:
Many APIs such as OpenGL (Shreiner, Neider, Woo, & Davis, 2004) use the same canonical view volume as presented here. They also usually have the user specify the absolute values of n and f . The projection matrix for OpenGL is
Other APIs send n and f to 0 and 1, respectively. Blinn (J. Blinn, 1996) recom- mends making the canonical view volume $[0, 1]^3$ for efficiency. All such decisions will change the the projection matrix slightly.
//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
auto v = t.toVector4();
// TODO : Find out the bounding box of current triangle.
// iterate through the pixel and find if the current pixel is inside the triangle
// If so, use the following code to get the interpolated z value.
//auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
//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;
// TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
}
先找到包圍盒子bounding box
在bounding box中檢測像素是否在三角形內
如果在,則
用重心座標插值得到当前三角形像素的z值
判斷z值与depth buffer的关系
z<depth buffer
設置當前像素顏色
//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
auto v = t.toVector4();
// TODO : Find out the bounding box of current triangle.
// iterate through the pixel and find if the current pixel is inside the triangle
// If so, use the following code to get the interpolated z value.
//auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
//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;
// TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
// Finding out the bounding box for the current triangle
float min_x = ceil(std::min({v[0].x(), v[1].x(), v[2].x()}));
float max_x = ceil(std::max({v[0].x(), v[1].x(), v[2].x()}));
float min_y = ceil(std::min({v[0].y(), v[1].y(), v[2].y()}));
float max_y = ceil(std::max({v[0].y(), v[1].y(), v[2].y()}));
// Iterating through each pixel in the bounding box
for (float x = min_x; x <= max_x; x++) {
for (float y = min_y; y <= max_y; y++) {
// If the pixel is inside the triangle
if (insideTriangle(x+0.5f, y+0.5f, t.v)) {
auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
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;
if (z_interpolated < depth_buf[get_index(x, y)]) {
// Set the pixel color if it should be painted
set_pixel(Eigen::Vector3f(x, y, z_interpolated), t.getColor());
depth_buf[get_index(x, y)] = z_interpolated;
}
}
}
}
}
//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
auto v = t.toVector4();
// TODO : Find out the bounding box of current triangle.
// iterate through the pixel and find if the current pixel is inside the triangle
// If so, use the following code to get the interpolated z value.
//auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
//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;
// TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
// Finding out the bounding box for the current triangle
// float min_x = std::min({v[0].x(), v[1].x(), v[2].x()});
// float max_x = std::max({v[0].x(), v[1].x(), v[2].x()});
// float min_y = std::min({v[0].y(), v[1].y(), v[2].y()});
// float max_y = std::max({v[0].y(), v[1].y(), v[2].y()});
float min_x = std::floor(std::min({v[0].x(), v[1].x(), v[2].x()}));
float max_x = std::ceil(std::max({v[0].x(), v[1].x(), v[2].x()}));
float min_y = std::floor(std::min({v[0].y(), v[1].y(), v[2].y()}));
float max_y = std::ceil(std::max({v[0].y(), v[1].y(), v[2].y()}));
bool ssaa_mode = true;
if(ssaa_mode){
// Iterating through each pixel in the bounding box
for (float x = min_x; x <= max_x; x++) {
for (float y = min_y; y <= max_y; y++) {
float min_depth = std::numeric_limits<float>::infinity();
Eigen::Vector3f color(0, 0, 0);
// Super Sampling at 2x2 grid within the pixel
for (int dx = 0; dx < 2; ++dx) {
for (int dy = 0; dy < 2; ++dy) {
float sample_x = x + dx * 0.5f;
float sample_y = y + dy * 0.5f;
// If the sample point is inside the triangle
if (insideTriangle(sample_x, sample_y, t.v)) {
auto[alpha, beta, gamma] = computeBarycentric2D(sample_x, sample_y, t.v);
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;
// Accumulate color and find minimum depth
color += t.getColor();
min_depth = std::min(min_depth, z_interpolated);
}
}
}
color /= 4.0f; // average the color
if (min_depth < depth_buf[get_index(x, y)]) {
// Set the pixel color if it should be painted
set_pixel(Eigen::Vector3f(x, y, min_depth), color);
depth_buf[get_index(x, y)] = min_depth;
}
}
}
return;
}else{
// Iterating through each pixel in the bounding box
for (float x = min_x; x <= max_x; x++) {
for (float y = min_y; y <= max_y; y++) {
// If the pixel is inside the triangle
if (insideTriangle(x, y, t.v)) {
auto [alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
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;
if (z_interpolated < depth_buf[get_index(x, y)]) {
// Set the pixel color if it should be painted
set_pixel(Eigen::Vector3f(x, y, z_interpolated), t.getColor());
depth_buf[get_index(x, y)] = z_interpolated;
}
}
}
}
}
}