Games101作业2:光栅化

Assignment2

前置知识

光栅化

将数据绘制成图像(呈现到屏幕上)

采样:用某种方法(函数)对某个点给出确定的值

光栅化采样的任务:屏幕上的像素是离散的,要判断该像素是否需要绘制(该点是否在绘制的三角形中)

包围盒(Bounding Box):减少需要扫描的范围,取三角形三个点XY的最大和最小值,构建一个正方形的包围盒

走样

走样本质:采样的频率低于信号频率,使信号与信号之间发生重叠

反走样(antialiasing):先模糊,再采样;本质是滤波使信号“变窄了”,截去了重叠的部分

MSAA(Supersampling):将一个像素分成多个小像素,每个像素独立计算是否在三角形内部,最后根据结果在大像素内取平均

code

static bool insideTriangle(int x, int y, const Vector3f* _v)
{   
 // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]
    Eigen::Vector3f OA = Vector3f(_v[0].x() - x, _v[0].y() - y,0);
    Eigen::Vector3f OB = Vector3f(_v[1].x() - x, _v[1].y() - y,0);
    Eigen::Vector3f OC = Vector3f(_v[2].x() - x, _v[2].y() - y,0);
	//  若三条边两两叉积方向一致,则在三角形内
    auto a = OA.cross(OB);
    auto b = OB.cross(OC);
    auto c = OC.cross(OA);
    return (a.dot(b) > 0 && b.dot(c) > 0);
}

//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

    //  取三角形三个点XY的最大和最小值,构建一个正方形的包围盒
    float BoxRight = std::max({t.v[0].x(), t.v[1].x(), t.v[2].x()});
    float BoxLeft = std::min({t.v[0].x(), t.v[1].x(), t.v[2].x()});
    float BoxBottom = std::max({t.v[0].y(), t.v[1].y(), t.v[2].y()});
    float BoxTop = std::min({t.v[0].y(), t.v[1].y(), t.v[2].y()});

    //  打包成lambda,方便实现MSAA
    auto fun = [&](float x, float y, int& count) -> float{
		x = (int)x + 0.5f;
		y = (int)y + 0.5f;
        //  比较深度值
        // 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.
		float& z_depth = rasterizer::depth_buf[get_index(x, y)];
        if (z_interpolated < z_depth)
        {            
            //z_depth = z_interpolated;
            //set_pixel(Vector3f(x, y, 0), t.getColor());
            ++count;
            return z_interpolated;
        }
        else
            return z_depth;
    };

    //  遍历包围盒中像素,判断像素是否在三角形内部
    for (int x = BoxLeft; x < BoxRight; ++x)
        for (int y = BoxTop; y < BoxBottom; ++y)
        {
            int count = 0;
            float z = 0;
            if (insideTriangle(x + 0.25f, y + 0.25f, t.v))
                z = std::max(0.0f, fun(x + 0.25f, y + 0.25f, count));
			if (insideTriangle(x + 0.75f, y + 0.25f, t.v))
                z = std::max(0.0f, fun(x + 0.75f, y + 0.25f, count));
			if (insideTriangle(x + 0.25f, y + 0.75f, t.v))
                z = std::max(0.0f, fun(x + 0.25f, y + 0.75f, count));
			if (insideTriangle(x + 0.75f, y + 0.75f, t.v))
                z = std::max(0.0f, fun(x + 0.75f, y + 0.75f, count));
            if (count)
            {
                set_pixel(Vector3f(x, y, 0), t.getColor() * count / 4.0f);
                if (z)
                    rasterizer::depth_buf[get_index(x, y)] = z;
            }
		}
}

注意事项

判断点是否在三角形中

将三角形三个点分别命名为ABC,设点O,连接OA、OB、OC,判断OA和OB、OB和OC、OC和OA两两叉乘方向是否一致,若一致,则点在三角形内

实现MSAA时,同一像素中每个样本点如何共用同一个深度值

如果每个样本点都需维护自己的深度值的话,整个depth buffer就是原来4倍,空间消耗大。于是我先将x和y取整成x+0.5、y+0.5f(和原来一样),如果样本点中至少有一个点需要绘制(在三角形中且离相机更近),则将该样本点的深度值作为整个点的深度值

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值