GAMES101作業解答-作業02-Triangles and Z-buffering


GAMES101作業解答-作業02-Triangles and Z-buffering

1. 題目要求

  • 在屏幕上畫出一個實心三角形, 換言之,柵格化一個三角形。上一次作業中,在視口變化之后,我們調用了函數 rasterize_wireframe(const Triangle& t)。但這一次,你需要自己填寫並調用 函數 rasterize_triangle(const Triangle& t)。
  • 該函數的內部工作流程如下:
    1. 創建三角形的 2 維 bounding box。
    1. 遍歷此 bounding box 內的所有像素(使用其整數索引)。然后,使用像素中 心的屏幕空間坐標來檢查中心點是否在三角形內。
    1. 如果在內部,則將其位置處的插值深度值 (interpolated depth value) 與深度 緩沖區 (depth buffer) 中的相應值進行比較。
    1. 如果當前點更靠近相機,請設置像素顏色並更新深度緩沖區 (depth buffer)。
      我們需要修改的函數如下:
      • rasterize_triangle(): 執行三角形柵格化算法
      • static bool insideTriangle(): 測試點是否在三角形內。你可以修改此函 數的定義,這意味着,你可以按照自己的方式更新返回類型或函數參數。
      因為我們只知道三角形三個頂點處的深度值,所以對於三角形內部的像素, 我們需要用插值的方法得到其深度值。我們已經為你處理好了這一部分,因為有 關這方面的內容尚未在課程中涉及。插值的深度值被儲存在變量 z_interpolated 中。

2. 作業解答

  • 所需的實驗環境前面已經介紹了,這些題目都是基於前面的基礎或者框架,為了進一步實現各種復雜功能,我們需要理解作業意圖以及看閆老師的pdf文件和視頻,同時要完成作業需要去查閱一些網上資料。
  • 本次作業主要目的是實現三角形的光柵化以及實現Z-buffer算法對三角形的遮擋。
  • 關鍵部分的代碼如下所示:
// Screen space rasterization 屏幕空間光柵化
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();
    // 畫出三角形所在邊界
    // x_l = x_min ; x_r = x_max ; y_b = y_min ; y_t = y_max
    int x_l = std::floor(std::min(v[0][0], std::min(v[1][0], v[2][0])));   //floor向下取整
    int x_r = std::ceil(std::max(v[0][0], std::max(v[1][0], v[2][0])));    //ceil向上取整
    int y_b = std::floor(std::min(v[0][1], std::min(v[1][1], v[2][1])));
    int y_t = std::ceil(std::max(v[0][1], std::max(v[1][1], v[2][1])));

    for (int x = x_l; x <= x_r; x++)
        for (int y = y_b; y <= y_t; y++) {

            if (insideTriangle(x + 0.5, y + 0.5, t.v)) {
                auto[alpha, beta, gamma] = computeBarycentric2D((float) x + 0.5f, (float) y + 0.5f, t.v);  //重心坐標插值
                float w_reciprocal = 1.0f / (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 (depth_buf[get_index(x, y)] > z_interpolated) {
                    Vector3f color = t.getColor();
                    Vector3f point(3);
                    point << (float) x, (float) y, z_interpolated;
                    depth_buf[get_index(x, y)] = z_interpolated;
                    set_pixel(point, color);
                }
            }
        }
}
]// 利用叉乘以及右手定則判斷是否在三角形內部方法
static bool insideTriangle(int x, int y, const Vector3f* _v)
{
    Vector2f point(x, y);

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

    Vector2f AP = point - _v[0].head(2);
    Vector2f BP = point - _v[1].head(2);
    Vector2f CP = point - _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;

}
  • 實驗結果

    與實驗文檔中的圖是反的,這個坐標系的選取問題,不影響結果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM